5

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

Steve Bauman
  • 8,165
  • 7
  • 40
  • 56

1 Answers1

7

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
Ben Swinburne
  • 25,669
  • 10
  • 69
  • 108
  • 1
    Yea you're completely right, I've run out of options so I'll have to replace the service provider. Though I'm definitely glad that replacing the service provider is an option. Really appreciate the in depth response on this – Steve Bauman Nov 25 '14 at 15:52
  • Is there a newer solution to this? It seems that Illuminate\Pagination\Factory no longer exists in this location. – Daniel Tate Feb 01 '22 at 01:34