How to find available dates with query - laravel

Could you help me build a query to find free dates in Laravel Eloquent.
So I have two models, Node and Booking.
Models are related by HasMany relations
public function dates()
{
return $this->hasMany(Booking::class, 'object_id', 'nid');
}
The model of booking have the following structure:
| bid | object_id | checkin | checkout |
| 1 | 32 | 2017-04-25 | 2017-04-28 |
| 2 | 32 | 2017-05-01 | 2017-05-09 |
| 3 | 44 | 2017-04-21 | 2017-04-24 |
| 4 | 51 | 2017-05-01 | 2017-05-08 |
My purpose is to find available Nodes between given dates.
So, if I want search one date between (for example created_at) it's simple:
whereBetween(‘created_at’, [$date1, $date2])
But how to create a search query between two dates of checkin and checkout?

You mean something like this?
$query->where('checkin','<=', $date)
->where('checkout','>=', $date);
You could also add it to a scope: Laravel query-scopes

Related

Laravel - how to handle ENUMs

Considering "enums", for instance:
gender: male, female
marital status: Single, Married, Separated, Divorced, Widowed
What is the best way to work with them in Models in a Laravel application? How to retrieve the list of possibilities and how to store them?
I tried using a table/model named "parameters". Simplifying, consider two tables:
people
|-----|-------|---------|----------------|
| id | name | gender | marital_status |
|-----|-------|---------|----------------|
| 1 | Clark | 1 | 4 |
| 2 | Bruce | 1 | 3 |
| 3 | Diana | 2 | 3 |
| 4 | Louis | 2 | 4 |
|-----|-------|---------|----------------|
parameters (I called like this, but it could be "domains", "enums", "lists", etc).
|----|----------------|---------|
| id | type | name |
|----|----------------|---------|
| 1 | gender | Male |
| 2 | gender | Female |
| 3 | marital_status | Single |
| 4 | marital_status | Married |
|----|----------------|---------|
But here I faced some doubts: how to create relationship between these models on Laravel, considering that just part of parameters table can be used on relationship? I.e. I shouldn't be able to set $person->gender = 3;
Maybe, the ideal is to create a table for each "type of parameter", but actually, there are lots of parameter types.
Other approach is to hard code the enums as config options, as presented in How to show to handle enums in Laravel?.
So, what is the best way to work with them in a Laravel application?
A static information like gender and marital status should not saved in database, something like this are saved in config files. you could add a new config file to config directory and call it for example general.php then you could save this info in it, like:
<?php
return [
'gender' => [
'male',
'female'
],
'marital_status' => [
'Single',
'Married',
'Separated',
'Divorced',
'Widowed'
]
];
And then after running php artisan config:cache you could call it when you want as config('general.gender').
Also, you could handle them in your migration file as:
$table->enum('gender', config('general.gender'));
Finally, as a validation rule you could do:
'field' => 'in:' . implode(',', config('general.gender')),

Laravel | Return rows in order based off pivot

I have the following setup:
stages:
| id | name | order |
commands:
| id | name | body |
------------------------------=
| 1 | test | phpunit |
| 2 | style | echo "style" |
| 3 | deploy | deploy |
command_stage:
| command_id | stage_id | order |
---------------------------------
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
Basically, I would like to create a method on the stage model which allows me to get all of the commands back based off of the order, but commands have a specific order and so do the stages.
So each command is stored under a stage so we know which part to run but each command also has an order in that stage. Now I know I can do something like the following:
$inOrder = collect();
Stage::get()->each(function ($stage) {
$commands = $stage->commands()->orderByPivot('order')->get();
$inOrder->push($commands);
});
return $inOrder;
But I was wondering if there is a nicer way to do this? Or even a way to do this solely on one database hit?
Pre-load and sort the relationship:
$stages = Stage::with(['commands' => function ($subQuery) {
$subQuery->orderBy('command_stage', 'order');
}])->get();
foreach($stages as $stage) {
$inOrder->push($stage->commands);
}
This method of Eager-Loading will reduce the N+1 query issue of doing $stage->commands() inside the foreach() loop.

Laravel - Eloquent filter where Left Join does not exist

I am trying to figure out how to make this query work. These two tables do not have a direct relation (i.e. hasOne, hasMany, etc). I am looking to only get back records from client_vendor_relationship that do NOT have a collection_opt_in. Since I don't have a way of doing ->whereDoesntHave(), I am not sure how to get this data back.
client_vendor_relationship
| id | client_id | vendor_id | active |
|----|-----------|-----------|--------|
| 1 | 23484 | 1872 | 1 |
| 2 | 5643 | 345 | 1 |
| 3 | 431 | 4443 | 1 |
collection_opt_in
| id | client_id | vendor_id | year |
|----|-----------|-----------|------|
| 1 | 23484 | 23484 | 2020 |
| 2 | 23484 | 23484 | 2019 |
| 3 | 431 | 4443 | 2019 |
Current Query
$relationships = ClietVendorRelationship::where('active', 1)
->leftJoin('collection_opt_in', function($join){
$join->on('client_vendor_relationship.client_id', '=', 'collection_opt_in.client_id')
->on('client_vendor_relationship.vendor_id', '=', 'collection_opt_in.vendor_id');
})
->where() // Not sure what to put here to ONLY get rows back that the left join didnt find entries for
->groupBy('client_vendor_relationship.id')
->get();
The end goal of this above query would to be to only get the row back from client_vendor_relationship with the id of 2. I need to do this in Eloquent. I know I could easily just do a collection filter but the front end table I am using requires an eloquent query to be returned.
why using left join? while there is another straightforward ways?
you can use 'whereNotExists':
$relationships = ClietVendorRelationship::where('active', 1)
->whereNotExists(function ( $query){
$query->select('collection_opt_in.id')->from('collection_opt_in')->
whereColumn('collection_opt_in.client_id', '=', 'client_vendor_relationship.client_id')->
whereColumn('collection_opt_in.vendor_id', '=', 'client_vendor_relationship.vendor_id');
})
->groupBy('client_vendor_relationship.id')
->get();
also i must say i don't recommend using group by without aggregation

Use data gotten from one table to get data from another data

I have three tables
Job Model
+---------------------------+
| id | name |
+---------------------------+
| 1 | web design |
+---------------------------+
| 2 | desktop development |
+---------------------------+
Applicant Model
+----------------------------------------------------------+
| id | job_id | user_id | desc |
+----------------------------------------------------------+
| 1 | 2 | 1 | I am an expert developer |
+----------------------------------------------------------+
| 2 | 2 | 2 | I am good |
+----------------------------------------------------------+
User Model
+----------------+
| id | name |
+----------------+
| 1 | john |
+----------------+
| 2 | steve |
+----------------+
Using eloquent laravel,
How do I get applicants with job_id "2" and their user name together.
Tried a lot but unfortunately to no avail.
You would use a query something like this:
$jobs = Job::where('id', 2)
->join('applicants', 'jobs.id', '=', 'applicants.job_id')
->join('users', 'applicants.user_id', '=', 'users.id')
->select(['user.name', 'job.name', 'applicant.desc'])
->get();
You will have to change it to your requirements but should about what you need.
You can get more info here:
https://laravel.com/docs/5.7/queries
Hope that helps

Laravel many-to-many relationship with varying options

I am new to Laravel and am attempting to set up a many to many relationship (at least I think that's what I need)
Essentially each user have preferences there are 7 types of preferences some preferences can have multiple values and some have only one value
Here are the user_pref_options
project_type | ( will be checkboxes on view and have multiple options)
favorite | (a user can have multiple this is a foreign key to another table)
tagline | ( will be checkboxes on view and have multiple options)
bedroom_min | (a single value per user)
bedroom_max | (a single value per user)
sf_min | (a single value per user)
sf_max | (a single value per user)
and here is what the user_pref table has
| id | user_id | pref_option_id | value |
| --- | --- | --- | --- |
| 1 | 1 | 1 | 5 |
| 2 | 1 | 1 | 3 |
| 3 | 1 | 2 | 364 |
| 4 | 1 | 2 | 201 |
| 5 | 1 | 2 | 9 |
| 6 | 1 | 2 | 244 |
| 7 | 1 | 2 | 192 |
| 8 | 1 | 2 | 292 |
| 9 | 1 | 4 | 1 |
| 10 | 1 | 11 | 1 |
| 11 | 1 | 12 | 6 |
| 12 | 1 | 13 | 1628 |
| 13 | 1 | 14 | 9134 |
so that would be 1 users notice how some option types have multiples
sorry I had to lay a lot of background before I ask my question.
I would like to be able to connect the user prefs to the user using Eloquent and am having trouble figuring out which way it should be done..
here is what I have tried
//User model
public function prefs(){
return $this->belongsToMany('App\Pref', 'pref_user', 'user_id', 'pref_id');
}
and
//Pref Model
public function user()
{
return $this->belongsToMany('App\Pref', 'pref_user', 'user_id', 'pref_id');
}
I have taken a look here
I would like to be able to get all the preferences and display them on a view
(I won't bore you by pasting that in here now)
my struggle is that some of the preferences have multiple options and some have single options. How do I retrieve the values
maybe I need to separate each preference type to its own model but that seems like overkill I am open to suggestions
user_pref table makes it difficult to distinguish between your prefs and also sets a lot of overhead data.
So, you can set the single value prefs (bedroom_min, bedroom_max, sf_min and sf_max) in user model or in separated model and retrieve them with user. And for other prefs, many-to-many relation is better and more flexible.
Finally, When you fetch User model, you will get the model and its relations.

Resources