In my case, I have to filter the data by city or institute
I have two tables like below
Institutes table
id | institute_name | phoneNumber
-------------------------------------
1 infocampus 9999999999
-------------------------------------
2 jspider 2348234982
courses table
id | institute_id | course_name
------------------------------------------
1 1 java
2 1 php
Relations that I have created
Institue model
public function courses()
{
return $this->hasMany(Course::class);
}
Course model
public function institute()
{
return $this->belongsTo(Institute::class);
}
I have tried with below code
public function filter(Request $request)
{
$institute = (new Institute)->newQuery();
// Search for a user based on their institute.
if ($request->has('institute_name')) {
$institute->where('institute_name', $request->input('institute_name'));
}
// Search for a user based on their course_name.
if ($request->has('course_name')) {
$institute->whereHas('courses', function ($query) use ($request) {
$query->where('courses.course_name', $request->input('course_name'));
});
}
return response()->json($institute->get());
}
From above i able to filter the data but it show only institution table data like below
[
{
"id": 2,
"institute_name": "qspider",
"institute_contact_number": "9903456789",
"institute_email": "qspider#gmail.com",
"status": "1",
"created_at": null,
"updated_at": null
}
]
but what I need is when I do seach with course_name or instute_name I need to fetch data from institue table as well as courses table data.
Can anyone help on this, please?
Try the following it should return the institutes with the courses.
$institute->with(['courses' => function ($query) use ($request) {
$query->where('courses.course_name', $request->input('course_name'));
}])
Related
I want to get all projects, and foreach project I want to get a property for example is_liked which indicates that if the current_user (I've his Id) has liked this project or not.
User Model
class User extends Model
{
public function projects()
{
return $this->hasMany(Project::class);
}
public function favorite_projects()
{
return $this->belongsToMany(Project::class, 'favorite_projects', 'user_id', 'project_id')->withTimestamps();
}
}
Project Model
class Project extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
User Table
- id
- name
Project Table
- id
- user_id
- title
favorite_projects table
- user_id
- project_id
What is the best way to get this done ? the data I want to get is something like this:
[
{
"id": 1,
"user_id": 3,
"title": "my title",
"is_liked": true
}
]
Note: the current_user->id might or might not be same as the project->user_id.
$projects = DB::table('projects')
->join('favorite_projects', 'favorite_projects.project_id', '=', 'projects.id')
->select('projects.*', 'favorite_projects.*')
->where('projects.user_id', Auth::id())
->get();
This join statement allows you to join 2 tables together and for each project that is being favorited by the user, you will see the favorite record attached with the record.
Perform a dd($projects) after that SQL query and see what the result is like, and then for each result, you set $project['is_liked'] accordingly.
I'm using this query to get data using relation
return Product::with('attributes')
->whereHas('attributes', function ($query) use ($attribute_id,$attribute_value){
$query->whereIn('attribute_id', $attribute_id);
$query->whereIn('value', $attribute_value);
})
->paginate(10);
$attribute_id and $attribute_value are arrays, i'm getting data using this relation but when $attribute_id and $attribute_value are empty then i'm not getting any result but it should return result through product table if there are no attributes.
I have changed it to something like this:
if(!empty($attribute_id))
{
$query->whereIn('attribute_id', $attribute_id);
}
if(!empty($attribute_value))
{
$query->whereIn('value', $attribute_value);
}
model relation :
public function attributes()
{
return $this->hasMany(ProductsAttribute::class, 'product_id ');
}
Table:
id | Title | Price
1 Title 1 5000
2 Product 2 7000
this is related to product_attribute table
id | product_id | attribute_id | attribute_name | value
1 1 5 Color Red
2 1 6 Size XL
3 2 5 Color Green
Is there any other way to make a check in query so that if attributes are not provided then atleast product data should return.
A cleaner way might be to use local scopes. That way, your controllers will look cleaner. It also makes the code easily testable. Here is how I might approach this.
NOTE: Code hasn't been tesed.
In your controller:
return Product::with([
'attributes' => function ($query) use ($attribute_id, $attribute_value) {
return $query->inAttributeId($attribute_id)
->inAttributeValue($attribute_value);
}
])->paginate(10);
In your ProductsAttribute model:
public function scopeInAttributeId($query, $attributeId)
{
if (empty($attributeId)) {
return $query;
}
return $query->whereIn('attribute_id', $attributeId);
}
public function scopeInAttributeValue($query, $attributeValue)
{
if (empty($attributeValue)) {
return $query;
}
return $query->whereIn('value', $attributeValue);
}
As you can see, the scopes modify the query only if there are values in the passed in array. If the passed in array is empty, it returns the original query.
I want this object only if it has all the necessary relationships.
At the moment my code:
StudentController
$student = Student::with('inscriptions','inscriptions.classroom')
->find($request->user()->id);
Student
public function inscriptions()
{
return $this->hasMany('App\InscribedStudent');
}
InscribedStudent - Note: "Registration Open"
public function classroom()
{
return $this->hasOne('App\Classroom', 'id')->where('registration_open', true);
}
Json Return When haven't registration opened
{
"inscriptions": [
{
"id": 1,
"student_id": 1,
"classroom_id": 1,
"deleted_at": null,
"created_at": "2019-07-04 23:34:48",
"updated_at": "2019-07-04 23:34:48",
"classroom": null
}
]
}
I want to do something like that, because I don't need the object InscribedStudent if I haven't a classroom.
public function inscriptions()
{
return $this->hasMany('App\InscribedStudent')
->hasOne('App\Classroom', 'id')
->where('registration_open', true);
}
You can use has() or whereHas() to check that the classroom exists.
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence
// this will only get students that have a classroom through inscriptions
$students = Student::has('incriptions.classroom')
->with('inscriptions.classroom')
->get();
// this will get students, but only fetch inscriptions if there is a classroom
$students = Student::with(['inscriptions' => function($inscriptionQuery) {
$inscriptionQuery->has('classroom')->with('classroom');
}])
->get();
You can also make a custom scope on the Student model if you want to use that instead.
// this will only get students that have a classroom through inscriptions
public function scopeHasClassroom($query)
{
$query->has('inscriptions.classroom')
->with('inscriptions.classroom');
}
// this will get students, but only fetch inscriptions if there is a classroom
public function scopeHasClassroom($query)
{
$query->with(['inscriptions' => function($inscriptionQuery) {
$inscriptionQuery->has('classroom')->with('classroom');
}]);
}
Then you can call the custom scope like this:
$students = Student::hasClassroom()->get();
https://laravel.com/docs/5.8/eloquent#query-scopes
In my case I'm working on search training institutes based on institute name,location and course
I have 3 tables
institutes Table
id | institute_name | phone_number
----------------------------------------------
1 | vepsun | 85214542462
----------------------------------------------
2 | infocampus | 52466475544
Locations table
id | institute_id(fk) | location_name
------------------------------------------------
1 | 1 | Banglore
------------------------------------------------
2 | 1 | delhi
courses table
id | institute_id(fk) | course_name
------------------------------------------------
1 | 1 | php
------------------------------------------------
2 | 1 | delhi
I have created relations between 3 tables tables
Institute Model :
public function locations()
{
return $this->hasMany(Location::class);
}
public function courses()
{
return $this->hasMany(Course::class);
}
Course Model:
public function institute()
{
return $this->belongsTo(Institute::class);
}
Location model:
public function institute()
{
return $this->belongsTo(Institute::class);
}
So I have tried below code
public function filter(Request $request)
{
$institute = (new Institute)->newQuery();
// Search for a user based on their institute.
if ($request->has('institute_name')) {
$institute->where('institute_name', $request->input('institute_name'));
}
// Search for a user based on their course_name.
if ($request->has('course_name')) {
$institute->whereHas('courses', function ($query) use ($request) {
$query->where('courses.course_name', $request->input('course_name'));
});
}
// Search for a user based on their course_name.
if ($request->has('location_name')) {
$institute->whereHas('locations', function ($query) use ($request) {
$query->where('locations.location_name', $request->input('location_name'));
});
}
return response()->json($institute->get());
}
From above code i'm able to filter the data but it show only institution table data like below.
[
{
"id": 2,
"institute_name": "qspider",
"institute_contact_number": "9903456789",
"institute_email": "qspider#gmail.com",
"status": "1",
}
]
but what I need is when I do seach with course_name or instute_name I need to fetch data from institues table,courses and locations table. Can anyone help on this, please?
Eager load the relations in your if statements.
// Search for a user based on their course_name.
if ($request->has('course_name')) {
$institute->whereHas('courses', function ($query) use ($request) {
$query->where('courses.course_name', $request->input('course_name'));
})
->with('courses); // <<<<<< add this line
}
// Search for a user based on their course_name.
if ($request->has('location_name')) {
$institute->whereHas('locations', function ($query) use ($request) {
$query->where('locations.location_name', $request->input('location_name'));
})
->with('locations'); // <<<<<<< add this line
}
This will fetch related courses and locations as well.
Problem details:
I have three models
a Directorate with id and name fields,
an Employee with id and name fields and
a Telephone with id, tel, employee_id, directorate_id, description and type fields. The employee_id may be nullable, that is there are telephones stored in database with employee_id = null
The models are related as follows:
an employee may have many telephones
a directorate, may have many telephones
class Directorate extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function employees()
{
return $this->hasMany(Employee::class);
}
}
class Employee extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function directorate()
{
return $this->belongTo(Directorate::class);
}
}
class Telephone extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
public function directorate()
{
return $this->belongsTo(Directorate::class);
}
}
Question:
I want to fetch a Collection of all the Telephone models that belong to a specific Directorate, that have employee_id = null and also having their directorate relation eager loaded. In addition, from that resulting collection of Telephone models, I need only some of the models' fields, that is id, tel and description
Tries
What I tried so far was the following:
I created a query scope in the Telephone model:
public function scopeHaveNoEmployeeId($query)
{
return $query->where('telephones.employee_id', '=', null);
}
In my controller
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get(['id', 'tel', 'description']);
However what I am receiving are the requested fields of the filtered models without the relation eager loaded, for instance:
[
{
"id": 79,
"tel": "0648136867",
"directorate": null
},
{
"id": 380,
"tel": "0223796011",
"directorate": null
}
]
I tried also to lazy eager load the relation afterwards but with no luck.
Finally I noticed that if I request all the Telephone models fields, the relation will eager load as I request. For example:
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get();
Then as a result:
[
{
"id": 79,
"tel": "0648136867",
"directorate": {
"id": 23
"name": "Some name"
}
},
{
"id": 380,
"tel": "0223796011",
"directorate": {
"id": 23
"name": "Some name"
}
}
]
Your telephone does not have any relationship with the directorate model.
put this in your Telephone model.
public function directorate()
{
return $this->belongsTo(Directorate::class);
}
Actually, after digging into Laravel's details for a while, I noticed that my initial question was out of context and somewhat silly. I was first eager loaded a relationship and then fatuously I filtered out the relationship by not including it in get() parameters. I had just to do the following:
$myTelephones = Telephone::with('directorate')
->haveNoEmployeeId()
->where('directorate_id', $directorateId)
->get(['id', 'tel', 'description', 'directorate']);