Laravel Sort hasMany relationship by Array values - php

I have this method in a Model called Category, that brings all products from certain Category.
Model:
public function products()
{
return $this->hasMany(Product::class);
}
What I would like is put these products in order based on Array with IDs.
I tried this but didn't work:
public function products()
{
if ( !is_null($this->products_order)) {
$order = json_decode($this->products_order, true);
$products = $this->hasMany(Product::class)->orderBy('id',...$order);
return $products;
}
return $this->hasMany(Product::class);
}
$this->products_order is a Array of IDs.

Related

Laravel - how to use model's ID inside belongs to many relationship query?

Models:
Products
Variants
VariantValue
// Product.php
public function variants()
{
return $this->belongsToMany(Variant::class, 'product_variant', 'product_id', 'variant_id')
->with([
'values' => function ($builder) {
return $builder->whereHas('products', function ($q) {
return $q->where('products.id', $this->id);
});
},
]);
}
// Variant.php
public function values()
{
return $this->hasMany(VariantValue::class);
}
// VariantValue.php
public function products()
{
return $this->belongsToMany(Product::class, 'product_variant_value', 'variant_value_id', 'product_id');
}
The above works if we do the following:
Product::first()->variants()->get()->toArray()
But, it doe NOT work if we do the following (the values array is empty):
Product::with('variants')->get()->toArray()
Meaning the issue is that the product ID is not available inside the belongs to many query:
return $q->where('products.id', $this->id);
Any idea how I can make this work? The goal is to load relationship using:
Product::with('variants')->get()

How to get only active element from many to many relationship with translation in laravel

I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
I get the results by this:
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
but I want to get only the active accessories something like where accessori.active = 1 but I really don't know where to put it. I've tried in different way but I'm stuck on it by 2 days.
IIRC you don't need a model for the intermediate table on your many to many relationships.
If you want to return Products where Accessori is active you can use whereHas on the Product model.
$prod = Product::whereHas('accessori', function($query) {
$query->where('active', 1);
})->get();
Where the $query param will be running on the Accessori model.
You can do the inverse as well with Accessori to Product.
$acessoris = Accessori::where('active', 1)->whereHas('accessoriProduct')->with(['accessoriLang', 'accessoriProducts.productsLang'])->get();

get extra data in Many To Many eloquent-relationships in laravel

I create a table like this:
posts
id title
categories
id name
category_post
post_id
category_id
custom_value
in Category model:
public function posts()
{
return $this->belongsToMany(Post::class);
}
with this command:
$category = Category::find(1);
$posts = $category->posts()->get();
I can get all of posts.
It is possible to return custom_value in category_post with each related post?
Use withPivot function
class Category extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class)->withPivot('custom_value');
}
}
You can use withPivot() method
return $this->belongsToMany(Post::class)
public function posts()
{
return $this->belongsToMany(Post::class)->withPivot('column1','column2');
}
or
public function categories()
{
return $this->belongsToMany(Category::class)->withPivot('column1','column2');
}

Want to fetch data from three tables in laravel 5.2

I have a little query in which I need your help, Please have a look below.
I want to fetch all the data from the products table with some conditions like city, price, Type, category.
I can fetch all the data but I can't fetch the category data from the product model with all other conditions.
Below is my tables and Eloquent relations. I am using Laravel 5.2.
products ->foreign_key('subcategory_id')
subcategories ->foreign_key('category_id')
category
users: ->foreign_key('product_id')
users table columns: ->city, price, product_id
Relations:
User Model:
public function product(){
return $this->hasMany('App\Product');
}
Product Model:
public function subcategory(){
return $this->belongsTo('App\Subcategory', 'subcategory_id');
}
Subcategory Model:
public function product(){
return $this->hasMany('App\Product', 'subcategory_id');
}
public function category(){
return $this->belongsTo('App\Category');
}
Category Model:
public function subCategory(){
return $this->hasMany('App\Subcategory');
}
public function product(){
return $this->hasManyThrough('App\Product', 'App\Subcategory');
}
Here is my query(in ProductsController.php).
$city_id, $category_id, $min_price, $max_price : demo data passed
//fetching city data
$products = Product::whereHas('user', function($query) use($city_id) {
$query->where('city_id', $city_id);
});
//fetching category data (I am not sure about this part)
$products = $products->whereHas('category', function($query) use($category_id) {
$query->where('id', $category_id);
});
//fetching price data
$products = $products->where('price', '>=', $min_price)->where('price', '<=', $max_price);
//sub category filtering
$products = $products->where('subcategory_id', 1);
$products = $products->get()->toArray();
return $products;
Any help would be appreciated. Thanks in Advance.
I think you can use with() method:
Product Model:Add the following method
public function subcategory($category_id){
return $this->belongsTo('App\Subcategory', 'subcategory_id')->with(`category`)->where('category_id',$category_id);
}
Now in Controller, you can check if the product belongs to that category,
$products = $products->subcategory($category_id);
This will get you category data also.

Laravel unify multiple relations into one

In my application there are three models: User, Product and Retailer. A user can optionally be associated with one Retailer.
Each Product belongs to one User and optionally one Retailer.
Users should then be able to access all Products that belong to them, as well as all products that belong to the retailer they are associated with (if any).
Basically what this means is that I need to create two relations and somehow unify them.
public function products()
{
// Via column `user_id` in products table
return $this->hasMany('App\Product');
}
// And:
public function products()
{
// Via column `user_id` in products table
return $this->hasManyThrough('App\Product', 'App\Retailer');
}
How am I able to unify these two relations into one?
// User model
public function products()
{
return $this->hasMany('App\Product');
}
public function retailer()
{
return $this->belongsTo('App\Retailer');
}
// Product model
public function user()
{
return $this->belongsTo('App\User');
}
public function retailer()
{
return $this->belongsTo('App\Retailer');
}
// Retailer Model
public function products()
{
return $this->hasMany('App\Product');
}
public function users()
{
return $this->hasMany('App\User');
}
Usage:
// with one user
$user = User::find(1);
$retailerProducts = $user->retailer->products;
foreach( $retailerProducts as $product )
{
echo $product->id;
}
// When getting multiple users, use eager loading to get all products in one query
$users = User::with('retailer.products')->get();
foreach( $users as $user )
{
foreach( $user->retailer->products as $product )
{
echo $product->id;
}
}

Categories