7

I'm trying to get a multi-dimensional array from an Entity.

Symfony Serializer can already convert to XML, JSON, YAML etc. but not to an array.

I need to convert because I want have a clean var_dump. I now have entity with few connections and is totally unreadable.

How can I achieve this?

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Developer
  • 2,731
  • 2
  • 41
  • 71
  • possible duplicate of [How to get a Doctrine2 result object as an associative array?](http://stackoverflow.com/questions/7259256/how-to-get-a-doctrine2-result-object-as-an-associative-array) – denys281 Feb 21 '14 at 13:34
  • i dont want get restult as array - i use it as entity and need in other plaace convert to array. – Developer Feb 21 '14 at 13:48
  • There are much better ways to debug your application than "var_dumps". Try use xdebug - this tool as a debuger is really great. – Cyprian Feb 21 '14 at 14:45
  • Prefer use this class http://www.doctrine-project.org/api/common/2.4/class-Doctrine.Common.Util.Debug.html with method dump – Benjamin Lazarecki Feb 21 '14 at 14:55
  • Why do you want clean var dumps? If you are just using it to debug then (as @Cyprian says, there are better ways to go about it. If you are looking to use `var dumps` as a part of your coding then you really shouldn't. Pictures of cats however... – qooplmao Feb 23 '14 at 06:11
  • because var_dump is too big - usually i want get partial informations - entities have many realtions so var_dump give my too big text. – Developer Feb 23 '14 at 11:06

5 Answers5

13

You can actually convert doctrine entities into an array using the built in serializer. I actually just wrote a blog post about this today: https://skylar.tech/detect-doctrine-entity-changes-without/

You basically call the normalize function and it will give you what you want:

$entityAsArray = $this->serializer->normalize($entity, null);

I recommend checking my post for more information about some of the quirks but this should do exactly what you want without any additional dependencies or dealing with private/protected fields.

Skylord123
  • 482
  • 4
  • 11
  • Is there annotation to tell that some property should be returned as object without serialisation? My object has properties (object, stream). I want to convert Object to array of objects. – Eugene Kaurov Nov 07 '22 at 13:40
  • If some property is a strem then you will get error: An unexpected value could not be normalized: "stream" resource. Easiest way is to add @Ignore annotation. I need to export it as object – Eugene Kaurov Nov 07 '22 at 13:41
  • Current Symfony serializer requires the second parameter to be of type `string`: `public function serialize(mixed $data, string $format, array $context = []): string;`, so this will, unfortunately, not work anymore and needs to be revisited. – jurchiks Jul 18 '23 at 20:07
9

Apparently, it is possible to cast objects to arrays like following:

<?php

class Foo
{
    public $bar = 'barValue';
}

$foo = new Foo();

$arrayFoo = (array) $foo;

var_dump($arrayFoo);

This will produce something like:

array(1) {
    ["bar"]=> string(8) "barValue"
}

If you have got private and protected attributes see this link : https://ocramius.github.io/blog/fast-php-object-to-array-conversion/

Get entity in array format from repository query

In your EntityRepository you can select your entity and specify you want an array with getArrayResult() method.
For more informations see Doctrine query result formats documentation.

public function findByIdThenReturnArray($id){
    $query = $this->getEntityManager()
        ->createQuery("SELECT e FROM YourOwnBundle:Entity e WHERE e.id = :id")
        ->setParameter('id', $id);
    return $query->getArrayResult();
}

If all that doesn't fit you should go see the PHP documentation about ArrayAccess interface.
It retrieves the attributes this way : echo $entity['Attribute'];

Antoine Subit
  • 9,803
  • 4
  • 36
  • 52
1

PHP 8 allows us to cast object to array:

$var = (array)$someObj;

It is important for object to have only public properties otherwise you will get weird array keys:

<?php
class bag {
    function __construct( 
        public ?bag $par0 = null, 
        public string $par1 = '', 
        protected string $par2 = '', 
        private string $par3 = '') 
    {
        
    }
}
  
// Create myBag object
$myBag = new bag(new bag(), "Mobile", "Charger", "Cable");
echo "Before conversion : \n";
var_dump($myBag);
  
// Converting object to an array
$myBagArray = (array)$myBag;
echo "After conversion : \n";
var_dump($myBagArray);
?>

The output is following:

Before conversion : 
object(bag)#1 (4) {
  ["par0"]=>               object(bag)#2 (4) {
    ["par0"]=>                      NULL
    ["par1"]=>                      string(0) ""
    ["par2":protected]=>            string(0) ""
    ["par3":"bag":private]=>        string(0) ""
  }
  ["par1"]=>               string(6) "Mobile"
  ["par2":protected]=>     string(7) "Charger"
  ["par3":"bag":private]=> string(5) "Cable"
}


After conversion : 
array(4) {
  ["par0"]=>      object(bag)#2 (4) {
    ["par0"]=>                  NULL
    ["par1"]=>                  string(0) ""
    ["par2":protected]=>        string(0) ""
    ["par3":"bag":private]=>    string(0) ""
  }
  ["par1"]=>      string(6) "Mobile"
  ["�*�par2"]=>   string(7) "Charger"
  ["�bag�par3"]=> string(5) "Cable"
}

This method has a benefit comparing to Serialiser normalizing -- this way you can convert Object to array of objects, not array of arrays.

Eugene Kaurov
  • 2,356
  • 28
  • 39
0

I had the same issue and tried the 2 other answers. Both did not work very smoothly.

  • The $object = (array) $object; added alot of extra text in my key names.
  • The serializer didn't use my active property because it did not have is in front of it and is a boolean. It also changed the sequence of my data and the data itself.

So I created a new function in my entity:

/**
 * Converts and returns current user object to an array.
 * 
 * @param $ignores | requires to be an array with string values matching the user object its private property names.
 */
public function convertToArray(array $ignores = [])
{
    $user = [
        'id' => $this->id,
        'username' => $this->username,
        'roles' => $this->roles,
        'password' => $this->password,
        'email' => $this->email,
        'amount_of_contracts' => $this->amount_of_contracts,
        'contract_start_date' => $this->contract_start_date,
        'contract_end_date' => $this->contract_end_date,
        'contract_hours' => $this->contract_hours,
        'holiday_hours' => $this->holiday_hours,
        'created_at' => $this->created_at,
        'created_by' => $this->created_by,
        'active' => $this->active,
    ];

    // Remove key/value if its in the ignores list.
    for ($i = 0; $i < count($ignores); $i++) { 
        if (array_key_exists($ignores[$i], $user)) {
            unset($user[$ignores[$i]]);
        }
    }

    return $user;
}

I basicly added all my properties to the new $user array and made an extra $ignores variable that makes sure properties can be ignored (in case you don't want all of them).

You can use this in your controller as following:

$user = new User();
// Set user data...

// ID and password are being ignored.
$user = $user->convertToArray(["id", "password"]);
Allart
  • 830
  • 11
  • 33
0

I add this trait to the entity:

<?php

namespace Model\Traits;

/**
 * ToArrayTrait
 */
trait ToArrayTrait
{
    /**
     * toArray
     *
     * @return array
     */
    public function toArray(): array
    {
        $zval = get_object_vars($this);

        return($zval);
    }
}

Then you cat do:

$myValue = $entity->toArray();

user1077915
  • 828
  • 1
  • 12
  • 26