Проблема
Я хотел бы установить аксессоры и мутаторы для одного атрибута модели, но с подстановочными знаками
У меня есть атрибут для разных языков, который называется tags_en, tags_es, Tags_fr и т. Д. Для (8) языковых тегов
Я хотел бы установить один метод доступа и один мутатор в модели тегов для всех 8 языковых подтипов один раз вместо использования нескольких методов доступа / мутатора для каждого из них.
Обычно для каждого из них можно сделать следующее, например, tags_en
public function getTagsEnAttribute($tags){
return join(', ', json_decode($tags));
}
public function setTagsEnAttribute($tags){
$this->attributes['tags_en'] =
json_encode(
array_map('trim', explode(',', $tags))
);
}
Затем я должен повторить их для каждого языкового разнообразия тегов, которые на данный момент являются 8 языками, что не практично.
Моя цель
Любой способ сделать аксессоры и мутаторы с подстановочными символами вроде того (которые, конечно, не работают таким образом):
public function getTagsWildcardAttribute($tags){
return join(', ', json_decode($tags));
}
или же
что-то вроде:
foreach ($tagsAttributes as $TagAttribute){
//method building code for each tags language
}
Подобная идея Laravel существует для валидации с подстановочными знаками
Я предполагаю, что может быть способ сделать это через класс Model laravel, используя подстановочный знак. Это похоже на Validator, где вы можете проверить каждый элемент массива следующим образом:
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
Вопросы:
Вы могли бы продлить castAttribute()
а также setAttribute()
методы.
protected function castAttribute($key, $value) {
if (is_null($value)) {
return $value;
}
if ($this->isTagCastable($key)) {
return join(', ', json_decode($value));
}
return parent::castAttribute($key, $value);
}
public function setAttribute($key, $value)
{
if ($this->isTagCastable($key)) {
$this->attributes[$key] =
json_encode(
array_map('trim', explode(',', $value))
);
}
return parent::setAttribute($key, $value);
}
protected function isTagCastable($key) {
return preg_match('/tags_[a-z]{2}/', $key);
}
Мне немного неясно, как настроена ваша база данных, но насколько я понимаю, в ней есть таблица с колонками tags_en
, tags_fr
, tags_de
, так далее.
Вот идея:
$casts
boot()
метод и использовать его для установки тегов creating
а также updating
castAttribute($key, $value)
метод и использовать его для приведения значения обратно при извлечении (это будет работать как метод доступа)Это будет выглядеть примерно так
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
protected static $tags = [
'tags_en',
'tags_fr',
'tags_de',
];
public static function boot()
{
static::creating(function ($model) {
foreach (static::$tags as $tag) {
// You can customize exactly what you need to do here
$model->$tag = json_encode($model->tag);
}
unset($model->tag);
});
static::updating(function ($model) {
foreach (static::$tags as $tag) {
// You can customize exactly what you need to do here
$model->$tag = json_encode($model->tag);
}
unset($model->tag);
});
parent::boot();
}
/**
* Cast an attribute to a native PHP type.
*
* @param string $key
* @param mixed $value
* @return mixed
*/
protected function castAttribute($key, $value)
{
if (in_array($key, static::$tags)) {
return join(', ', (array) json_decode($value));
}
parent::castAttribute($key, $value);
}
}
Когда вы создаете экземпляр модели:
$t = App\MyModel::create([
'name' => 'My Tags',
'tag' => ['key' => 'value', 'key2' => 'value2']
]);
Затем, когда вы получите экземпляр:
$t = App\MyModel::find($id);
echo $t->tags_en; // This will be handled by the `castAttribute($key, $value)` override
Что касается ваших последних 3 вопросов: Если вы считаете, что это должно быть включено, то лучше всего: а) попросить через репозиторий GitHub или, что еще лучше, б) кодировать его и поместить в PR. Персонал Stack Overflow не имеет никакого отношения к Laravel, поэтому они не могут, и не смогут и не смогут ничего сделать.
Для этого есть решение, Красноречивые Мутаторы https://github.com/topclaudy/eloquent-mutators
После установки пакета вы сможете зарегистрировать собственные расширения accessors / mutators для ваших моделей Eloquent.