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;
}
}
Related
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.
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();
I have relationship on User model like below:
public function brands() {
$roles = config('constants.roles');
if ($this->hasRole($roles['brand_site_admin'])) {
return $this->belongsToMany(Brand::class, 'brand_has_users');
} else
if ($this->hasRole($roles['client_admin'])) {
return $this->belongsToMany(Brand::class, 'brand_has_client_admin');
}
// For admin role I want to return all brands, from Brand Model
// ??
}
For Admin role I want to return all rows from Brand model, How can I get that?
And that should be instance of BelongsToMany class, then only it won't break code in my controller.
Update:
When I do $user->brands() I want all the brands from brands table if $user is an admin (In above code if it doesn't goes in any condition then it's Admin).
I think you should try this as suggested in this SO post, first create the relationships like this
$roles = config('constants.roles');
public function siteAdminBrands()
{
return $this->hasMany(Brand::class, 'brand_has_users');
}
public function clientAdminBrands()
{
return $this->hasMany(Brand::class, 'brand_has_client_admin');
}
public function brands($query)
{
return $query
->when($this->hasRole($roles['brand_site_admin']),function($q){
return $q->with('siteAdminBrands');
})
->when($this->hasRole($roles['client_admin']),function($q){
return $q->with('clientAdminBrands');
});
}
}
I have 3 models named "User","Order","Orders_products". The relations are following:
User has many Order
Order has many Orders_products
Here are the model's code
User Model
public function order(){
return $this->hasMany('App\Order');
}
Order Model
public function order_product(){
return $this-> hasMany('App\Orders_product');
}
public function user(){
return $this-> belongsTo('App\User');
}
Orders_products Model
public function order(){
return $this->belongsTo('App\Order');
}
An user could have multiple orders and all orders could have multiple ordered products. How can i get a particular users all orders along with the ordered products.
User model
public function order()
{
return $this->hasMany(Order::class);
}
Order Model
public function user()
{
return $this->hasOne(User::class);
}
public function orders_products()
{
return $this->belongsToMany(Orders_products::class);
}
Orders_products
public function order()
{
return $this->belongsToMany(Order::class);
}
This should work, $userid is how ever you specify the user id in your app.
User::with('order_product.order')->where('id', $usersid)->get();
$Order = Order::with('order_product')->where(['user_id'=>$id])->get();
where $id is the user_id
I have the following models: User, Device, Product.
User
public function devices()
{
return $this->hasMany('App\Device');
}
Device
public function user()
{
return $this->BelongsTo('App\User');
}
public function reading()
{
return $this->hasMany('App\Reading', 'device_id', 'part_id');
}
public function product()
{
return $this->hasOne('App\Product');
}
Product
public function device()
{
return $this->belongsTo('App\Device');
}
The following query pulls my users and all their devices, but inside that collection is not the relation from device to product.
$deviceSingles = User::with('devices')->get();
This query gets me all the products with all devices assigned to it
$deviceSinglesTwo = Product::with('device')->get();
How do I get that third relation, attached to my initial query so i can do this
$deviceSingles->device->product->title
Use nested eager loading.
To eager load nested relationships, you may use "dot" syntax.
User::with('devices.product')->get()