Laravel - 跨模型查询范围

时间:2017-06-14 11:29:47

标签: laravel eloquent

简而言之,我想创建一个我的查询范围可以在多个模型中使用的函数:

public function scopeNormaliseCurrency($query,$targetCurrency) {

    return $query->normaliseCurrencyFields(
        ['cost_per_day','cost_per_week'],
        $targetCurrency
    );

}

我的逻辑在这个范围内工作没有问题,但是我想让所有模型都能使用这个代码,因为不同的表中有多个货币字段,我不想复制每个查询范围中的代码 - 仅指定需要注意的列。

那么,我将在哪里创建我的函数normaliseCurrencyFields?我扩展了Model类,并使用newCollection关键字扩展Collection,但都导致Call to undefined method Illuminate\Database\Query\Builder::normaliseCurrencyFields()错误。

我调查了Global Scoping,但这似乎是本地化为模型。

我是否沿着正确的路线走?我应该专门针对Eloquent吗?

1 个答案:

答案 0 :(得分:2)

创建一个抽象的基础模型,该模型扩展了eloquent,然后使用您想要访问它的类来扩展它。我这样做是为了搜索函数,uuid创建和类代码函数。因此,我所保存的所有模型都必须具有某些属性并可以访问我的搜索功能。例如,我创建了一个静态搜索函数getobjectbyid()。因此,当扩展时,我可以这样称呼它:

$user = User::getobjectbyid('habwiifnbrklsnbbd1938');

因此,我知道我正在获取用户对象。

我的基本模型:

<?php
/**
 * Created by PhpStorm.
 * User: amac
 * Date: 6/5/17
 * Time: 12:45 AM
 */

namespace App;

use Illuminate\Database\Eloquent\Model as Eloquent;

abstract class Model extends Eloquent
{

    protected $guarded = [
        'class_code',
        'id'
    ];

    public $primaryKey = 'id';

    public $incrementing = false;

    public function __construct($attributes = array())  {
        parent::__construct($attributes); // Eloquent

        $this->class_code = \App\Enums\EnumClassCode::getValueByKey(get_class($this));

        $this->id = $this->class_code . uniqid();

        return $this;

    }


    public static function getObjectById($id){
        $class = get_called_class();
        $results = $class::find($id);
        return $results;

    }

    public static function getAllObjects(){
        $class = get_called_class();
        return $class::all();
    }

我的用户模型:

<?php

namespace App;


use Mockery\Exception;
use Illuminate\Support\Facades\Hash;

use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;

use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

use App\Model as Model;

class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{

    use Authenticatable;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'contact', 'username', 'email_address'
    ];

    /**
     * The column name of the "remember me" token.
     *
     * @var string
     */
    protected $rememberTokenName = 'remember_token';

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'remember_token', 'active'
    ];

    /**
     * the attributes that should be guarded from Mass Assignment
     *
     * @var array
     */
    protected $guarded = [
        'created_at', 'updated_at', 'password_hash'
    ];

    /**
     * Define table to be used with this model. It defaults and assumes table names will have an s added to the end.
     *for instance App\User table by default would be users
     */
    protected $table = "user";

    /**
     * We have a non incrementing primary key
     *
     * @var bool
     */
    public $incrementing = false;

    /**
     * relationships
     */
    public function contact(){
//        return $this->hasOne(Contact::class, 'id', 'contact_id');
        return $this->hasOne(Contact::class);
    }


    public function customers(){
//        return $this->hasOne(Contact::class, 'id', 'contact_id');
        return $this->hasMany(Customer::class);
    }

    /**
     * User constructor.
     * @param array $attributes
     */
    public function __construct($attributes = array())  {
        parent::__construct($attributes); // Eloquent
        // Your construct code.

        $this->active = 1;

        return $this;
    }


    /**
     * @param $password string
     * set user password_hash
     * @return $this
     */
    public function setPassword($password){
        // TODO Password Validation
        try{
            $this->isActive();
            $this->password_hash = Hash::make($password);
            $this->save();
        } catch(\Exception $e) {
            dump($e->getMessage());
        }
        return $this;
    }


    /**
     * Returns whether or not this use is active.
     *
     * @return bool
     */
    public function isActive(){
        if($this->active) {
            return true;
        } else {
            Throw new Exception('This user is not active. Therefore you cannot change the password', 409);
        }
    }


    public function getEmailUsername(){
        $contact = Contact::getObjectById($this->contact_id);

        $email = Email::getObjectById($contact->email_id);

        return $email->username_prefix;
    }


    /**
     * @return string
     *
     * getFullName
     * returns concatenated first and last name of user.
     */
    public function getFullName(){
        return $this->first_name . ' ' . $this->last_name;
    }


    /**
     * Get the name of the unique identifier for the user.
     *
     * @return string
     */
    public function getAuthIdentifierName(){
        return $this->getKeyName();

    }

    /**
     * Get the unique identifier for the user.
     *
     * @return mixed
     */
    public function getAuthIdentifier(){
        return $this->{$this->getAuthIdentifierName()};
    }

    /**
     * Get the password for the user.
     *
     * @return string
     */
    public function getAuthPassword(){
        return $this->password_hash;
    }

    /**
     * Get the token value for the "remember me" session.
     *
     * @return string
     */
    public function getRememberToken(){
        if (! empty($this->getRememberTokenName())) {
            return $this->{$this->getRememberTokenName()};
        }
    }

    /**
     * Set the token value for the "remember me" session.
     *
     * @param  string  $value
     * @return void
     */
    public function setRememberToken($value){
        if (! empty($this->getRememberTokenName())) {
            $this->{$this->getRememberTokenName()} = $value;
        }
    }

    /**
     * Get the column name for the "remember me" token.
     *
     * @return string
     */
    public function getRememberTokenName(){
        return $this->rememberTokenName;
    }

    /**
     * Get the e-mail address where password reset links are sent.
     *
     * @return string
     */
    public function getEmailForPasswordReset(){

    }

    /**
     * Send the password reset notification.
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token){

    }

    public function validateAddress(){

    }


}

一个TestController:

public function test(){
        $user = User::getObjectById('USR594079ca59746');

        $customers = array();

        foreach ($user->customers as $customer){

            $contact = Contact::getObjectById($customer->contact_id);

            $name = PersonName::getObjectById($contact->personname_id);

            $c = new \stdClass();

            $c->id = $customer->id;
            $c->name = $name->preferred_name;

            $customers[] = $c;
        }

        $response = response()->json($customers);

        return $response;
}

请注意getObjectById如何扩展并可用于扩展我的基本模型的其他类。此外,我不必在我的用户模型中指定'id'或'class_code',并且在构造我的用户模型时,它调用父构造函数,该构造函数是我的基础模型上处理'id'和'class_code'的构造函数。 / p>