Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace the Laravel Builder class

I want to replace the Laravels builder class with my own that's extending from it. I thought it would be as simple as matter of App::bind but it seems that does not work. Where should I place the binding and what is the proper way to do that in Laravel?

This is what I have tried:

my Builder:

    use Illuminate\Database\Eloquent\Builder as BaseBuilder;
    class Builder  extends  BaseBuilder
    {

        /**
         * Find a model by its primary key.
         *
         * @param  mixed  $id
         * @param  array  $columns
         * @return \Illuminate\Database\Eloquent\Model|static|null
         */
        public function find($id, $columns = array('*'))
        {
            Event::fire('before.find', array($this));
            $result = parent::find($id, $columns);
            Event::fire('after.find', array($this));
            return $result;
        }
    }

And next I tried to register the binding in bootstrap/start.php file like this :

$app->bind('Illuminate\\Database\\Eloquent\\Builder', 'MyNameSpace\\Database\\Eloquent\\Builder');
return $app;
like image 876
Vit Kos Avatar asked May 05 '14 14:05

Vit Kos


2 Answers

Both of the answers are correct in some way. You have to decide what your goal is.

Change Eloquent Builder

For example, if you want to add a new method only for eloquent models (eg. something like scopes, but maybe a little more advanced so it’s not possible in a scope)

Create a new Class extending the Eloquent Builder, for Example CustomEloquentBuilder.

use Illuminate\Database\Eloquent\Builder;


class CustomEloquentBuilder extends Builder 
{

    public function myMethod()
    {
        // some method things
    }

}

Create a Custom Model and overwrite the method newEloquentBuilder

use Namespace\Of\CustomEloquentBuilder;
use Illuminate\Database\Eloquent\Model;


class CustomModel extends Model
{

    public function newEloquentBuilder($query)
    {
        return new CustomEloquentBuilder($query);
    }

}

Change Database Query Builder

For example to modify the where-clause for all database accesses

Create a new Class extending the Database Builder, for Example CustomQueryBuilder.

use Illuminate\Database\Query\Builder;


class CustomQueryBuilder extends Builder 
{

    public function myMethod()
    {
        // some method things
    }

}

Create a Custom Model and overwrite the method newBaseQueryBuilder

use Namespace\Of\CustomQueryBuilder;
use Illuminate\Database\Eloquent\Model;


class CustomModel extends Model
{

    protected function newBaseQueryBuilder()
    {
        $connection = $this->getConnection();

        return new CustomQueryBuilder(
            $connection, $connection->getQueryGrammar(), $connection->getPostProcessor()
        );
    }

}

Laravel Version: 5.5 / this code is untestet

like image 147
KohlerDominik Avatar answered Oct 05 '22 22:10

KohlerDominik


Illuminate\Database\Eloquent\Builder class is an internal class and as such it is not dependency injected into the Illuminate\Database\Eloquent\Model class, but kind of hard coded there.

To do what you want to do, I would extend the Illuminate\Database\Eloquent\Model to MyNamespace\Database\Eloquent\Model class and override newEloquentBuilder function.

public function newEloquentBuilder($query)
{
   return new MyNamespace\Database\Eloquent\Builder($query);
}

Then alias MyNamespace\Database\Eloquent\Model to Eloquent at the aliases in app/config/app.php

like image 42
tharumax Avatar answered Oct 05 '22 22:10

tharumax