Casting Eloquent\Collection (Laravel) to stdClass array using Repository pattern

Vic picture Vic · Jul 15, 2015 · Viewed 7.4k times · Source

I'm trying to implement the Repository pattern in a Laravel 5 app by following this article. In it, the repository implementation converts the object for the specific data source (in this case Eloquent) to an stdClass so that the app uses a standard format and doesn't care about the data source.

To convert a single Eloquent object they do this:

/**
* Converting the Eloquent object to a standard format
* 
* @param mixed $pokemon
* @return stdClass
*/
protected function convertFormat($pokemon)
{
    if ($pokemon == null)
    {
        return null;
    }

    $object = new stdClass();
    $object->id = $pokemon->id;
    $object->name = $pokemon->name;

    return $object;
}

Or, as someone in the comments pointed out, this could also work:

protected function convertFormat($pokemon)
{
    return $pokemon ? (object) $pokemon->toArray() : null;
}

But then, what happens when I want to cast an entire collection of Eloquent objects to an array of ** stdClass **? Do I have to loop through the collection and cast each element separately? I feel this would be a big hit on performance, having to loop and cast every element every time I need a collection of something and it also feels dirty.

Laravel provides Eloquent\Collection::toArray() which turns the entire collection to an array of arrays. I suppose this is better, but still not stdClass

The benefits of using a generic object would be that I could do this in my code

echo $repo->getUser()->name;

Instead of having to do this:

echo $repo->getUser()['name'];

Answer

Keith Mifsud picture Keith Mifsud · Nov 5, 2015

Using eloquent you can do something like this:

/**
 * Gets the project type by identifier.
 *
 * @param string $typeIdentifier
 *
 * @return object
 *
 */
public function getTypeByIdentifier($typeIdentifier)
{
    $type =  ProjectType::where(
        'type_identifier', $typeIdentifier
    )->first();

    return (object) $type->toArray();
}

All my factories etc accept stdClass so that it's uniform. In eloquent you can either do as above as Eloquent already has a toArray() function which is needed for serialisation, but you can also easily extend Model (Illuminate\Database\Eloquent) to have this method available to all your eloquent models. I suggest that you extend the model so that you can also automate this collections and not just single records.

Because I use the repository pattern with Eloquent I normally create an abstract EloquentRepository which extends the Eloquent Model methods and also obviously allows us to add new methods such as this one.