Другой подход - связать User и DataTypes как отношение «многие ко многим» и использовать область действия для их обработки.
Прежде всего, измените таблицу UserData на dataTypeUser, чтобы вы могли использовать красноречивые связи по умолчанию. В любой модели положить отношение принадлежит к многим. Модель пользователя
public function dataTypes()
{
return $this->belongsToMany('App\DataType')
->withPivot(['value']);
}
public function scopeField($query, $field)
{
return $query->whith(['dataTypes'=>function($q)use($field){
$q->where('data_types.field',$field);
}]);
}
Модель типа данных
public function users()
{
return $this->belongsToMany('App\User')
->withPivot(['value']);
}
Чтобы получить какое-либо значение, вы можете использовать $field = $user->field('something')->first()
, чтобы сохранить новые данные, можно использовать $user->field('something')->updateExistingPivot($field->id,['value'=>$newValue])
.
В любом случае, если к вашему пользователю не привязано много данных одного типа (например, более одного номера телефона), может быть лучше использовать одну таблицу, расширяющую миграцию пользователя, или, наконец, userData со столбцами для каждого типа данных. , В небольших приложениях у вас нет проблем, но по мере роста производительности вашего приложения будут проблемы со многими таблицами и множеством взаимосвязей.
Чтобы избежать длинного объявления, вы можете перезаписать magi c методы __get и __set. Оба они объявлены в Illuminate \ Database \ Eloquent \ Model, поэтому укажите в вашей пользовательской модели:
public function __get($key)
{
return $this->getAttribute($key) ?? $this->getAttributesFromPivot($key);
}
public function __set($key, $value)
{
if(in_array($key,array_keys($this->original)))
$this->setAttribute($key, $value);
else
$this->setAttributeFromPivot($key, $value);
}
public function setAttributeFromPivot($key, $value)
{
$this->dataTypes()->where('field',$key)->update(['value'=>$value]);
}
protected function getAttributesFromPivot($key)
{
return $this->dataTypes()
->where('field',$key)
// use this to get only one value direct
->first()->pivot->value ?? null;
// or use this to get all of them as array
// ->get()
// ->map(function($item){ return $item->pivot->value;}) ?? null;
}
В этом подходе вы можете использовать $user->city
, чтобы получить город поля или другой, заменяющий ->city
. Или вы можете использовать $user->address = 'foo';
, чтобы установить новое значение в сводной таблице. Обратите внимание, что он будет обновлять базу данных напрямую.
Теперь, если вам неудобно перезаписывать эти методы, вам не нужно. Измените подписи setAttributeFromPivot и getAttributeFromPivot на public function getField($key)
и public function setField($key, $value)
. Теперь вы можете использовать их в качестве распространенных методов.