简而言之,我想创建一个我的查询范围可以在多个模型中使用的函数:
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吗?
答案 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>