One of the former developers in an old system I'm working on used PHP serialize() to flatten one array of data into one column of a MySQL table.
I need to write a complex query that involves this column. Is there a way to unserialize the data (even if it's into a comma separated string) within the SQL query or do I need to pass the results back to PHP?
Serialized PHP data is just a string, so for "simple" searches, you can use basic MySQL string operations.
e.g. The serialized array has a name parameter and you need to match against that, so
... WHERE LOCATE(CONCAT('s:', LENGTH('foo'), ':foo') ,serializeddatafield) > 0
which would produce
WHERE LOCATE('s:3:foo', serializeddata) > 0
But then, this would find ANY strings whose value is foo anywhere in the data, and not necessarily in the particular array field you want.
e.g. you're probably better off yanking out the whole field, deserializing in PHP, and then doing the search there. You could use the above technique to minimize the total number of strings you'd have to yank/parse, however.
Related
I want to update a Serialized value on meta_value column on mysql table.But json is hard to select from sql . How can i achieve.
a:2:{i:0;a:2:{s:19:"sevent_speaker_name";s:8:"John Doe";s:18:"sevent_speaker_img";a:1:{i:0;s:5:"72921";}}i:1;a:2:{s:19:"sevent_speaker_name";s:10:"John Smith";s:18:"sevent_speaker_img";a:1:{i:0;s:5:"72922";}}}
Here is the value. I want to replace all sevent with elevent but how can i do it?
Can I use LIKE? But first it need to be unserialized?.
This encoded information probably comes from WordPress or some other PHP framework's database; it's not JSON. Note that strings are encoded by storing the string length and the string contents:
s:19:"sevent_speaker_name"
You can use MySQL's REPLACE function to replace sevent with elevent, but you must be careful to update the length value s as well, or WordPress/PHP won't be able to read in the data.
It's possible to write a MySQL query to update the specific example given above, but it's difficult to write a query to substitutes all strings generically. Here is a tool that does the work.
I am using symfony and doctrine as my ORM.
For available types I have:
array
simple_array
json_array
I am wondering what the difference is between each of them: when do I use one or the other?
Can I have a demonstration for each of them to illustrate the differences?
I already use simple_array in some applications but I find I don't understand formType... (Or maybe I'm not using it well!? )
To illustrate my question, here is an example:
I have an Task that I have to run on specific days
So I created TaskEntity with days attribute
Days would be:
$days = array(
1=>true,
2=>true,
3=>true,
4=>true,
5=>true,
6=>false,
7=>false
);
But I have no idea which of the above types to choose ...
For your problem simple_array is the right way, the right way may also create seven boolean fields.
However here's a little vademecum:
The best way to see how a type works in doctrine is to read the code of the type, this is because there are several details that are taken for granted or are not really explained in the documentation.
So you can go into
/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php
find your type and check if its methods work as you want.
Here some details:
simple_array
in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php
return implode(',', $value);
it's just a implode()/explode() of items, stores only the values and it's useful because you can easily query the database.
array
in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ArrayType.php
return serialize($value);
calls PHP to serialize()/unserialize(), it's faster than json_array. Looking at the code I think it also works with objects. Obviously if you see the field as plain text it's uncomprensible.
json_array
in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php
return json_encode($value);
it calls json_encode()/json_decode(), if you look in the field you can see a unformatted JSON array but it's more readable than PHP's serialized object and is really more portable (JSON exists everywhere).
June 2018 update
now there is a complete and more updated documentation here
json_array is deprecated in favor of json type, it will leverage on new database features for json fields
Another consideration: The most efficient way to represent a small set of true/false values like the ones presented here would be a bitfield.
That way you're only storing one integer instead of a full string. And you avoid the encode/decode overhead.
See https://stackoverflow.com/a/5412214/827254 for a good example.
The best solution for your problem, as stated, would be to use an array mapping of type array or json_array but not simple_array. The reason is that the serialization method of simple_array is just a call to implode(',', $array) and that would retain only the values and not the keys of the array, thus invalid for your situation where you have an associative array.
However, you could also model your $days attribute as a 0-based array (i.e. monday would be zero, tuesday would be 1, etc.). In that case, it would work because the deserializing with explode(',', $serialized); generates a 0-based array with the serialised values.
According to the Documentation:
Doctrine ORM > Basic Mapping > Doctrine Mapping Types
You have 3 choices regaring array data:
array Type that maps a SQL CLOB to a PHP array using serialize() and unserialize().
simple_array Type that maps a SQL CLOB to a PHP array using implode() and explode(), with a comma as delimiter.
IMPORTANT: Only use this type if you are sure that your values cannot contain a ,.
json_array Type that maps a SQL CLOB to a PHP array using json_encode() and json_decode().
So, if you are sure about not having , (comma) in your array values, use simple_array. If you have a simple array structure (linear), use array and if you have more complex key-value arrays, use json_array.
From www.doctrine-project.org reference
Array types
Types that map array data in different variations such as simple arrays, real arrays or JSON format arrays.
array
Maps and converts array data based on PHP serialization. If you need to store an exact representation of your array data, you should consider using this type as it uses serialization to represent an exact copy of your array as string in the database. Values retrieved from the database are always converted to PHP's array type using deserialization or null if no data is present.
simple_array
Maps and converts array data based on PHP comma delimited imploding and exploding. If you know that the data to be stored always is a scalar value based one-dimensional array, you should consider using this type as it uses simple PHP imploding and exploding techniques to serialize and deserialize your data. Values retrieved from the database are always converted to PHP's array type using comma delimited explode() or null if no data is present.
json
Maps and converts array data based on PHP's JSON encoding functions. If you know that the data to be stored always is in a valid UTF-8 encoded JSON format string, you should consider using this type. Values retrieved from the database are always converted to PHP's native types using PHP's json_decode() function. JSON objects are always converted to PHP associative arrays.
an other page with good description
I'm new to PHP/MySQL. I want to minimize the number of tables I have so I've been thinking of saving an array of IDs (from checkboxes users tick off) as a string instead of in a separate table. What do you use to format the list of IDs as a string so I can easily parse the IDs for future use in my program?
you can use implode()
and explode for joining the values and separating the values respectively. You can also try serialize() for storing the values. There are a lot of examples in my given links, so they will be helpful for your desirable data format.
Thats not a good idea. I think a 1:N-Relation is the better choice. This givs a better performance and the db supports integrity checks.
So if you want to, you can build a comma-separated list and than use following where-statement:
where CONCAT(',', FIELDWITHIDS, ',') like '%,13,%'
to find datasets that reference the ID 13. Or you have to use explode() and implode() in PHP.
Either comma separated values or php serialize (http://php.net/manual/en/function.serialize.php)
That being said, you lose the benefit of being able to do joins or integrity checks in your DB, so you should generally avoid it.
So, there's a field in the db in which I store serialized arrays.
$array = array('count1' => 10, 'count2' => 20, 'count3' => 4);
serialized:
a:3:{s:6:"count1";i:10;s:6:"count2";i:20;s:6:"count3";i:4;}
Would it be possible to pull count1+count2+count3 using a mysql query? I guess I'm looking for something like php's explode. Pretty sure this can't be done, but I thought I'd ask.
I need to pull the highest count1+count2+count3 rows and return the total count. Looping through each row and unserializing wouldn't work since there are TONS of rows.
If you need to access parts of your serialized data via SQL, you need to store them in separate columns.
While it might be possible to use techniques such as regular expressions to access those three values in this string, it would be extremely slow when used in a WHERE criterion as indexes would be useless - not to mention that it would be a huge mess, way worse than using goto in a programming language.
So the solution is to create a new columns and then iterate over all rows, unserialize them, and store the sum into the new column. That might take a while but you'll only need to it once.
Depending on your application it might be better to create three columns and store each value separately.
One of my fields in my data base is an array which has been converted to a string using the implode() function.
How do I retrieve the contents of this field (LESSONS) from the database and store it to a string when a user entered value is equal to the the value of the field NAME?
Thanks in advance for any help you may be able to provide.
Here you go:
$r = mysql_query('SELECT LESSONS FROM TABLE WHERE NAME=\'user_string\'');
$rows = mysql_fetch_assoc($r);
echo $rows['LESSONS'];
I don't know if I understood your question but... Take a look about Stored Procedures
If you used the implode function to convert your array into a string, then this data has lost any information about the array keys.
As far as you want to convert the data back, use the explode function:
$array = explode(',', $columnData);
But You can therefore not search for array keys within the database.
Next to that, the MySQL database (I assume you're using MySQL) can not search for array keys anyway.
You need to store the data in some other way into the mysql to search for it in an SQL later on.
For example, you can create a table that stores key/value combinations with a grouping index.
However MySQL has some string functions that can help you searching within the (now) string data in the MySQL database.
When searching for a value, before the comparison add a comma at the beginning and one at the end of the string. There is a MySQL string function that can concatenate strings. Then search within that expression for your value with a comma added in front and back as well.
Then you can lookop a single array element within the mysql database. MySQL String Functions.
This is a quick solution only, this won't work on large databases performant. However it might solve your problem w/o changing your database structure.