Eloquent - check if id exists on distant relation - laravel

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();

Related

Laravel HasManyThrough CrossDatabaseRelation

strange question:
I have 3 Models
Order
with id as PK
Orderline
with id as PK and order_id as FK. brand and partnumber are two separatet colums
Article
with combined PK brand and partnumber
**which is on another database **
One Order hasMany Orderlines. Every Orderline hasOneArticle.
i had make a function within order:
public function articles()
{
$foreignKeys = [
'brand_id',
'article_number',
];
$localKeys = [
'brand',
'partnumber',
];
return $this->hasManyThrough('App\Models\Masterdata\Articles','App\Models\Oms\OrderLine',$foreignKeys,$localKeys,'id','id');
}
How can i retrieve all Attributes from articles through Order?
I tried something like this:
$order = Order::find($orderid)->articles();
dd($order);
//did not work
$order = Order::with('orderlines.articles')->where('id','=',$orderid)->get();
Do you have an idea for me?
You can configure more than one database in the database.php config, and specify the $connection name in the Model class.
For the most part, Eloquent doesn't do JOINs, it just does IN statements on the key values from the preceding query, and programmatically marries the results together after the fact. Partly to avoid the mess of keeping table aliases unique, and partly to offer this kind of support- that your relations don't need to live in the same database.
In other words, what you have there should work just fine. If there's a specific error getting thrown back though, please add it to your post.

Broken Eloquent relationship with extended model

I have a model Asset with documents() { $this->hasMany(Document::class); } through a table data_asset_document. I extend Asset into multiple models, one of which is Equipment. In my seeder for Equipment, I attempt to create a Document bound to the Equipment record:
$asset = Equipment::create([...]);
$document = Document::create([
'name' => "$type Purchase Order",
'tracking_number' => app('incrementer')->current()
]);
$asset->documents()->save($document);
Eloquent produces this query:
update `data_document` set `equipment_id` = 1, `data_document`.`updated_at` = 2019-09-20 14:39:48 where `id` = 1
This is obviously incorrect, since data_document does not have an equipment_id column (Documents "belong to" several models besides Asset). How do I rewrite Asset::documents so that produces the correct mapping, even in its extensions? Or do I need to save my Document through a means other than Asset::documents?
Since your extended asset model is called Equipment, Laravel expects your foreign key to be called equipment_id. You will need to specify the actual foreign key of asset_id in your relationship.
https://laravel.com/docs/6.x/eloquent-relationships#one-to-many
hasMany
documents() {
$this->hasMany(Document::class, 'asset_id');
}
The problem is, I'm not convinced your relationship is really hasMany since you mention what looks like a pivot table data_asset_document as being involved. Many-to-many relationships, like mentioned in your title, would use the belongsToMany method.
https://laravel.com/docs/6.x/eloquent-relationships#many-to-many
https://laravel.com/docs/6.x/eloquent-relationships#has-many-through

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 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'));

Eloquent - Two Relationships In One?

I've been getting along slowly but surely with Laravel / Eloquent, but am now stumped:
entries Table:
id
user_id
group_id
content
users Table
id
faculty_id
name
group Table:
id
name
faculty Table
id
name
So entries are related to users and groups, and users are related to faculties - I've set up the basic relationships without a problem, and this enables me to find all entries by users from a certain faculty:
Faculty Model:
public function entries()
{
return $this->hasManyThrough('Entry','User');
}
Controller:
Faculty::find(Faculty-ID-here)->entries;
However, I now need to find entries by users that are from a certain faculty AND from a certain group, and I don't know how to write this combination this in Eloquent.
Hope that makes sense! Any suggestions?
Something like:
Entries::whereHas('user', function($q) {
$q->where('faculty_id', $facultyID);
})
->where('group_id', $groupID)
->get();
Assuming you have set up your 'user' relationship.

Resources