Laravel query with eloquent - php

Good morning.
I have a question that I can't solve with eloquent, let me put it in context.
I have several farms I need all the subscribers of that farm that are taken out through a pivot table and in turn all the receipts of those subscribers, so far so good.
The problem comes in that I put a condition in the dates of the receipts, and I want that it does not extract the subscribers that do not fulfill that condition.
$estates = Estate::with(['adminEstate.neighbours' => function ($query) use ($past_date_init) {
$query->with(['receiptHeader' => function ($query2) use ($past_date_init) {
$query2
->where('receipt_h_billing_init', '<=', $past_date_init)
->where('receipt_h_billing_end', '>=', $past_date_init);
$query2->with('receiptDetail');
}
]);
}])->get();
If they do not meet the date condition, I will not be able to get the subscribers.
Thanks for your help

Well for now you can use
query2
->whereDate('receipt_h_billing_init', '<=', $past_date_init)
->whereDate('receipt_h_billing_end', '>=', $past_date_init);
query2
->whereBetween(DB::raw('Date(receipt_h_billing_init)'),[$past_date_init, $past_date_init]);
as you can see here I didn't use whereBetween because it will compare also the time the first one will work fine

Related

How to use specific element of one to many relationship in whereHas (Laravel)

I want to get data list , which has many relational rows in another table.
I need to check specific row of relational rows for getting data list from first, for example with it can be the first one and second ... (some conditions), but in whereHas you know that we are checking all elements.
$shipments->whereHas('shipment_stops', function ($q) use ($startDate) {
$q->where('departure_date', '>=', $startDate) ;
});
This will check all shipment_stops, but I want to check only the last stop with the specific type (for example).
I know that maybe I can create better structure in DB, but anyway, I have this structure.
Thanks
Use Has One Of Many
public function latestShipmentStop()
{
return $this->hasOne(ShipmentStop::class)->latestOfMany();
}
..
$shipments->whereHas('latestShipmentStop', function ($q) use ($startDate) {
$q->where('departure_date', '>=', $startDate) ;
});

loading relationship with groupBy laravel

I have a query which selects some relationships and groups by the accommodations to remove the duplicate accommodations. But now when I want to load the discount realtion on rooms, it doesn't work because I select only the accommodation_id.
Here is my code:
$data = AccommodationRoom::with('accommodation.city', 'accommodation.accommodationFacilities', 'accommodation.gallery','discount')
->select('accommodation_id')
->whereHas('roomCapacityHistory', function ($query) use ($from_date, $to_date) {
$query->whereDate('from_date', '<=', $from_date);
$query->whereDate('to_date', '>=', $to_date);
})
->whereHas('accommodation', function ($query) use ($searchCity) {
$query->where('city_id', $searchCity);
})
->groupBy('accommodation_id')
->get();
Now if I add the id to the select it would be fine, but my groupBy doesn't work and gives me an error in this case. So I need a solution to get all my accomodations with the listed relations.
As you are looking for all your accommodations with some related models, you should actually select from your Accommodation model. This will work out of the box for the first three relations but will require some tweaking for the discount relation. The simpliest solution is to create a HasManyThrough relation on the Accommodation model:
class Accommodation extends Model
{
public function discounts()
{
return $this->hasManyThrough(Discount::class, AccommodationRoom::class);
}
}
Note: this expects your models to use foreign key columns named by convention; for different names you will need to pass the custom foreign key names as additional parameters according to the documentation.
With this relation set up, you can then use a query like the following:
$data = Accommodation::with('city', 'accommodationFacilities', 'gallery', 'discounts')
->whereHas('accommodationRooms.roomCapacityHistory', function ($query) use ($from_date, $to_date) {
$query->whereDate('from_date', '<=', $from_date);
$query->whereDate('to_date', '>=', $to_date);
})
->where('city_id', $searchCity)
->get();
Further explanation as asked for in the comments:
HasManyThrough builds a virtual relation between two models using a third model in between. Imagine you have Post, Comment and Like as models. One Post can have many Comments and one Comment can have many Likes:
has many has many
Post -----------------> Comment -----------------> Like
1 n 1 n
In this case we also know that one Post can have many Likes. And this is exactly the knowledge we utilize when using HasManyThrough. We simply tell Eloquent that a Post has many Likes, connected by the Posts in between:
has many has many
Post -----------------> Comment -----------------> Like
1 n 1 n
has many through Comment
Post ------------------------------------------------> Like
1 n

Add where clause to relations table in laravel

I have a question. This query gets me the needed data and that includes the related table delivery
$RS = $this->instance->user()->with(['driver.trailer', 'driver.truck', 'driver.delivery']);
I researched this topic, and I think part below should do the trick, but I don't know how to combine the two together.
//add WHERE clause to driver.delivery:
->whereBetween('created_at', [
Carbon\Carbon::parse('last monday')->startOfDay(),
Carbon\Carbon::parse('next sunday')->endOfDay(),])
->get();
I am new to Laravel (doing it for about 10 days now) and this concept is very new to me. (I have no issues writing a standard query)
Try this:
return $this->instance->user()->with(['driver.delivery' => function($query){
$query->whereBetween('created_at', [
Carbon\Carbon::parse('last monday')->startOfDay(),
Carbon\Carbon::parse('next sunday')->endOfDay() ]);
}])->with(['driver.trailer' 'driver.truck'])->get();

Eloquent eager loaded query not quite working with joins

I'm working on a Chemical database and am learning Eloquent as I go. This is in Slim Framework, not Laraval itself.
This thread helped get me close to what I need, but now I'm seeing something odd and I haven't been able to find a solution, though lots of people asking similar questions.
I have
$chemicals = $app->Chemical->with(array('Company', 'Room', 'Location', 'Measurement'))
->join('company', 'company_id', '=', 'company.id')
//->join('room', 'room_id', '=', 'room.id')
//->join('location', 'location_id', '=', "location.id")
->where('company', '=', 'ROUSSEL')
->get();
Notice the 2 Joins commented out. Those 2 fields do display properly in my table, but company is blank. If I switch which join is shown, it follows suit.
If I don't use any of the joins, I can do a where just fine with one of the chemical fields. My question is why does having a join seem to break that particular With statement and is there a way to fix it? I get the feeling that it's something to do with the With statement doing some kind of behind the scenes join, but I haven't been able to find any specifics..
Thanks,
Forgot to mention I had tried Eager Loading Constraints before as well.
$chemicals = $app->Chemical->with(
array(
'Company',
'Room',
'Measurement',
'Location' => function ($query) {
$query->where('location', '=', 'FLAMCAB');
}
))
//->where('company', '=', 'FISHER')
->get();
Using above without the where commented out gives me the message that the chemicals table does not have a column called company, which is true.
Not using it, I do get results:
As you can see it does filter the locations table, but it does only that, it doesn't filter chemicals by that, which is what I'm trying to do.
If you want to filter Chemicals based on their related Locations, you can combine constraining eager loads with querying relationship existence:
$filter = function ($query) {
$query->where('location', '=', 'FLAMCAB');
};
$chemicals = $app->Chemical->with(
array(
'Company',
'Room',
'Measurement',
'Location' => $filter
)
->whereHas('location', $filter)
->get();
I'm not sure how efficient this is though - you might want to check out the resulting query. Another option is to simply filter the collection using Collection filters after you run the query.
This question: Complex query with filters with Eloquent might also help you.

Querying relations with a where clause on the child table

I have been using the has method to query the existence of data in a related table and that is working just fine. Using the code example on the Laravel web site, you can do the following to get any post that has comments associated with it.
$posts = Post::has('comments')->get();
What I would like to be able to do, as an example, is query for any post which has comments from the last thirty days. Since the has method only has the ability to count related rows I am not sure of a good way to do this.
Ok, this is what I could come up with. It might not be the best solution, but it does work and doesn't seem too polluted. First, we'll need to add reference to Carbon and the Eloquent\Collection classes.
use \Carbon\Carbon;
use \Illuminate\Database\Eloquent\Collection;
Carbon does come with Laravel as a dependency, out of the box, but it would be smart to add it to your own project's dependencies anyway. Then, this code should do it:
// Gather all distinct 'post_id' from Comments made in the last 30 days
// along with its Post objects
$comments = Comment::with('Post')
->where('created_at', '>', Carbon::now()->subMonth())
->distinct()
->get(array('post_id'));
// Since we only want Posts, loop through the Comments collection and add
// the Posts to a new collection
$posts = new Collection;
foreach ($comments as $comment) {
$posts->add($comment->post);
}
From the Laravel 4 Documentation:
$posts= Post::with(array('comments' => function($query)
{
$query->where('published', '>=', 'date- 1 month'); //look date functions up
}))->get();
See Eager Load Constraints under laravel 4 documentation

Categories