I have a javascript that formats an HTML table that takes some parameters to configure it. I also have a reports table in mysql that contains definitions of my reports: a field for the report name, description, sql, footer, permissions, report status and some report specific parameters. I build up the parameters as an array so that I can set defaults that can then be overwritten by other processes before being passed to a process that turns that array into the javascript parameters.
We use PHP to build reports based on the information in the table and it merges an array of "default parameters" with an array of "report specific parameters" . Before we put the report definitions into a database there was a function for each report that used array_merge that merged the default parameters array and the report specific parameter array.
eg
$defaultparameters = array (
'base_path' => "'/inc/plugin/'",
'btn_reset' => "'true'",
'enable_default_theme' => "'true'");
$thisReportParameters = array (
'extensions' => "[{ name: 'sort', types: ['String', 'String', 'String','String', 'String','String', 'Number']},'col_2'=> "'multiple'",'col_3'=> "'select'");
$parameters = array_merge ($defaultparameters,$thisReportParameters);
This array is then passed to a function that builds the javascript for the page.
Now we've put all the reports into a table I'm having trouble pulling out the report specific parameters into an associative array.
The default parameters are now set in the report class as a property of the report object. I want to pull the additional report specific parameters from the database into an array to combine the two.
When I added 'col_2'=> "'multiple'",'col_3'=> "'select'" to the database and brought it back as an array it put the whole string in as element [0] in the array.
ie
Array ([0] => "'col_2'=> "'multiple'"'col_3'=> "'select'"")
as opposed to
Array([col2] =>"'multiple'",[col_3]=> "'select'")
I considered just adding the string from the DB to the end of the javascript configuration but this would not overwrite any settings that were already defined in the default settings array so I need to add it to an array first so that when it merges it overwrites the any defaults where the keys are the same.
The report specific options are many and varied in their format so I can't feasibly create a field for each.
I thought about exploding the string on , then parsing the pairs to build the array but the value can have "," in it as well so that might mess up the exploding.
There's probably a really neat way of achieving this but at the moment it escapes me...
Any suggestions welcome
C
You could serialize your arrays.
There's also an option to encode them in JSON which may be better if your DB is postgres - it has some built-in support for things like that and it would be easier to work with your data using some other language if need ever arises.
In any case, be sure to properly sanitize your data before trying to put it into the DB.
Related
I'm currently developing an API using Laravel for my project, the concept:
Retrieve JSON data from MySQL.
Receive user input from the Front-end (string).
Convert both JSON and string input into an array with similar structure. The array structure here is basically ["ObjectA", "ObjectA_quantity", "ObjectB", "ObjectB_quantity", ...].
Basically, eliminate the quantity of every object of Database's Array, based on every object that User Input's Array got. For example, if the Database's Array got ["pizza", "1", "burger", "2"], and the User Input's Array got ["pizza", "1"], the output of the method is expected to be ["burger", "2"].
The method that I developed will give inconsistent and confusing output, like for some object, it works well, for other it doesn't eliminate anything and if the User Input's Array too big (> 1 object), it also doesn't eliminate anything. I really welcome different approach or anything else that will give the expected output as above. Thank you very much
Here's the source code of the method I've develop: (method's located on: else if ($transactionGetter->type == 'return'), Line 148 and so forth)
https://github.com/andre-nk23/packme-backend/blob/master/app/Http/Controllers/API/TransactionController.php
if it's a JSON you must decode the value before access
$transactionGetter=json_decode($transactionGetter);
I come from a Javascript and Ruby background and this is baffling me. Laravel can store two different array syntaxes in my DB depending on how I handle my array serialization. In my understanding, collect() creates a true Laravel array. Why then is it storing a serialized array? Furthermore, is the {'key':'value'}syntax still an array despite having no square brackets surrounding it? It looks to me like a standard object or a hash, but if I try to do toArray() on it, it recognizes that it's already an array and throws an error. What am I misunderstanding and what is correct here?
Given a form:
edit.blade:
<select class="form-control m-bootstrap-select m_selectpicker" name="temp">
<option value={{ json_encode(array("$key"=>"$cph"), JSON_FORCE_OBJECT) }}>
</select>
The following two controllers syntaxes yield different database insertions.
PageController.php:
$page->cph_default = collect($request->temp);
$page->save();
Laravel stores an array with the following syntax in my database: ["{\"11\":\"1100\"}"]
PageController.php
$page->cph_default = json_decode($request->temp, true);
$page->save();
Laravel stores an array with the following syntax in my database: {"19": "1900"}
A PHP array with the syntax ['key' => 'value'] is called an associative array, and acts like a hash. A JSON-encoded associative array will show up as an object in JSON syntax. Examples and more info on PHP.net
Laravel's collect() function is a convenience wrapper for creating a new Collection. A Collection is not really a "true Laravel array" so much as it is an object wrapper with some convenience methods for modifying the underlying array. Think of it like a scalar object.
In your form when generating the option value, the submitted form value ($request->temp) will be a JSON-encoded string. Literally the string '{"19": "1900"}'.
Calling collect($request->temp) does no modification to that submitted data. It's simply creating a new Collection (array), containing a single string item. If you were to call toArray() on the collection, you'd see something like this:
[
0 => '{"19": "1900"}'
]
Note that this is not an associative array, it is a numeric array with a zero-based index. This array is encoded as a JSON array, not as a hash object. Hence your first result.
Calling json_decode($request->temp) is turning the string back into an associative array (hash) before saving it via Eloquent. Eloquent then calls json_encode() again internally, turning it back into the same JSON as your form's option value.
If you were to decode the form value before creating the collection, the resulting database save would look identical. You'd just have the convenience of the Collection wrapper:
$page->cph_default = collect(json_decode($request->temp, true));
$page->save();
If you're treating the column as a JSON type, you should ensure the data passed to Eloquent is NOT already encoded, or you'll get the double encoding experienced in your first example.
No Matter What is.
First If you are stroring the array into database convert to JSON FORMAT
For eg
$variable = json_encode($request->controlname);
This is the right way to store array
Into database
I am trying to return multiple arrays in one JSON object and having some difficulty with the syntax. An Android app receives updates from multiple tables, that I wish to be returned in one response.
Currently, this is how I am encoding the various result sets:
$json=json_encode(array($table1, $table2, $table3, $table4, $table5, $table6));
The data is returned in this format:
[{"table1":[{...}]},{"table2":[{...}]},...]
In the Android code, I'd like to be able to parse it as a JSONObject, from which I can then retrieve each array by name instead of parsing it as a JSONArray and retrieving each sub array by position. The JSON response would look like this instead:
{{"table1":[{...}]},{"table2":[{...}]},...}
It seems all I need to do is wrap the results arrays in an object, instead of an array on the PHP side, but although I've managed to blindly cobble together enough PHP code to get this far, I can't seem to figure out that final step.
Your last example is not valid JSON, curly braces always mean object with keys; instead you're treating it as an array. If you want an object, then add keys to the array in PHP like so:
$json=json_encode(array('a' => $table1, 'b' => $table2, 'c' => $table3));
This would then yield
{"a":{"table1":[{...}]},"b":{"table2":[{...}]},...}
Which seems to be what you want.
#Anonymous answer did the trick. Just to clarify, I had to clean up what I was doing previously, so instead of this:
$table1['table1'] =$stmt_table1->fetchAll(PDO::FETCH_ASSOC);
$table2['table2'] =$stmt_table2->fetchAll(PDO::FETCH_ASSOC);
...
$json=json_encode(array($table1, $table2, $table3, $table4, $table5, $table6));
I now have this:
$table1_results =$stmt_table1->fetchAll(PDO::FETCH_ASSOC);
$table2_results =$stmt_table2->fetchAll(PDO::FETCH_ASSOC);
...
$json=json_encode(array('table1' => $table1_results , 'table2' => $table2_results,...);
Background:
I have a class in this application I'm building whose job is:
__construct: $this->data = $this->mongoDB->collection->findOne();
Intermediate functions are employed to manipulate the data in tens of different ways each request. One manipulation could trigger one which would trigger another. This allows me to do unlimited updates to the mongo document with just one query, as long as $this->data['_id'] remains the same. This is the only place where data manipulation of this specific collection is allowed.
__destruct: $this->monboDB->collection->save($data)
Data is then read back, json_encode'd and sent to Javascript to draw the page
Intention:
I intended to delete a member of an array by looping through said array, matching a value within it, and unsetting that. Example:
foreach($this->data['documents'] as $key => $val){
if($val == $toBeDeleted){
unset($this->data['documents'][$key];
}
}
Then, this would be saved to the DB when the script finishes.
Problem:
When javascript reads back the data, rather than having ['a', 'b', 'd'], I had {'0': 'a', '1': 'b', '3': 'd'} - which can't be treated like an array and would pretty much break things.
I had this question half typed out before my a-hah! moment, so I figured I'd post my own answer to it too for future reference.
In php, an associative array and an array are all the same. You can have out of order keys, nonconsecutive keys, and almost any key that you'd like to use in calling your array member. Most, if not all, php array functions work with any array key. Objects are a totally different thing.
That being said, Javascript doesn't share the same rules for arrays. A javascript array must have consecutive keys starting at zero, otherwise it is an object. MongoDB is similar to Javascript in this way.
When php converts an object to be used in MongoDB or in Javascript, if the php array doesn't follow that rule, it becomes a Javascript object.
The problem was after unsetting an array index, it left a gap, causing nonconsecutive array keys, causing it to become an object. Simple fix would either be array_slice($array, $key, 1) or $array = array_values($array)
I have a client server scenario where the type conversion did by the SoapClient class in PHP, cannot tell wether an empty array is associative or numeric, and so defaults to numeric.
All exposed functions use basic types, no classes.
An associative array such as array("something"=>123) gets converted to a map data type. However, when the same array is empty, such as array(), it gets converted to an array on the Ruby side. Type casting to object (object)array() will result in a struct data type on the Ruby side.
The argument is a bit more complex, not as simple as above:
array(
"options"=>array(
"plans"=>array(
0=>array(
"name"=>"abc",
"product_options"=>array(
"optional_key_determines_associative_array_data_type"=>0,
),
),
),
),
);
If the array under "product_options" is empty, it gets converted to an array in Ruby, instead of a map. Once again, type casting to object in PHP results in a struct in Ruby.
What can I do on the PHP side to make empty "associative" arrays end up as maps on the Ruby side?
PHP 5.3.3, using SoapClient.
Ruby 1.8.7, Rails 2.3.2 using Action Web Service.
You can wrap your array in a SoapVar class with APACHE_MAP as encoding parameter. Like This:
array(
"options"=>array(
"plans"=>array(
0=>array(
"name"=>"abc",
"product_options"=> new SoapVar(array(), APACHE_MAP),
),
),
),
);
Well, this is exactly what I mean: To overcome that problem you will need to change the logic in your scripts - not the PHP. As you can not define a PHP array to be associative you will need to modify the receiving script.
If it was me I would not send an empty array. Put a status field into the array. This could be a field counting the available products which in this case would count 0. You will have a more meaningful communication AND the array IS suddenly associative no matter what
e.g
"product_options" => array ('products'=>0,'...'=>...) and so forth.
What I say is you will need to change the logic, you can not change PHP.
Hope that helps,
Uwe
I might be wrong here, but by my understanding:
I do believe what you are trying to achieve is not possible. An array (and we are talking array only, no objects) is an array. The structure given by the content makes an array associative or not.
An empty array is not associative.