Laravel Relationships setup for the following table - laravel

I am trying to set up a exam timetable module,
This is the table structure:-
id
title
start_date
end_date
class_id
subject_id
date(for each subject_id)
Now the thing is that class_id exists in classroom table as "id" and I need to get it's name from it which is in the table as "title". Similarly for the subject_id where it exists in subject table as "id" and it's name which is in the table as "title". Once I get these the database table would look something like this:-
id title start_date end_date class_id subject_id date
1 test some_date some_date 1 1 date
1 test some_date some_date 1 2 date
1 test some_date some_date 1 3 date
1 test some_date some_date 1 4 date
how do I set up my controller with the relationships, please help!

Try this.
In exam model.
public function class()
{
return $this->hasMany('App\Class');
}
public function subject()
{
return $this->hasMany('App\Subject');
}
In class model.
public function exam()
{
return $this->belongsTo('App\Subject');
}
In subject model
public function exam()
{
return $this->belongsTo('App\Subject');
}
This way, you can perform
return $exam->subject->title
or
return $exam->class->title
but if you have relationship between class and subject already, you can achieve this in another way using belongs to through which you can find here. https://laravel.com/docs/5.6/eloquent-relationships#has-many-through

Related

Fetch one record from relationship for Datatable

I'm using Laravel v8
I have 3 models as:Family, FamilyMember, FamilyRelationship
Family table:
id
address
created_at
updated_at
1
test
NULL
NULL
Family Relationship table:
id
name
created_at
updated_at
1
Head
NULL
NULL
2
Spouse
NULL
NULL
3
Child
NULL
NULL
Family Member table:
id
first_name
last_name
family_id
family_relationship_id
1
John
Doe
1
1
2
Jane
Doe
1
2
3
Max
Doe
1
3
4
Mary
Doe
1
3
I have created relation in the Family model as
public function members(){
return $this->hasMany(FamilyMember::class, 'family_id');
}
And Family Relationship relation in Family Member model as
public function familyrelationship()
{
return $this->belongsTo(FamilyRelationship::class, 'family_relationship_id');
}
I'm using Datatable to display the Family Information along with Head of the family
I want to display columns id and address from Family model and first_name and last_name from Family Member model where the family member relationship is Head.
How should go ahead with making relationship to display only head of the family detail in the datatable grid which is searchable too?
Above thing can be easily achieved using eloquent JOINs but I want to know if this can be achieved using relationship functionality provided by Laravel.
you can try whereHas mixing with hasOne , to build a new relation:
public function members(){
return $this->hasMany(FamilyMember::class, 'family_id');
}
// then your new relation:
public function head(){
return $this->hasOne(FamilyMember::class, 'family_id')->whereHas('familyrelationship',function ($query){
$query->where('name','Head');
});
}
hasOne, will take only first result ...

Laravel: How to get the latest record in group of records with where condition?

I have two tables which are named as students and cities. students table has a primary key which is related to the cities table.
Students table:
In the frontend, I would like to have the data of the cities table with these requirements:
The data of the students table must be grouped by city_id
If there are more than one records with the same city_id in the students table, select only the latest record of the group.
Search in the latest records and select only students who are inactive.
Here is the relationship function of the city model:
public function student()
{
return $this->hasOne(Student::class, 'city_id', 'id')->orderByDesc('id');
}
This is my controller function:
$data = City::whereHas('student', function($query){
$query->where('is_active', 0)
})->with('student')->get();
Expected result: Considering the sample data, the query must return nothing.
Current result: It returns the third row as there is an inactive student record in the second row. So in this case where condition doesn't work properly.
I can get expected result with this SQL query:
select *
from students s
where id = (select max(t2.id)
from students s2
where s.city_id = s2.city_id) AND is_active = '0';
How can I fix this logical error?
What about something like this?
public function inactiveStudent()
{
return $this->hasOne(Student::class, 'city_id', 'id')
->where('is_active', 0)
->orderByDesc('id');
}
$data = City::whereHas('inactive_student')
->with('inactive_student')
->get();
I'm not certain if it's inactive_student or inactiveStudent when you do the query.

Select from two column by two dates in codeignter models

I want to select from two column with two dates given in codeigniter models.
$total_car = 5;
My customer order table
booked_car start_date end_date
1 2019-06-06 2019-06-07
2 2019-07-15 2019-07-18
1 2019-08-27 2019-09-03
I want to check total car has been booked by selected dated in my models
$this->db->select('SUM(total_car) AS booked_car');
$this->db->from('car_order');
$this->db->where('start_date >=', '2019-08-27');
$this->db->where('end_date <=', '2019-09-03');
Result when search date same with in customer order table:
$booked_car = 1;
$avalaible car = 4 (get from $total_car - $booked_car);
But when I try to change date on start_date and end_date :
$this->db->select('SUM(total_car) AS booked_car');
$this->db->from('car_order');
$this->db->where('start_date >=', '2019-08-29');
$this->db->where('end_date <=', '2019-09-05');
or
$this->db->where('start_date >=', '2019-08-31');
$this->db->where('end_date <=', '2019-09-04');
Result :
$booked_car = 0;
$avalaible car = 5 (get from $total_car - $booked_car);
I think result should be :
$booked_car = 1;
$avalaible car = 4 (get from $total_car - $booked_car);
Because on '2019-08-29' or '2019-08-31' or any date as long as range between '2019-08-27' until '2019-09-03', car still booked base on booked_car table above.
How can I get correct results base on date in order table in my models.
Thank you for your assistance.
maybe you should do this
$this->db->where('DATE(start_date) >=', datefordatabase('2019-08-29'));
$this->db->where('DATE(end_date) <=', datefordatabase('2019-09-05'));

Laravel join query with conditions

I have 4 tables.
User table:
id col1 col2
CoursesAssigned table:
id user_id course_id approved
CourseInfo table:
id parent_id
CourseParents table:
id start_date end_date
I think the table names and its column names are self explanatory.
I have 2 kinds of users - i) assigned ii) unassigned. I show them in 2 different pages.
While showing the assigned students I need those students from users table for each of whom there is at least one row in CoursesAssigned table where user_id is his own user id and the approved field is 1 and the course_id in that row has its own parent_id (from CourseInfo) with end_date (from CourseParents) greater than or equal to today.
For showing unassigned students, I need those students from users table, for each of whom -
either
there is NO row in CoursesAssigned table where the user_id is his own user id and the approved column has a value 1. That is for an unassigned user, there may exist a row with his own user id but the approved field contains 0.
or
there may be rows in CoursesAssigned table with the user_id being his own user id and the approved field having a value 1 but the parent_id obtained from CourseInfo has from CourseParents an end_date which is less than today's date.
I can write a query for assigned students like:
$date=date('Y-m-d');
$records = User::join('CoursesAssigned','users.id','=','CoursesAssigned.user_id')
->join('CourseInfo','CourseInfo.id','=','CoursesAssigned.course_id')
->join('CourseParents','CourseParents.id','=',
'CourseInfo.parent_id')
->where('CoursesAssigned.approved','=',1)
->where('CourseParents.end_date','>=',$date)
->select('users.id','users.col1','users.col2')
->orderBy('users.id','desc');
But that should not produce the correct result as that does not check CoursesAssigned table for at least 1 row that meets all mentioned criteria. Q1) Or should it ?
Q2) What is about the query that fetches only the unassigned students ?
EDIT : The answer can be in ORM, query builder or even raw MySql for Laravel format.
EDIT2 : Let me clarify the scenario here :
I need to fetch both assigned and unassigned users separately.
To obtain assigned users I have 1 rule: How can I get those users who have at least 1 approved course in CoursesAssigned table and the parent (obtained from CourseInfo table )of that course has the end_date (in CourseParents table) greater than or equal to today.
To obtain unassigned students I have 2 rules :
Rule 1: Get those tudents who do not have any approved course (i.e. all courses have approved =0). They are unassigned students
Rule 2: Get those students who have approved courses but none of the approved courses meet the criteria of those for assigned students . That means there is no approved course there that has a parent whose end_date is greater than or equal to today.They are also unassigned students.
I'm still not completely sure about your table relationships but from my guess, I came up with the following solution, first create the relationships using Eloquent models:
User Model (for usres table):
namespace App;
use App\Course;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
public function courses()
{
return $this->hasMany(Course::class);
}
}
Course Model (for CoursesAssigned table):
namespace App;
use App\CourseInfo;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
protected $table = 'CoursesAssigned';
public function courseInfo()
{
return $this->belongsTo(CourseInfo::class);
}
}
CourseInfo Model (for CourseInfo table):
namespace App;
use App\CourseParent;
use Illuminate\Database\Eloquent\Model;
class CourseInfo extends Model
{
protected $table = 'CourseInfo';
public function courseParent()
{
return $this->belongsTo(CourseParent::class, 'parent_id');
}
}
CourseParent Model (for CourseParents table):
namespace App;
use Illuminate\Database\Eloquent\Model;
class CourseParent extends Model
{
protected $table = 'CourseParents';
}
Get the assigned users:
$assignedUsers = User::whereHas('courses', function($query) {
$query->where('approved', 1)
->with(['courses.courseInfo.courseParent' => function($query) {
$query->where('end_date', >= \Carbon\Carbon::now());
}]);
})->get(); // paginate(...) for paginated result.
This should work if my assumption is correct. Try this for assignedUsers first then let me know and then I'll look into it for the other requirements. Also make sure that you do understand about Eloquent relationships between models and implement everything correctly (with correct namespace).
Note: This answer is incomplete and need further info because the answer is a result of direct conversation with OP over phone (OP called me because I was reachable) so some changes will be made overtime if needed and will be continued step by step until I can come up with a solution or leave it.

Select records where not in relational table

I have 2 tables with this structures :
**table1**
id | title
-----+--------
1 | Blah1
2 | Blah2
**table2**
id | table1_id | article_id
-----+-------------+------------
1 | 1 | 1
2 | 1 | 3
3 | 2 | 1
Now I want to know how can I select all records from table1 where not use in table2
for example I need all table1 records where not exists in table2 for article_id=3
How can I create model and use eloquent models ?
UPDATE:
I need Blah2 from table1 and then show to my user, because Blah1 inserted for article_id = 3 before.
UPDATE 2:
This is worked query, I need write model for this query:
SELECT a.*
FROM table1 AS a
WHERE a.id NOT IN (SELECT table1_id
FROM table2
WHERE article_id = 3
)
you need to create model something like below you can change name appropriately
here i will refer something like below
table1 => ParentModel and table2 => ChildModel
define relation for children in ParentModel with below method
class ParentModel extends Model {
public function children() {
return $this->hasMany(ChildModel::class, 'table1_id');
}
}
whereDoesntHave method is available to filter records with related model
check here https://laravel.com/docs/5.3/eloquent-relationships#querying-relationship-absence
ParentModel::whereDoesntHave('children', function($q){
// here $q refers to related model in this case ChildModel
$q->where('article_id', 3);
})->get();
above query should return the required results.

Resources