73

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 ...

Joseph Erickson
  • 2,304
  • 20
  • 29
0x1gene
  • 3,349
  • 4
  • 29
  • 48
  • 3
    if you use `json_array`, just keep in mind that de facto (because of the bug http://www.doctrine-project.org/jira/browse/DBAL-446) it can never be `null` even when it's declared `nullable=true` (when the entity is constructed/hydrated by doctrine). So to circumvent this problem, _always_ set value `array()` for your `$myJsonArray` property. So that your property definition would be: `/* @Column(type="json_array) */ private $myJsonArray = array();`. And check whether it's set via `empty($this->myJsonArray)` but not `null === $this->myJsonArray()` – Dimitry K Oct 11 '14 at 17:18
  • 1
    Another link to the same bug that still isn't fixed: https://github.com/doctrine/dbal/issues/1643 – ar34z Mar 31 '17 at 14:03

5 Answers5

139

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
Marino Di Clemente
  • 3,120
  • 1
  • 23
  • 24
  • 1
    As mentioned in the OP comments: `json_array` returns an empty array when the value is `null`. This is a bug: https://github.com/doctrine/dbal/issues/1643 – ar34z Mar 31 '17 at 14:04
  • 4
    json_array is deprecated https://www.doctrine-project.org/projects/doctrine-dbal/en/2.7/reference/types.html – hayzem Jun 29 '18 at 09:20
12

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.

Community
  • 1
  • 1
Jason Hanley
  • 304
  • 2
  • 14
3

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.

Luis
  • 1,140
  • 9
  • 9
2

According to the Documentation:

Doctrine ORM > Basic Mapping > Doctrine Mapping Types

You have 3 choices regaring array data:

  1. array Type that maps a SQL CLOB to a PHP array using serialize() and unserialize().

  2. 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 ,.

  3. 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.

Community
  • 1
  • 1
Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
0

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.

Jean-Christophe Meillaud
  • 1,961
  • 1
  • 21
  • 27
Mohammad Trabelsi
  • 3,308
  • 2
  • 10
  • 18