Я пытаюсь сделать Related_Products на одной странице продукта. Я хочу показать, что другие продукты имеют одинаковый идентификатор категории с сводной таблицей product_categories (product_id, category_id) Я много пробовал кода, но не могу этого сделать
Помогите пожалуйста, как мне это сделать? Большое спасибо.
хранилище продукта:
<?php
namespace App\Repositories;
use App\Models\Product;
use App\Traits\UploadAble;
use Illuminate\Http\UploadedFile;
use App\Contracts\ProductContract;
use Illuminate\Database\QueryException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
/**
* Class ProductRepository
*
* @package \App\Repositories
*/
class ProductRepository extends BaseRepository implements ProductContract
{
use UploadAble;
/**
* ProductRepository constructor.
* @param Product $model
*/
public function __construct(Product $model)
{
parent::__construct($model);
$this->model = $model;
}
/**
* @param string $order
* @param string $sort
* @param array $columns
* @return mixed
*/
public function listProducts(string $order = 'id', string $sort = 'desc', array $columns = ['*'])
{
return $this->all($columns, $order, $sort);
}
/**
* @param int $id
* @return mixed
* @throws ModelNotFoundException
*/
public function findProductById(int $id)
{
try {
return $this->findOneOrFail($id);
} catch (ModelNotFoundException $e) {
throw new ModelNotFoundException($e);
}
}
/**
* @param array $params
* @return Product|mixed
*/
public function createProduct(array $params)
{
try {
$collection = collect($params);
$featured = $collection->has('featured') ? 1 : 0;
$status = $collection->has('status') ? 1 : 0;
$merge = $collection->merge(compact('status', 'featured'));
$product = new Product($merge->all());
$product->save();
if ($collection->has('categories')) {
$product->categories()->sync($params['categories']);
}
return $product;
} catch (QueryException $exception) {
throw new InvalidArgumentException($exception->getMessage());
}
}
/**
* @param array $params
* @return mixed
*/
public function updateProduct(array $params)
{
$product = $this->findProductById($params['product_id']);
$collection = collect($params)->except('_token');
$featured = $collection->has('featured') ? 1 : 0;
$status = $collection->has('status') ? 1 : 0;
$merge = $collection->merge(compact('status', 'featured'));
$product->update($merge->all());
if ($collection->has('categories')) {
$product->categories()->sync($params['categories']);
}
return $product;
}
/**
* @param $id
* @return bool|mixed
*/
public function deleteProduct($id)
{
$product = $this->findProductById($id);
$product->delete();
return $product;
}
/**
* @param $slug
* @return mixed
*/
public function findProductBySlug($slug)
{
$product = Product::where('slug', $slug)->first();
return $product;
}
}
контроллер продукта:
<?php
namespace App\Http\Controllers\Site;
use Cart;
use DB;
use App\Models\Product;
use App\Models\Category;
use App\Models\Brand;
use App\Models\Order;
use Illuminate\Http\Request;
use App\Contracts\ProductContract;
use App\Http\Controllers\Controller;
use App\Contracts\AttributeContract;
use App\Contracts\OrderContract;
class ProductController extends Controller
{
protected $productRepository;
protected $attributeRepository;
protected $orderRepository;
public function __construct(ProductContract $productRepository, AttributeContract $attributeRepository, OrderContract $orderRepository)
{
$this->productRepository = $productRepository;
$this->attributeRepository = $attributeRepository;
}
public function index(Request $request)
{
$pagination = 2;
if (request()->sort == 'low_high') {
$products = Product::where('status', '1')->orderBy('price')->paginate($pagination);
} elseif (request()->sort == 'high_low') {
$products = Product::where('status', '1')->orderBy('price', 'desc')->paginate($pagination);
} else {
$products = Product::where('status', '1')->OrderBy('name', 'asc')->paginate($pagination);
}
return view('site.pages.products', compact('products' ));
}
public function search( Request $request) {
$request->validate([
'q' => 'required'
]);
$q = $request->q;
$filteredProducts = Product::where('name', 'like', '%' . $q . '%')->where('status', '1')->paginate(2);
if ($filteredProducts->count()) {
return view('site.pages.products')->with(
'products' , $filteredProducts
);
} else {
return redirect('/products')->with(
'status' , 'search failed ,, please try again'
);
}
}
public function show($slug, $id='')
{
$product = $this->productRepository->findProductBySlug($slug);
$attributes = $this->attributeRepository->listAttributes();
$productCategories=DB::table('product_categories')->get();
$products = Product::where('id', '!=' ,$product->id)->where('status','1')->orderby('id','desc')->get();
return view('site.pages.product', compact('product', 'attributes', 'productCategories', 'products'));
}
public function addToCart(Request $request)
{
$product = $this->productRepository->findProductById($request->input('productId'));
$options = $request->except('_token', 'productId', 'price', 'qty');
if($product->quantity<1){
return redirect()->back()->with('error', 'Cant add Item to cart.');
}
Cart::add(uniqid(), $product->name, $request->input('price'), $request->input('qty'), $options);
return redirect()->back()->with('message', 'Item added to cart successfully.');
}
}
product.blade. php:
@extends('site.app')
@section('title', $product->name)
@section('content')
<section class="section-pagetop bg-dark">
<div class="container clearfix">
<h2 class="title-page">{{ $product->name }}</h2>
</div>
</section>
<section class="section-content bg padding-y border-top" id="site">
<div class="container">
@if( session('message'))
<div class="alert alert-success">
{{ session('message')}}
</div>
@endif
@if( session('error'))
<div class="alert alert-danger">
{{ session('error')}}
</div>
@endif
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="row no-gutters">
<aside class="col-sm-5 border-right">
<article class="gallery-wrap">
@if ($product->images->count() > 0)
<div class="img-big-wrap">
<div class="padding-y">
<a href="{{ asset('storage/'.$product->images->first()->full) }}" data-fancybox="">
<img src="{{ asset('storage/'.$product->images->first()->full) }}" alt="">
</a>
</div>
</div>
@else
<div class="img-big-wrap">
<div>
<a href="https://via.placeholder.com/176" data-fancybox=""><img src="https://via.placeholder.com/176"></a>
</div>
</div>
@endif
@if ($product->images->count() > 0)
<div class="img-small-wrap">
@foreach($product->images as $image)
<div class="item-gallery">
<img src="{{ asset('storage/'.$image->full) }}" alt="">
</div>
@endforeach
</div>
@endif
</article>
</aside>
<aside class="col-sm-7">
<article class="p-5">
<h3 class="title mb-3">{{ $product->name }}</h3>
<dl class="row">
<dt class="col-sm-3">SKU</dt>
<dd class="col-sm-9">{{ $product->sku }}</dd>
<dt class="col-sm-3">Weight</dt>
<dd class="col-sm-9">{{ $product->weight }}</dd>
</dl>
<div class="mb-3">
@if ($product->sale_price > 0)
<var class="price h3 text-danger">
<span class="currency">{{ config('settings.currency_symbol') }}</span><span class="num" id="productPrice">{{ $product->sale_price }}</span>
<del class="price-old"> {{ config('settings.currency_symbol') }}{{ $product->price }}</del>
</var>
@else
<var class="price h3 text-success">
<span class="currency">{{ config('settings.currency_symbol') }}</span><span class="num" id="productPrice">{{ $product->price }}</span>
</var>
@endif
</div>
<hr>
<form action="{{ route('product.add.cart') }}" method="POST" role="form" id="addToCart">
@csrf
<div class="row">
<div class="col-sm-12">
<dl class="dlist-inline">
@foreach($attributes as $attribute)
@php $attributeCheck = in_array($attribute->id, $product->attributes->pluck('attribute_id')->toArray()) @endphp
@if ($attributeCheck)
<dt>{{ $attribute->name }}: </dt>
<dd>
<select class="form-control form-control-sm option" style="width:180px;" name="{{ strtolower($attribute->name ) }}">
<option data-price="0" value="0"> Select a {{ $attribute->name }}</option>
@foreach($product->attributes as $attributeValue)
@if ($attributeValue->attribute_id == $attribute->id)
<option
data-price="{{ $attributeValue->price }}"
value="{{ $attributeValue->value }}"> {{ ucwords($attributeValue->value . ' +'. $attributeValue->price) }}
</option>
@endif
@endforeach
</select>
</dd>
@endif
@endforeach
</dl>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-12">
<dl class="dlist-inline">
<dt>Availability: </dt>
<dd>
@if($product->quantity==0)
<span class="badge badge-danger"> Not In stock</span>
@else
<span class="badge badge-success"> In stock</span>
@endif
</dd>
</dl>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<dl class="dlist-inline">
<dt>Availability: </dt>
<dd>
{{ $product->quantity<1 ? 'No Item is available' : $product->quantity.' item in stock' }}
</dd>
</dl>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-12">
<dl class="dlist-inline">
<dt>Quantity: </dt>
<dd>
<input class="form-control" type="number" min="0" value="0" max="{{ $product->quantity }}" name="qty" style="width:70px;">
<input type="hidden" name="productId" value="{{ $product->id }}">
<input type="hidden" name="price" id="finalPrice" value="{{ $product->sale_price != '' ? $product->sale_price : $product->price }}">
</dd>
</dl>
</div>
</div>
<hr>
<button type="submit" class="btn btn-success"><i class="fas fa-shopping-cart"></i> Add To Cart</button>
</form>
</article>
</aside>
</div>
</div>
</div>
<div class="col-md-12">
<article class="card mt-4">
<div class="card-body">
{!! $product->description !!}
</div>
</article>
</div>
</div>
</div>
</section>
<section class="section-content padding-y-sm bg">
<div class="container">
<header class="section-heading heading-line">
<h4 class="title-section bg">RELATED PRODUCTS</h4>
</header>
<div class="row">
@foreach($products as $product)
<div class="col-md-2">
<figure class="card card-product">
@if ($product->images->count() > 0)
<div class="img-wrap padding-y"><img src="{{ asset('storage/'.$product->images->first()->full) }}" alt=""></div>
@else
<div class="img-wrap padding-y"><img src="https://via.placeholder.com/176" alt=""></div>
@endif
<figcaption class="info-wrap">
<h4 class="title"><a href="{{ route('product.show', $product->slug) }}">{{ $product->name }}</a></h4>
</figcaption>
<div class="bottom-wrap">
<a href="{{ route('product.show', $product->slug) }}" class="btn btn-sm btn-success float-right">View Details</a>
@if ($product->sale_price != 0)
<div class="price-wrap h5">
<span class="price"> {{ config('settings.currency_symbol').$product->sale_price }} </span>
<del class="price-old"> {{ config('settings.currency_symbol').$product->price }}</del>
</div>
@else
<div class="price-wrap h5">
<span class="price"> {{ config('settings.currency_symbol').$product->price }} </span>
</div>
@endif
</div>
</figure>
</div>
@endforeach
</div>
<!-- row.// -->
</div>
<!-- container .// -->
</section>
@stop
@push('scripts')
<script>
$(document).ready(function () {
$('#addToCart').submit(function (e) {
if ($('.option').val() == 0) {
e.preventDefault();
alert('Please select an option');
}
});
$('.option').change(function () {
$('#productPrice').html("{{ $product->sale_price != '' ? $product->sale_price : $product->price }}");
let extraPrice = $(this).find(':selected').data('price');
let price = parseFloat($('#productPrice').html());
let finalPrice = (Number(extraPrice) + price).toFixed(2);
$('#finalPrice').val(finalPrice);
$('#productPrice').html(finalPrice);
});
});
</script>
@endpush
Модель продукта:
<?php
namespace App\Models;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
/**
* @var string
*/
protected $table = 'products';
/**
* @var array
*/
protected $fillable = [
'brand_id', 'sku', 'name', 'slug', 'description', 'quantity',
'weight', 'price', 'sale_price', 'status', 'featured',
];
/**
* @var array
*/
protected $casts = [
'quantity' => 'integer',
'brand_id' => 'integer',
'status' => 'boolean',
'featured' => 'boolean'
];
/**
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = $value;
$this->attributes['slug'] = Str::slug($value);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function categories()
{
return $this->belongsToMany(Category::class, 'product_categories', 'product_id', 'category_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function images()
{
return $this->hasMany(ProductImage::class);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function brand()
{
return $this->belongsTo(Brand::class);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function attributes()
{
return $this->hasMany(ProductAttribute::class);
}
}
Категория Модель:
<?php
namespace App\Models;
use App\Models\Product;
use TypiCMS\NestableTrait;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
use NestableTrait;
/**
* @var string
*/
protected $table = 'categories';
/**
* @var array
*/
protected $fillable = [
'name', 'slug', 'description', 'parent_id', 'featured', 'menu', 'image'
];
/**
* @var array
*/
protected $casts = [
'parent_id' => 'integer',
'featured' => 'boolean',
'menu' => 'boolean'
];
/**
* @param $value
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = $value;
$this->attributes['slug'] = Str::slug($value);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function children()
{
return $this->hasMany(Category::class, 'parent_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function parent()
{
return $this->belongsTo(Category::class, 'parent_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products()
{
return $this->belongsToMany(Product::class, 'product_categories', 'category_id', 'product_id');
}
}
Таблица product_categories:
'product_categories', 'category_id', 'product_id'