Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending the Laravel Eloquent\Collection Class

I understand that the default Eloquent\Collection class can be overridden in your model by using the method:

public function newCollection(array $models = array()) {

    return new CustomCollection($models);
}

Which works great if I'm using typical queries such as:

Model::where('name', $name)->get();

This is great so I can add methods to the eloquent collection class, such as:

$records = Model::where('name', $name)->get();

$records->toTable();

But if I'm using pagination on the model, for example:

Model::where('name', $name)->paginate(25);

It returns an instance of the class Illuminate\Support\Collection instead of the Illuminate\Database\Eloquent\Collection.

Is there a way of overriding or extending the typical Illuminate\Support\Collection?

I'm trying to add a toTable() method to the returned Collection. I'd rather not have to replace the pagination service provider with my own.

Thanks!!

like image 619
Steve Bauman Avatar asked Nov 19 '14 16:11

Steve Bauman


1 Answers

You will need to replace the pagination service provider, amongst a couple of other classes in the pagination library. By the sound of it you know how to do it this way, but were hoping for another answer, but as I have the code I'll drop it in here for you.

The reason you need to replace these classes/methods is because the files in Illuminate directly reference instances of classes within the Illuminate namespace.

In config/app.php

Replace

'Illuminate\Pagination\PaginationServiceProvider',

With

'ExtendedPaginationServiceProvider',

Create a new file somewhere the autoloader is capable of finding it called ExtendedPaginationServiceProvider.php and place the following in it

<?php

use Illuminate\Support\ServiceProvider;

class ExtendedPaginationServiceProvider extends ServiceProvider
{
    /**
     * @inheritdoc
     */
    public function register()
    {
        $this->app->bindShared('paginator', function($app)
        {
            $paginator = new ExtendedPaginationFactory($app['request'], $app['view'], $app['translator']);

            $paginator->setViewName($app['config']['view.pagination']);

            $app->refresh('request', $paginator, 'setRequest');

            return $paginator;
        });
    }
}

Create a new file somewhere the autoloader is capable of finding it called ExtendedPaginationFactory.php and place the following in it

<?php

use Illuminate\Pagination\Factory;

class ExtendedPaginationFactory extends Factory
{
    /**
     * @inheritdoc
     */
    public function make(array $items, $total, $perPage = null)
    {
        $paginator = new ExtendedPaginationPaginator($this, $items, $total, $perPage);

        return $paginator->setupPaginationContext();
    }
}

Create a new file somewhere the autoloader is capable of finding it called ExtendedPaginationPaginator.php and place the following in it

<?php

use Illuminate\Pagination\Paginator;

class ExtendedPaginationPaginator extends Paginator
{
    /**
     * Get a collection instance containing the items.
     *
     * @return ExtendedCollection
     */
    public function getCollection()
    {
        return new ExtendedCollection($this->items);
    }
}

You'll notice the above returns a new instance of ExtendedCollection. Obviously replace this with your CustomCollection class you refer to in your question.

For others to reference, an ExtendedCollection class may look similar to the below

Create a new file somewhere the autoloader is capable of finding it called ExtendedCollection.php and place the following in it

<?php

use Illuminate\Support\Collection;

class ExtendedCollection extends Collection
{

}

Also, after creating these files, don't forget to run the following in the terminal

composer dump-autoload
like image 101
Ben Swinburne Avatar answered Oct 31 '22 01:10

Ben Swinburne