These are the two queries I am firing. I want to make it simpler and faster. how should I do it?
$parentList = Category::select('parent_id')->groupBy('parent_id')->get()->toArray();
$categories = Category::whereNotIn('categories.id', $parentList)->get();
Table categories have following columns(
id,
parent_id,
name)
Make this relation in your Category Model as :-
public function parents()
{
return $this->hasOne('App\Category', 'parent_id', 'id');
}
Then simply use this relation as :-
$categories = Category::whereDoesntHave('parents')->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 have a two tables orders and product. Relation is One to One. In my order class i created method product
public function product() {
return $this->hasOne('App\Product', 'key_id', 'key_id');
}
Now in controller i want select rows where id is not null that's why i wanna use InnerJoin
Order::where('order_id', 7)
->join('products', 'products.key_id', 'orders.key_id')
->get();
That is fine but i would like get
Order::where('order_id', 7)->get();
and all join move to method like:
public function product() {
return $this->hasOne('App\Product', 'key_id', 'key_id')
->join('products', 'products.key_id', 'orders.key_id')
}
How can i do this ?
You have defined the relations between both the models, so If you fetch order with the following query:
Order::where('order_id', 7)->with('product')->get();
Remove the join line from product function i.e. ->join('products', 'products.key_id', 'orders.key_id')
After doing this, dump and die the $order, there will be an key pair with product and its values.
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();
this is my query
$personnel_info = \DB::table('assigns AS a')
->join('boxes AS b','b.id','=', 'a.box_id')
->join('positions AS p','p.id','=', 'b.position_id')
->select('a.id','b.id AS box_id','p.id as position_id','p.title','a.status','a.end_date')
->where('a.personnel_id','=',$personnel_id)
->get();
and this realtionship for boxes:
class Boxes extends Model
{
public function position()
{
return $this->belongsTo('Positions');
}
public function assign()
{
return $this->hasOne('Assigns', 'box_id');
}
}
how to use eloquent query(also realtionship) for replace DB facade query?
i want select some field for tables.without define fileds in boxes model
tnx
Try
$personnel_info = Assign::with('box.position')
->where('personnel_id', $personnel_id)
->get();
Then dd($personnel_info) to see everything that was returned. If you don't like the values, then add your select() clause.
I'm having two tables as 'jobs' and 'desired_skills'.
Table structure is as follows.
jobs table
jobs Table
desired_skills table
desired_skils table
where desired_skills.job_id refers to jobs.job id
In controller I have (I am getting $id as an argument from the url, and I can confirm the argument grabs the desired value)
$jobs = DB::table('jobs')->where(function ($query) use ($id) {
$query->Join('desired_skills', 'desired_skills.job_id', '=', 'jobs.job_id')
->where('jobs.employer_id', '=', $id);
->select('*')
})->get();
when I dump and die $jobs it only returns values from jobs table.
but when I run the query
SELECT * FROM jobs INNER JOIN desired_skills ON desired_skills.job_id = jobs.job_id it returns the desired value set.
What am I doing wrong? Any help will be greatly appreciated.
I think it has to do with wrapping your join inside of a where clause. I don't think it's giving you your desired query with that there.
$jobs = DB::table('jobs')
->join('desired_skills', 'desired_skills.job_id', '=', 'jobs.job_id')
->where('jobs.employer_id', '=', $id)
->get();
The query SELECT * FROM jobs INNER JOIN desired_skills ON desired_skills.job_id = jobs.job_id
is not the same has what you are trying to do in the function. In this query there is not
mention of 'employer_id' in the table 'jobs'.
An alternative would be to use eloquent relationships, as refered in a comment.
You need 3 classes in models:
Employer
Job
DesiredSkill
Between Employer and Job -> one-to-many relation (an employer can have multiple jobs).
Between DesiredSkill and Job -> one-to-one relation.
I'm not sure what you are trying to get from the join, but i think that if you implement
the methods that allow the relationships i believe you solve whatever.
class Job extends Model
{
public function employer()
{
return $this->hasOne('App\Job');
}
}
class Employer extends Model
{
public function jobs()
{
return $this->hasMany('App\Employer');
}
public function desiredSkill()
{
return $this->hasOne('App\DesiredSkill');
}
}
class DesiredSkill extends Model
{
public function job()
{
return $this->hasOne('App\DesiredSkill');
}
}
Try this:
$jobs = DB::table('jobs')
->join('desired_skills', 'desired_skills.job_id', '=', 'jobs.job_id')
->select('jobs.*', 'desired_skills.*')
->get();