#laravel
Вопрос:
Я настроил свою модель следующим образом:
class Items extends Model {
use HasFactory;
protected $table = 'item';
protected $primaryKey = 'id';
protected $connection = 'mysql';
public $timestamps = false;
protected $fillable = ['user_id', 'title', 'desc', 'start_datetime', 'due_datetime', 'priority', 'status'];
public function getManager() {
return $this->belongsTo(User::class, 'user_id');
}
public function getAssignees() {
return $this->belongsToMany(User::class);
}
}
Я получаю все элементы, используя метод контроллера ниже, что я хочу сделать, так это заполнить поле user_id в каждом из элементов, используя метод getManager (), который я объявил в своей модели элементов. Я знаю, как это сделать, когда вы получаете только один элемент, но как заполнить каждую запись, когда получаете их все?
public function getall() {
try {
$items = Item::get();
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
Я пробовал это, но не повезло:
public function getall() {
try {
$items = Item::get();
$items = array_map(function ($el) {
return $el->manager = $el->getManager()->get();
}, $items);
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
Комментарии:
1. Почему у вас есть и
BelongsTo
то, и другое, иBelongsToMany
отношения, настроенные для этой модели? Как только вы правильно настроите отношения, вы можете просто сделатьItem::with('user')->get();
2. Ваши методы отношений также не должны называться так. Они должны быть названиями из одного слова, отражающими модель, с которой они связаны, как
public function user()
это сделает вашу жизнь намного проще, когда все уладится.
Ответ №1:
Здесь есть несколько вещей, по поводу которых у меня есть некоторые опасения. Ваш код может работать, но вы также делаете больше, чем нужно, и не используете Laravel так, как он должен был использоваться.
Название модели
Ваша модель называется Items, но она должна быть единственной, Item. Это помогает Laravel автоматизировать работу, чтобы у вас было меньше работы.
https://laravel.com/docs/8.x/eloquent#eloquent-model-conventions
class Item extends Model {
Настройки базы данных
Вы установили атрибуты $table, $PrimaryKey и $connection, но они должны быть автоматическими. Вероятно, вы можете их удалить.
protected $table = 'items'; // assuming your model name is Item, this would automatically be 'items'
protected $primaryKey = 'id'; // default is already 'id'
protected $connection = 'mysql'; // default is your main db, probably already 'mysql', unless if you have multiple db connections
Метки времени
Я не уверен, почему вы хотите отключить метки времени. Вы определенно можете, но я всегда нахожу полезным знать, когда что-то было создано или обновлено в последний раз. Поскольку Laravel обрабатывает метки времени для вас, я бы предложил оставить его включенным, но это зависит от вас.
https://laravel.com/docs/8.x/eloquent#timestamps
public $timestamps = false;
Отношения с менеджером
Ваши отношения с менеджером-это getManager, но вы должны быть просто менеджером. Это все равно будет работать, но не так, как должен был работать Ларавель. Я бы предложил изменить его на manager () и не указывать имя столбца. Это автоматически сделает имя столбца manager_id, поэтому вам придется его обновить. Или вы можете сохранить имя столбца «идентификатор пользователя».
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-inverse
public function manager() {
return $this->belongsTo(User::class);
}
Отношения цессионариев
Так же, как и в отношениях с менеджером, вы должны изменить getAssignees() на assignees(). Я предполагаю, что у вас уже есть миграция базы данных, настроенная для вашей таблицы «item_user», которую будет искать Laravel. Если нет, проверьте документы Laravel о том, как его настроить.
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many
public function assignees() {
return $this->belongsToMany(User::class);
}
Извлечение Предметов
Наконец, с учетом вышеуказанных изменений получить все предметы должно быть легко. Чтобы загрузить отношения, используйте метод $with. Это называется Нетерпеливой загрузкой. Проверьте документы для получения дополнительной информации.
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading
$items = Item::with('manager','assignees')->get();
Возвращаемые Коды Ответов
Вы неправильно отвечали на свои ответы. Вам не нужно задавать код ответа 200, так как это значение по умолчанию. Если вы собираетесь установить его на что-то другое, поместите код в метод response() вместо метода json ().
https://laravel.com/docs/8.x/responses
return response()->json(['items' => $items]);
return response($err,400);
Теперь, собрав все это вместе, ваша модель изделия должна выглядеть примерно так:
class Item extends Model {
use HasFactory;
protected $fillable = ['manager_id', 'title', 'desc', 'start_datetime', 'due_datetime', 'priority', 'status'];
public function manager() {
return $this->belongsTo(User::class);
}
public function assignees() {
return $this->belongsToMany(User::class);
}
}
Ответ №2:
public function getall() {
try {
$items = Item::get()
->transform(function($el){
$el->manager = $el->getManager()->get();
);
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
Попробуйте применить метод преобразования к своим результатам, и он сработает.
https://laravel.com/docs/8.x/collections#method-transform
функция преобразования в основном будет просто повторять результаты и выполнять все, что ей скажут, как цикл for, но для коллекций.
Кроме того, чтобы сделать ваш запрос эффективным, избегайте загрузки отношения в функцию преобразования и используйте функцию laravel, чтобы сделать его эффективным