L5 如何使用散列 id 但保留数据透视功能的特征
L5 How to use trait that hashes id but keep pivot functionality
我使用特征向我的 ID 添加了哈希值。但是现在这样做我就不能再使用 attach() 或关系了。
例如,这种关系在我看来不再有效:
@foreach ($invoice->items as $item)
{{ $item->item }}
@endforeach
这是为我散列 id 的特征
<?php
namespace App\Traits;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder;
trait HashedId
{
/**
* Get the user's id as hashids.
*
* @param $value
* @return string
*/
public function getIdAttribute($value)
{
$hashids = new \Hashids\Hashids(env('APP_KEY'),10);
return $hashids->encode($value);
}
public function scopeHashId(Builder $query, $id)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$id = $hashIds->decode($id)[0];
return $query->where('id', $id);
}
}
发票模型:
<?php
namespace App;
use App\Traits\HashedId;
use Illuminate\Database\Eloquent\Model;
use HipsterJazzbo\Landlord\BelongsToTenants;
class Invoice extends Model
{
use BelongsToTenants;
use HashedId;
//
protected $fillable = [
'client_id',
'invoice_number',
'purchase_order',
'invoice_note',
'invoice_status',
'invoice_total',
'invoice_type',
'sub_total',
'balance_due',
'due_date',
'invoice_type',
'user_id',
];
protected $hidden = [
'user_id'
];
public function items()
{
return $this->belongsToMany('App\LineItem', 'invoice_items', 'invoice_id', 'item_id');
}
public function client()
{
return $this->belongsTo('App\Client');
}
}
我曾尝试通过控制器执行此操作,但感觉更像是一种 hack,而不是正确的方法,而且我仍然无法使用 $invoice->attach($lineItem)
或 $invoice->items
//Currently I have to unhash the ids in order to save them as a pivot
$hashIds = new \Hashids\Hashids(env('APP_KEY'), 10);
$invoiceId = $hashIds->decode($request->invoice_id)[0];
$lineItemId = $hashIds->decode($request->item_id)[0];
//Should have been able to use $invoice->attach($lineItemId)
DB::table('invoice_items')->insert(
['invoice_id' => $invoiceId, 'item_id' => $lineItemId]
);
如何在控制器中继续使用 $invoice->attach($lineItem)
或 $invoice->items
,同时仍然使用散列我的 ID 的特征?
就像您评论的那样,您不能使用附加,因为 id 是 getIdAttribute 的散列 cos。我想建议你使用 getOriginal().
例如,
$invoice->attach($lineItem->getOriginal()['id']);
我认为这可能是唯一的附加方式。
我 re-written 特征如下(假设您使用的是 PHP 5.6 或更高版本):
<?php
namespace App\Traits;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder;
trait HashedId
{
/**
* Get model ID attribute encoded to hash ID.
*
* @return string
*/
public function getHashIdAttribute()
{
$hashIds = new Hashids(env('APP_KEY'), 10);
return $hashIds->encode($this->getKey());
}
/**
* Restrict query scope to find model by encoded hash ID.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param integer $id
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHashId(Builder $query, $id)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$id = $hashIds->decode($id)[0];
return $query->where('id', $id);
}
/**
* Restrict query scope to find models by encoded hash IDs.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $ids
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHashIds(Builder $query, ...$ids)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$ids = array_map(function ($id) use ($hashIds) {
return $hashIds->decode($id)[0];
}, $ids);
return $query->whereIn('id', $ids);
}
}
您可能会注意到我已将访问器 getIdAttribute()
重命名为 getHashIdAttribute()
。因此,您现在可以通过调用 $model->hash_id
而不是 $model->id
.
来获取模型实例的哈希 ID
这就是我认为你的问题所在,因为 Laravel 期望 $model->id
返回一个整数键,而它本来会得到哈希 ID。
如果在实施上述更改后您仍然遇到错误,您能说明具体的错误是什么吗?
我使用特征向我的 ID 添加了哈希值。但是现在这样做我就不能再使用 attach() 或关系了。
例如,这种关系在我看来不再有效:
@foreach ($invoice->items as $item)
{{ $item->item }}
@endforeach
这是为我散列 id 的特征
<?php
namespace App\Traits;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder;
trait HashedId
{
/**
* Get the user's id as hashids.
*
* @param $value
* @return string
*/
public function getIdAttribute($value)
{
$hashids = new \Hashids\Hashids(env('APP_KEY'),10);
return $hashids->encode($value);
}
public function scopeHashId(Builder $query, $id)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$id = $hashIds->decode($id)[0];
return $query->where('id', $id);
}
}
发票模型:
<?php
namespace App;
use App\Traits\HashedId;
use Illuminate\Database\Eloquent\Model;
use HipsterJazzbo\Landlord\BelongsToTenants;
class Invoice extends Model
{
use BelongsToTenants;
use HashedId;
//
protected $fillable = [
'client_id',
'invoice_number',
'purchase_order',
'invoice_note',
'invoice_status',
'invoice_total',
'invoice_type',
'sub_total',
'balance_due',
'due_date',
'invoice_type',
'user_id',
];
protected $hidden = [
'user_id'
];
public function items()
{
return $this->belongsToMany('App\LineItem', 'invoice_items', 'invoice_id', 'item_id');
}
public function client()
{
return $this->belongsTo('App\Client');
}
}
我曾尝试通过控制器执行此操作,但感觉更像是一种 hack,而不是正确的方法,而且我仍然无法使用 $invoice->attach($lineItem)
或 $invoice->items
//Currently I have to unhash the ids in order to save them as a pivot
$hashIds = new \Hashids\Hashids(env('APP_KEY'), 10);
$invoiceId = $hashIds->decode($request->invoice_id)[0];
$lineItemId = $hashIds->decode($request->item_id)[0];
//Should have been able to use $invoice->attach($lineItemId)
DB::table('invoice_items')->insert(
['invoice_id' => $invoiceId, 'item_id' => $lineItemId]
);
如何在控制器中继续使用 $invoice->attach($lineItem)
或 $invoice->items
,同时仍然使用散列我的 ID 的特征?
就像您评论的那样,您不能使用附加,因为 id 是 getIdAttribute 的散列 cos。我想建议你使用 getOriginal().
例如,
$invoice->attach($lineItem->getOriginal()['id']);
我认为这可能是唯一的附加方式。
我 re-written 特征如下(假设您使用的是 PHP 5.6 或更高版本):
<?php
namespace App\Traits;
use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder;
trait HashedId
{
/**
* Get model ID attribute encoded to hash ID.
*
* @return string
*/
public function getHashIdAttribute()
{
$hashIds = new Hashids(env('APP_KEY'), 10);
return $hashIds->encode($this->getKey());
}
/**
* Restrict query scope to find model by encoded hash ID.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param integer $id
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHashId(Builder $query, $id)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$id = $hashIds->decode($id)[0];
return $query->where('id', $id);
}
/**
* Restrict query scope to find models by encoded hash IDs.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $ids
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeHashIds(Builder $query, ...$ids)
{
$hashIds = new Hashids(env('APP_KEY'), 10);
$ids = array_map(function ($id) use ($hashIds) {
return $hashIds->decode($id)[0];
}, $ids);
return $query->whereIn('id', $ids);
}
}
您可能会注意到我已将访问器 getIdAttribute()
重命名为 getHashIdAttribute()
。因此,您现在可以通过调用 $model->hash_id
而不是 $model->id
.
这就是我认为你的问题所在,因为 Laravel 期望 $model->id
返回一个整数键,而它本来会得到哈希 ID。
如果在实施上述更改后您仍然遇到错误,您能说明具体的错误是什么吗?