Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 4 of 4
  1. #1
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Passing Data Between JS & PHP

    I've searched google far and wide (but maybe not with the right params?) but I have run out of options to try to accomplish my seemingly simple task.

    My problem is I need to pass a multidimensional array between JS and PHP. I have successfully transfered my PHP array into JS, but I am unable to reverse the transaction without knowing all of the fields on the JS array.

    This may seem like a PHP question (since I talk about it alot) but the problem I'm having is going from Javascript to PHP. I felt this was more of a Javascript question than a PHP question... but its debatable.

    Here is some background information regarding the "why the heck are you doing this". I have a very ajax-i-fied page that I'm using to generate reports from. I am going to have many, many different options that will affect how the data is filtered / sorted / displayed on this report. Due to the amount of options, and attempting to reduce the number of tables and fields in my database, the method I chose to accomplish this is to store everything in a multi-dimensional array, serialize it, then base64 encode it, and then save that into a field in my database (yes, its a huuuuge field). Sounds complicated, but it works beautiful as far as PHP is concerned.

    So the order of events when a report is called up is this:

    1. Select report record from database (including the huge string)
    2. Decode/unserialize the string into my multi-dimensional array.
    3. Read out all the options on the page (using a foreach loop via PHP) to set the initial values of the report options and all that good stuff.


    After the initial page load, I'm currently maintaining that ginormous saved settings string whenever someone makes a change. Which means i decode/unserialize, make my change, then serialize/encode and then save it back to a hidden input. The reason I'm going through this painstaking process is so I have one variable I need to be concerned with when saving information. Also, it allows me to store more than just a name and a value that a hidden input would limit me to. That way I don't 1. miss any info or 2. have to change 10 different spots to add a new saved setting, just append the array and I'm done as far as preserving the information goes.

    A different process (this is what I'm trying to do now) is to restore the array from the DB using PHP (same as I'm doing now), put it into a Javascript array, and manipulate this JS array while the user is modifying the report. No PHP is involved after the initial load. Then, if the user wants to save this report, pull the array back out of JS, serialize / encode it using PHP and put it back into the database. I've successfully completed this, except for the last part of getting the array out of javascript and into PHP. I can't find a JS serialize method that is fully compatible with PHP unserialize(). Every function I've found says that there's a bug with multi-byte characters. Javascript handles them fine, but PHP blows up on them. So I'm trying to find a work-around.

    Any ideas?

    One idea I'm currently exploring is converting the JS array into XML, then parse the XML into a PHP array, and bam I've got it. I think this might work, but it's still a work in progress. If I get that working I'll post back here on exactly what I did to make it work.

    I hope this post makes sense. Thanks for reading and thanks in advance for any replies!

  • #2
    Senior Coder nikkiH's Avatar
    Join Date
    Jun 2005
    Location
    Near Chicago, IL, USA
    Posts
    1,973
    Thanks
    1
    Thanked 32 Times in 31 Posts
    Why not just store it all as xml from the beginning? XML is much more portable, and you can use DOM methods.

    PHP can serialize to xml if you use pear.
    http://pear.php.net/package/XML_Serializer

    If this post contains any code, I may or may not have tested it. It's probably just example code, so no getting knickers in a bunch over a typo, OK? If it doesn't have basic error checking in it, such as object detection or checking if objects are null before using them, put that in there. I'm giving examples, not typing up your whole app for you. You run code at your own risk.
    Bored? Visit
    http://www.kaelisspace.com/

  • #3
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I haven't worked with XML directly much. My first big question is does XML let me update variables (on the client side) using AJAX? For example, if someone changes the title, is there a method to allow me to update those XML values?

    Currently I'm displaying those values on the screen and also saving them into the saved string. The reason I wanted to switch to JS was so I could update the variables on the fly using the prototype notation, for example: $('title').value = "New Title".

    As long as I can directly address the variables in XML, then it would probably make sense to go straight to XML. Can you verify this?

  • #4
    New to the CF scene
    Join Date
    Aug 2007
    Posts
    3
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I found the solution! After a few days of research (and an updated version of PHP), I figured it out!

    Grab a cup of coffee, a dew, (or if its after hours, a beer) because this is gonna be a long one.

    The overall goal is to pass a multidimensional PHP array to Javascript, manipulate that JS array using AJAX (or other JS methods), then transfer that JS array back to PHP in a usable format.

    Disclaimer: Most of the code found in this post is NOT a creation of my own. I have merely chained together the right sequence of this code to get the desired results and I am merely posting them here to share my solution with everyone.

    So the first step is to take a PHP array and get it into javascript. The method I chose is to use a PHP function called arrayToJS I found on the web to generate a PHP string that I put between script tags and then echoed in the body of my file. I'm sure there are different methods than the one I chose, but this is what worked for me.

    PHP Code:
    function arrayToJS($array$baseName){
       
    //Write out the initial array definition
       
    $jsArray $baseName " = new Hash(); \r\n ";

       
    //Reset the array loop pointer
       
    reset ($array);

       
    //Use list() and each() to loop over each key/value
       //pair of the array
       
    while (list($key$value) = each($array)) {
          if (
    is_numeric($key)) {
             
    //A numeric key, so output as usual
             
    $outKey "[" $key "]";
          } else {
             
    //A string key, so output as a string
             
    $outKey "['" $key "']";
          }
          
          if (
    is_array($value)) {
             
    //The value is another array, so simply call
             //another instance of this function to handle it
             
    $jsArray .= arrayToJS($value$baseName $outKey);
          } else {

             
    //Output the key declaration
             
    $jsArray .= $baseName $outKey " = ";

             
    //Now output the value
             
    if (is_string($value)) {
                
    //Output as a string, as we did before       
                
    $jsArray .= "'" $value "'; \r\n ";
             } else if (
    $value === false) {
                
    //Explicitly output false
                
    $jsArray .= "false; \r\n";
             } else if (
    $value === NULL) {
                
    //Explicitly output null
                
    $jsArray .= "null; \r\n";
             } else if (
    $value === true) {
                
    //Explicitly output true
               
    $jsArray .= "true; \r\n";
             } else {
                
    //Output the value directly otherwise
                
    $jsArray .= $value "; \r\n";
             }
          }
       }
       
       return 
    $jsArray;

    Note: This function doesn't actually create a JS ARRAY, but rather it creates a JS HASH. You can modify that in the second line of that function depending on if you need to address keys using numbers or if you want to address keys using names (index or associative, respectively). If you want to address it using index, change Hash() to Array().

    Now that the PHP array is in JS (as an array or hash), you can manipulate it however you want using javascript. Party!


    Up until now, it was smooth sailing for me. The next hurdle was getting the array out of javascript and into PHP so it could be stored back into the database.

    I tried many different serialize functions to put the array into a string, then base64 encoded it, then posted it to a PHP script. However, no matter what I tried, I was unable to successfully unserialize the array into PHP. The PHP function unserialize kept returning a false value. I gave up on this due to a lack of alternative functions to try. This method might work for a different application, but it wouldn't work for the data I was using.

    The one that finally worked was converting the JS array to a JSON format, base64 encode it, post it to a PHP page, base64 decode it, json_decode it, run get_object_vars recursively, and I have my JS array transfered to PHP. Simple, right? Here's the details on how to do this.

    The javascript prototype library, http://prototypejs.org has some functions for both Arrays and Hashs that will convert the entire array to JSON (JavaScript Object Notation) format. That covers the JSON conversion for Javascript.

    Next, you need to perform a base64 encode on that JSON string. I found a script online at: http://www.webtoolkit.info

    Code:
    /**
    *
    *  Base64 encode / decode
    *  http://www.webtoolkit.info/
    *
    **/
    
    var Base64 = {
    
    	// private property
    	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    
    	// public method for encoding
    	encode : function (input) {
    		var output = "";
    		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    		var i = 0;
    
    		input = Base64._utf8_encode(input);
    
    		while (i < input.length) {
    
    			chr1 = input.charCodeAt(i++);
    			chr2 = input.charCodeAt(i++);
    			chr3 = input.charCodeAt(i++);
    
    			enc1 = chr1 >> 2;
    			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
    			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
    			enc4 = chr3 & 63;
    
    			if (isNaN(chr2)) {
    				enc3 = enc4 = 64;
    			} else if (isNaN(chr3)) {
    				enc4 = 64;
    			}
    
    			output = output +
    			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
    			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
    
    		}
    
    		return output;
    	},
    
    	// public method for decoding
    	decode : function (input) {
    		var output = "";
    		var chr1, chr2, chr3;
    		var enc1, enc2, enc3, enc4;
    		var i = 0;
    
    		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    
    		while (i < input.length) {
    
    			enc1 = this._keyStr.indexOf(input.charAt(i++));
    			enc2 = this._keyStr.indexOf(input.charAt(i++));
    			enc3 = this._keyStr.indexOf(input.charAt(i++));
    			enc4 = this._keyStr.indexOf(input.charAt(i++));
    
    			chr1 = (enc1 << 2) | (enc2 >> 4);
    			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
    			chr3 = ((enc3 & 3) << 6) | enc4;
    
    			output = output + String.fromCharCode(chr1);
    
    			if (enc3 != 64) {
    				output = output + String.fromCharCode(chr2);
    			}
    			if (enc4 != 64) {
    				output = output + String.fromCharCode(chr3);
    			}
    
    		}
    
    		output = Base64._utf8_decode(output);
    
    		return output;
    
    	},
    
    	// private method for UTF-8 encoding
    	_utf8_encode : function (string) {
    		string = string.replace(/\r\n/g,"\n");
    		var utftext = "";
    
    		for (var n = 0; n < string.length; n++) {
    
    			var c = string.charCodeAt(n);
    
    			if (c < 128) {
    				utftext += String.fromCharCode(c);
    			}
    			else if((c > 127) && (c < 2048)) {
    				utftext += String.fromCharCode((c >> 6) | 192);
    				utftext += String.fromCharCode((c & 63) | 128);
    			}
    			else {
    				utftext += String.fromCharCode((c >> 12) | 224);
    				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
    				utftext += String.fromCharCode((c & 63) | 128);
    			}
    
    		}
    
    		return utftext;
    	},
    
    	// private method for UTF-8 decoding
    	_utf8_decode : function (utftext) {
    		var string = "";
    		var i = 0;
    		var c = c1 = c2 = 0;
    
    		while ( i < utftext.length ) {
    
    			c = utftext.charCodeAt(i);
    
    			if (c < 128) {
    				string += String.fromCharCode(c);
    				i++;
    			}
    			else if((c > 191) && (c < 224)) {
    				c2 = utftext.charCodeAt(i+1);
    				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
    				i += 2;
    			}
    			else {
    				c2 = utftext.charCodeAt(i+1);
    				c3 = utftext.charCodeAt(i+2);
    				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
    				i += 3;
    			}
    
    		}
    
    		return string;
    	}
    
    }
    The next step is to post that base64 encoded JSON string to a PHP page. You can do this using a hidden input in a HTML form, AJAX, or if you have another method more power to you. The page I'm working on is AJAX driven, so I chose AJAX. I'm not going to cover that here since this isn't a tutorial how to do AJAX. But just understand that you need to post this string to the next page.

    Now the string has left JS land and is now in the capable hands of PHP. The first step is to pull the variable out of the POST vars (however you do that), and run the PHP function base64_decode on that data. You now have a perfectly good JSON string.

    The next step is to convert that JSON string into something usable in PHP.

    Yesterday, I ran across two PHP functions, json_encode and json_decode. (available in PHP version 5.2 or later) These functions will encode a PHP array into JSON format or decode a string from JSON format.

    After I upgraded our version of PHP to 5.2.3, I got these functions to work and I thought I was good to go. After trying to foreach through what I thought was an array, I discovered an error in my error log: "PHP Catchable fatal error: Object of class stdClass could not be converted to string"

    I did a print_r on the output of json_decode and came across a small problem. Where I was expecting "Array" it said "stdClass Object". I searched on google real quick, found out that I can run get_object_vars and it should convert it back into a format I can use, which in my case was an array.

    This worked fine... for the first dimension. So my buddy hooked me up with a link to: http://us3.php.net/manual/en/functio...bject-vars.php and the one of the user comments is a recursive function to convert all elements:

    PHP Code:
    function conv_obj($Data){
         if(
    is_object($Data)){
             foreach(
    get_object_vars($Data) as $key=>$val){
                 if(
    is_object($val)){
                     
    $ret[$key]=conv_obj($val);
                 }else{
                     
    $ret[$key]=$val;
                 }
             }
             return 
    $ret;
         }elseif(
    is_array($Data)){
             foreach(
    $Data as $key=>$val){
                 if(
    is_object($val)){
                     
    $ret[$key]=conv_obj($val);
                 }else{
                     
    $ret[$key]=$val;
                 }
             }
             return 
    $ret;
         }else{
             return 
    $Data;
         }
     } 
    This function will loop recursively through the entire object and return to you a perfectly usable PHP array. Now you can have your way with it in PHP.

    I hope this helps someone!
    Last edited by Firemouth; 08-22-2007 at 04:57 PM. Reason: Added color to clearly show the final solution


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •