Developer
Developer

Reputation: 2895

Convert Entity to array in Symfony

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?

Upvotes: 7

Views: 63454

Answers (5)

user1077915
user1077915

Reputation: 894

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();

Upvotes: 0

Eugene Kaurov
Eugene Kaurov

Reputation: 2971

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.

Upvotes: 1

Allart
Allart

Reputation: 928

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"]);

Upvotes: 0

Skylord123
Skylord123

Reputation: 482

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.

Upvotes: 14

Antoine Subit
Antoine Subit

Reputation: 9913

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'];

Upvotes: 9

Related Questions