#php #laravel #eloquent #laravel-blade #laravel-7
#php #laravel #красноречивый #laravel-blade #laravel-7
Вопрос:
У меня есть 2 таблицы: Продукты и изображения.
У каждого продукта есть много изображений (через внешний ключ product_id)
*product_id, product_title*
1, "Product 1"
2, "Product 2"
3, "Product 3"
4, "Product 4"
*image_id, product_id(foreign key), image_url, created_at*
25, 1, "/filename_xyz", '5:00'
26, 1, "/filename_abc", '5:30'
27, 2, "/filename_def", '6:30'
28, 1, "/filename_abc", '7:00'
29, 3, "/filename_def", '8:00'
У меня есть контроллер, который возвращает все продукты в мое представление.
ProductController.php
public function index(){
$data_to_return = Product::orderby('product_id', 'DESC')->paginate(10);
return view('product.index', [
'product_data' => $data_to_return,
]);
}
Этот контроллер загружается в view корректно product.index.
Я успешно перебираю результаты в моем блейд-файле следующим образом:
@foreach($product_data as $product)
{{ $product->product_title }}
<!--however, I would like to also print one of the images linked to a product-->
@endforeach
У меня возникли проблемы с планированием «ссылки» или «присоединения» к изображению. Для продукта с product_id=1 в базе данных изображений имеется несколько записей. Я хотел бы, чтобы мое представление отображало информацию о продукте из таблицы Products, а также ТОЛЬКО ОДНО изображение из таблицы Images (соответствующее product_id). В моем случае мне нужен первый результат (или ограничение 1) при заказе с помощью created_at ASC.
Пример: Продукт 1 отобразил бы в моем представлении image_url «/filename_xyz», потому что он был создан первым из изображений с product_id = 1
Я думал, что решение может быть примерно таким:
Зациклите массив продуктов:
@foreach($product_data as $product)
{{ $product->product_title }}
<!-- And calling a controller like -->
{{Image::mainImage($product->id)}}
<!-- Where mainImage returns the image_url I am looking for-->
@endforeach
или
Улучшаю свою модель, сначала определенным образом соединяю таблицы, что делает то, о чем я упоминал ранее, показывая только одно изображение, которое меня интересует. Я не могу понять, как добиться этого с помощью наилучшей практики Laravel / Eloquent.
Комментарии:
1. {{ $product->image_url[0] }}
Ответ №1:
Вот где пригодились бы красноречивые взаимосвязи!
Взаимосвязь ваших моделей должна напоминать эту настройку;
class Product extends Model
{
public function image()
{
return $this->hasOne('your/path/to/image/model');
}
}
class ProductImage extends Model
{
public function product()
{
return $this->belongsTo('your/path/to/product/model');
}
}
И при правильной настройке вы бы сделали что-то вроде <img src="{{ $product->image->image_url }}">
для отображения изображения продукта. Это предполагает, что у вас есть только одно изображение для каждого продукта.
При ваших миграциях, скажем, при вашей product_images
миграции таблиц, вы должны написать $table->foreignId('product_id')->constrained();
, и Laravel автоматически узнает, где искать соответствующую запись изображения.
Комментарии:
1. Спасибо за объяснение! Как бы вы подошли к проблеме, когда у вас есть несколько изображений, связанных с одним и тем же product_id, но возвращающих только первую найденную строку изображения, а не остальные изображения (изображение будет: order by ‘created_at’ ASC LIMIT 1).
2. Если у вас их более одного
product_image
наproduct
строку, то я бы обновил приведенную выше взаимосвязь Product сhasOne
наhasMany
, и вы могли бы вызвать$product->images::first()
. Я полагаю, что именно так это и будет работать, я еще не тестировал это, имейте в виду, но это должно быть приблизительной идеей