I have a Student in the users table, Parent is in the same table, and that Parent is the parent of that Student.
The Student has a Schedule in the schedules table.
How I can write hasMany and belongsTo to get the proper relation like in following custom query which works fine:
$schedules = DB::table('users')
->join('schedules', 'users.id', '=', 'schedules.studentID')
->select('users.*', 'schedules.*', 'users.fname as fname', 'users.lname as lname')
->where('users.parent_id',$request->id)
->where('schedules.status','1')
->where('schedules.status_dead','0')
->whereIn('schedules.std_status',[1, 2])
->get();
As shown in the image below:
Before the relationship lets create parent scope and find student more elegant way
User Model
public function scopeByParent($query,$parentId){
return $query->where("parent_id",$parentId);
}
Above scope provide us to get user or users by parent id.
Then create relationships.
User Model
public function schedules(){
return $this->hasMany("App\Schedule","studentID","id");
}
Schedule Model
public function users(){
return $this->belongsTo("App\User","id","studentID");
}
Then lets create our query using above scope and relation.
User::with(["schedules" => function ($query) {
$query->whereStatusAndStatusDead(1, 0)
->whereIn('std_status', [1, 2]);
}])
->byParent($request->id)
->get();
Related
I have 4 table categories, initiatives, a pivot table for the "Many To Many" relationship category_initiative and initiativegroup table related with initiatives table with initiatives.initiativesgroup_id with one to many relation.
With pure sql I retrive the information I need with:
SELECT categories.id, categories.description, initiatives.id, initiatives.description, initiativegroups.group
FROM categories
LEFT JOIN category_initiative ON categories.id = category_initiative.category_id
LEFT JOIN initiatives ON category_initiative.initiative_id = initiatives.id
LEFT JOIN initiativegroups ON initiatives.initiativegroup_id = initiativegroups.id
WHERE categories.id = '40'
How can I use eloquent model to achieve same results?
Since you have such a specific query touching multiple tables, one possibility is to use query builder. That would preserve the precision of the query, retrieving only the data you specifically need. That would look something like this:
$categories = DB::table('categories')
->select([
'categories.id',
'categories.description',
'initiatives.id',
'initiatives.description',
'initiativegroups.group',
])
->leftJoin('category_initiative', 'categories.id', '=', 'category_initiative.category_id')
->leftJoin('initiatives', 'category_initiative.initiative_id', '=', 'initiatives.id')
->leftJoin('initiativegroups', 'initiatives.initiativegroup_id', '=', 'initiativegroups.id')
->where('categories.id', '=', 40)
->get();
In your models define the relationships:
Category.php model
public function initiatives()
{
return $this->belongsToMany('App\Initiative');
}
Initiative.php model (If has many categories change to belongs to many)
public function category()
{
return $this->belongsTo('App\Category');
}
Then maybe change your initiativegroup -> groups table, and then create a pivot table called group_initiative. Create model for group. Group.php and define the relationship:
public function initiatives()
{
return $this->belongsToMany('App\Initiative');
}
Then you can also add the following relationship definition to the Initiative.php model
public function group()
{
return $this->belongsTo('App\Group');
}
That should get you started.
for the record..
with my original relationship, but changing table name as alex suggest, in my controller:
$inits = Category::with('initiative.group')->find($id_cat);
simple and clean
I'm trying to do where clause for fortune_code inside joindraw table, comparing with the lucky_fortune_code from product table. How can i access and do the check?
Product::where('status', StatusConstant::PT_ENDED_PUBLISHED)
->where('lucky_fortune_code', '<>', '')
->with(['joindraw' => function ($query){
$query->where('fortune_code', $this->lucky_fortune_code)
->with('user');}])->desc()->get();
Product.php
class Product extends Model
{
public function joindraw(){
return $this->hasMany('App\Models\Joindraw');
}
Joindraw.php
class Joindraw extends Model
{
public function product(){
return $this->belongsTo('App\Models\Product', 'product_id');
}
What you can do is a join:
Product::where('status', StatusConstant::PT_ENDED_PUBLISHED)
->where('lucky_fortune_code', '!=', '')
->join('joindraws', 'joindraws.fortune_code', '=', 'products.lucky_fortune_code')->get();
By the way, you can also omit the second 'product_id' parameter in the belongsTo() relation, as this column name is already assumed by convention.
Also, there is no desc() method on the query builder. Use orderBy('lucky_fortune_code', 'desc') instead.
However, whenever you have to write joins in Laravel, you should think about your relationship structure, because there's probably something wrong.
I have 4 tables. Championships, Users, Roles and users_roles.
One user belongs to championship as judge. But I have to select only users who have role 'Judge'.
For this, I created new column in championships table which is called "main_judge" and created new relationship
class Championship extends Model
{
...
public function mainJudge()
{
return $this->hasOne('App\User', 'id', 'main_judge');
}
...
}
Then I add to query some code
$query->join('users_roles', 'users.id', '=', 'users_roles.user_id')
->join('roles', 'users_roles.role_id', '=', 'roles.id')
->where('roles.alias', '=', 'judge');
when I print query as sql I got (see screen)
http://joxi.ru/a2X45M1Sw0RpE2
and after $query->get() instead of user ID i got a role ID (see screen)
http://joxi.ru/bmoxMaDs3NVoE2
I would suggest using eloquent rather than the query builder as it will remove the need to manually define any joins.
You should just be able to do this:
$championship = Championship::find($id);
$judge = $championship->mainJudge;
If you then dd($judge) you should end up with the appropriate User object.
I've 3 tables:
Courses (have category_id)
Authors
Categories (of courses)
In my Authors model I've added:
public function courses () {
return $this->belongsToMany('App\Course', 'courses2authors')->where('status','=', 1);
}
"courses2authors" is the pivot table.
Then in my controller I retrieve courses info with:
$authors = Author::where('status', '=', 1)->orderBy('pos')->with('courses')->get();
It's ok but I've only the category_id in ->courses, how to add category name in the model relationship.
I try something like:
return $this->belongsToMany('App\Course', 'courses2authors')
->where('status','=', 1)->join('categories', 'categories.id', '=',
'courses.category_id')->select('categories.name as categoria');
But in this way in take only the category name and not the course data.
You can define belongsTo relationship in Course Model with Categories.
Course Model
public function categories () {
return $this->belongsTo('App\Categories', 'category_id');
}
While retrieving Author with Courses then you can use like this. (Controller code)
$authors = Author::where('status', '=', 1)->orderBy('pos')
->with('courses',function($query){
$query->with('categories);
})->get();
if you don't want to use like this then you can set $with attribute in Courses Model.
protected $with = ['categories']; // default with define here.
Use in controller :-
$authors = Author::where('status', '=', 1)->orderBy('pos')
->with('courses')->get();
In Laravel 4/5 how can order a table results based in a field that are connected to this table by a relationship?
My case:
I have the users that only store the e-mail and password fields. But I have an another table called details that store the name, birthday, etc...
How can I get the users table results ordering by the details.name?
P.S.: Since users is a central table that have many others relations and have many items, I can't just make a inverse search like Details::...
I would recommend using join. (Models should be named in the singular form; User; Detail)
$users = User::join('details', 'users.id', '=', 'details.user_id') //'details' and 'users' is the table name; not the model name
->orderBy('details.name', 'asc')
->get();
If you use this query many times, you could save it in a scope in the Model.
class User extends \Eloquent {
public function scopeUserDetails($query) {
return $query->join('details', 'users.id', '=', 'details.user_id')
}
}
Then call the query from your controller.
$users = User::userDetails()->orderBy('details.name', 'asc')->get();