Laravel Custom Model Methods

前端 未结 3 997
孤街浪徒
孤街浪徒 2021-01-31 02:37

Whenever I add additional logic to Eloquent models, I end up having to make it a static method (i.e. less than ideal) in order to call it from the model\'s facade.

相关标签:
3条回答
  • 2021-01-31 03:11

    Actually you can extend Eloquent Builder and put custom methods there.

    Steps to extend builder :

    1.Create custom builder

    <?php
    
    namespace App;
    
    class CustomBuilder extends \Illuminate\Database\Eloquent\Builder
    {
        public function test()
        {
            $this->where(['id' => 1]);
    
            return $this;
        }
    }
    

    2.Add this method to your base model :

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

    3.Run query with methods inside your custom builder :

    User::where('first_name', 'like', 'a')
        ->test()
        ->get();
    

    for above code generated mysql query will be :

    select * from `users` where `first_name` like ? and (`id` = ?) and `users`.`deleted_at` is null
    

    PS:

    First Laurence example is code more suitable for you repository not for model, but also you can't pipe more methods with this approach :

    public static function getAllSortedByMake()
    {
        return Car::where('....')->get();
    }
    

    Second Laurence example is event worst.

    public function scopeGetAllSortedByMake($query)
    {
        return $query->where('...')->get();
    }
    

    Many people suggest using scopes for extend laravel builder but that is actually bad solution because scopes are isolated by eloquent builder and you won't get the same query with same commands inside vs outside scope. I proposed PR for change whether scopes should be isolated but Taylor ignored me.

    More explanation : For example if you have scopes like this one :

    public function scopeWhereTest($builder, $column, $operator = null, $value = null, $boolean = 'and')
    {
        $builder->where($column, $operator, $value, $boolean);
    }
    

    and two eloquent queries :

    User::where(function($query){
        $query->where('first_name', 'like', 'a');
        $query->where('first_name', 'like', 'b');
    })->get();
    

    vs

    User::where(function($query){
        $query->where('first_name', 'like', 'a');
        $query->whereTest('first_name', 'like', 'b');
    })->get();
    

    Generated queries would be :

    select * from `users` where (`first_name` like ? and `first_name` like ?) and `users`.`deleted_at` is null
    

    vs

    select * from `users` where (`first_name` like ? and (`id` = ?)) and `users`.`deleted_at` is null
    

    on first sight queries look the same but there are not. For this simple query maybe it does not matter but for complicated queries it does, so please don't use scopes for extending builder :)

    0 讨论(0)
  • 2021-01-31 03:24

    My question is at more of a fundamental level such as why is all() accessible via the facade?

    If you look at the Laravel Core - all() is actually a static function

    public static function all($columns = array('*'))
    

    You have two options:

    public static function getAllSortedByMake()
    {
        return Car::where('....')->get();
    }
    

    or

    public function scopeGetAllSortedByMake($query)
    {
        return $query->where('...')->get();
    }
    

    Both will allow you to do

    Car::getAllSortedByMake();
    
    0 讨论(0)
  • 2021-01-31 03:30

    for better dynamic code, rather than using Model class name "Car",

    just use "static" or "self"

    public static function getAllSortedByMake()
    {
        //to return "Illuminate\Database\Query\Builder" class object you can add another where as you want
        return static::where('...');
    
        //or return already as collection object
        return static::where('...')->get();
    }
    
    0 讨论(0)
提交回复
热议问题