How to query models where relationship is null in Strapi? - strapi

I have a model Category with a belongs to many relationship with itself:
Category has many categories in subcategories
Category belongs to one category in supercategory
When I query all categories I get the correct results:
strapi.services.category.find()
When I query all subcategories I also get the correct results:
strapi.services.category.find({ supercategory_null: false })
But when I query just supercategories it doesn't return any categories:
strapi.services.category.find({ supercategory_null: true })
Question
How can I query just the categories that have no supercategory relationship?

This should work
strapi.services.category.find({ supercategory_null: true },['category']);
Defination:
find(params, populate)
populate (array): you have to mention data you want populate e.g ["author", "author.name", "comment", "comment.content"]

The solution I found is to use knex instead of the strapi api:
// Assuming your table name is `category`
const knex = strapi.connections.default;
const categories = await knex(`category`).select(`*`).where(`supercategory`, null);

Related

belongsToMany with nullable foreign - Laravel 5.8

in my Laravel project i get this database structure:
Products
Id
Name
Orders
Id
Total
Order_Product
Product_id (nullable)
Order_Id
Details
In my Order model I make belongsToMany retaltionship with Product model:
public function products() {
return $this->belongsToMany(Product::class)->withPivot('Details');
}
The Problem is when I try to get the Order Products Collection
$order->products();
I don't get rows with nullable product_id, Any solution please ? Thank you.
Laravel support "Null Object Pattern" since version 5.5 which allows you to define a default model that will be returned if the given relationship is null.
Try using the following code:
public function products() {
return $this->belongsToMany(Product::class)->withDefault()->withPivot('Details');
}
Most likely, you don't get "nullable" products because you have a relation Order->Products. When you call $order->products(), eloquent tries to get all Product entities that are connected to your Order via product_id field. So, if field is empty, then you can't get Product because there is no connection.
One of the solutions is:
create another entity like OrderLine(Order_Product table); add methods like $orderLine->details() and relation to Product like $orderLine->product()
add relation to OrderLine inside Order - $order->line() or $order->info() etc. -> Order hasMany OrderLine
then use $order->line() to get an order's details and products (if exists)
p.s. I've compiled it in my head so it might need some code adjustments.
Good luck

Eloquent - check if id exists on distant relation

I need to check if a country id exists on a distant relation to a product. I only need a true or false as result. I haven't figured out how to put the query. The different relations are defined in each model:
Product - belongsToMany ShippingProfile
ShippingProfile - hasMany Methods
Method - belongsTo ShippingZone
ShippingZone - belongsToMany Countries
So if I have product id 2, and country id 5, I want to find out if the country id is available in any zone within any of the methods belonging to the profile of the product. (actually it is only one profile per product but it is defined as belongsToMany with a pivot table).
I tried to get access to countries as a first step, but I can't get access to it by using this syntax:
$prod = \App\Product::find(2)
->shipping_profiles()
->methods()->zones()->countries();
I get the error: "Call to undefined method Illuminate\\Database\\Query\\Builder::methods()
(methods() is correctly defined in shippingProfiles though).
Edit2:
Using "with", I can do a "where" check on the countries, but if I provide a non existing country, it doesn't fail - it just returns the product with the properties and a zone with an empty countries array:
return $prod = \App\Product::find(2)->with([
'shipping_profiles.methods.zone.countries' => function($query) {
$query->where('countries.id', 10000);
}])->firstOrFail();
So if you can advice any other method that will return either true/false or return the zone or null, that's what I'm looking for..
Use whereHas():
return $prod = \App\Product::whereKey(2)->whereHas(
'shipping_profiles.methods.zone.countries', function($query) {
$query->where('countries.id', 10000);
})->firstOrFail();

Laravel sort by pivot table column

I am trying to sort an eloquent query in laravel by a column from the pivot table.
Basically as long as the product is favorited by the user, it is added to the pivot table, and it should first show the favorited ones, and then the remaining ones. Since I will be using foreach in the blade.
products table contains these columns:
id, category, product_name, priority, status, created_at, updated_at
users table contains these columns:
id, name, email, created_at, updated_at
with the following in the users model:
public function favorites()
{
return $this->belongsToMany(Products::class, 'favorites', 'user_id', 'product_id')
->withTimeStamps();
}
favorites table contains these columns:
id, user_id, product_id, created_at, updated_at
In the controller, the eloquent query is currently:
$productinprogress = Products::all()
->sortByDesc("priority")
->where('status', 'inprogress');
I am just confused as to how to tackle this.
Your help is appreciated. Thank you so much.
I think you should make two queries to avoid loading duplicate products, first one for favorite products, second one should be some thing like this:
Products::all()->sortByDesc("priority")->where('status', 'inprogress')->whereNotIn('id', $favorite_products);
and then in the blade file, you make two foreach, first one for favorites, and 2end for others.
you can use something like bellow:
$productinprogress = Products::all()
->where('status', 'inprogress')
->sortByDesc("priority");
and if you want an efficient solution using eager loading and loading favorites too, use following code
$productinprogress = Products::all()
->with('favorites')
->where('status', 'inprogress')
->sortByDesc("priority");

How to connect some table in Laravel?

I have the some tables: Orders, Products, ProductsImages.
I try to get all orders:
$orders = Orders::with("Products")->with("images")->get();
So relationship is:
Orders.product_id = Products.id
Products.id = ProductsImages.product_id
I want to connect these tables in one request
through Order model.
You want to use many-to-many relation between orders and products and one-to-many relation between products and productsImages
Just setup these relationships as described in documentation and load data using nested eager loading:
Orders::with('products.productsImages')->get();

eloquent filter result based on foreign table attribute

I'm using laravel and eloquent.
Actually I have problems filtering results from a table based on conditions on another table's attributes.
I have 3 tables:
venue
city
here are the relationships:
a city has many locations and a location belongs to a city.
a location belongs to a venue and a venue has one location.
I have a city_id attribute on locations table, which you may figured out from relationships.
The question is simple:
how can I get those venues which belong to a specific city?
the eloquent query I expect looks like this:
$venues=Venue::with('location')->where('location.city_id',$city->getKey());
Of course that's not gonna work, but seems like this is common task and there would be an eloquent command for it.
Thanks!
A couple of options:
$venues = Venue::whereIn('location_id', Location::whereCityId($city->id)->get->lists('id'))
->get();
Or possibly using whereHas:
$venues = Venue::whereHas('location', function($query) use ($city) {
$query->whereCityId($city->id);
})->get();
It is important to remember that each eloquent query returns a collection, and hence you can use "collection methods" on the result. So as said in other answers, you need a Eager Loading which you ask for the attribute you want to sort on from another table based on your relationship and then on the result, which is a collection, you either use "sortBy" or "sortByDesc" methods.
You can look at an example below:
class Post extends Model {
// imagine timpestamp table: id, publish, delete,
// timestampable_id, timestampble_type
public function timestamp()
{
return $this->morphOne(Timestamp::class, 'timestampable');
}
}
and then in the view side of the stuff:
$posts = App\Post::with('timestamp')->get(); // we make Eager Loading
$posts = $posts->sortByDesc('timestamp.publish');
return view('blog.index', compact('posts'));

Resources