Модель и аксессуар Laravel с символом подстановки (*)

Проблема

Я хотел бы установить аксессоры и мутаторы для одного атрибута модели, но с подстановочными знаками
У меня есть атрибут для разных языков, который называется 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',
]);

Вопросы:

  1. Если эти модели аксессоры и мутаторы с джокером не доступны в текущей структуре Laravel — вы согласны со мной, что это стоит добавлять в следующих версиях Laravel?
  2. Если так, то как попросить производителей ларавеллы, официально, рассмотреть это в следующих версиях?
  3. Может ли персонал Stackoverflow попросить строителей Laravel об этом улучшении (если они это увидят) от нашего имени?

0

Решение

Вы могли бы продлить 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);
}
1

Другие решения

Мне немного неясно, как настроена ваша база данных, но насколько я понимаю, в ней есть таблица с колонками tags_en, tags_fr, tags_de, так далее.

Вот идея:

  1. Добавьте свойство, которое содержит столбцы, которые вы хотите установить / получить
  2. Создать пользовательский тип в $casts
  3. Переопределить boot() метод и использовать его для установки тегов creating а также updating
  4. Переопределить 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, поэтому они не могут, и не смогут и не смогут ничего сделать.

1

Для этого есть решение, Красноречивые Мутаторы https://github.com/topclaudy/eloquent-mutators

После установки пакета вы сможете зарегистрировать собственные расширения accessors / mutators для ваших моделей Eloquent.

0
По вопросам рекламы [email protected]