Join to leftJoin queries in Laravel - php

I have a query that Im trying to retrieve. Its suppose to get a listings information with its trips and location details.
This is how Im calling the query inside the Destinations controller:
public function destinations($id) {
$destination = Destination::findOrFail($id);
$listingGuides = Listing::findGuidesTrips($destination)
->with('locations')
->withCount('trips')
->get();
return view('destinations.index', compact('listingGuides');
}
And the findGuidesTrips method is inside the Listings Model:
public static function findGuidesTrips($destination) {
$query = self::query()
->leftJoin('trips', 'listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('listings.name,listings.slug,listings.type,listings.id,MIN(trips.cost) as starting_price')
)
->groupBy('listings.id');
$query = self::query()
->leftJoin('locations', 'listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('locations.longitude as longitude')
)->addSelect(
\DB::raw('locations.latitude as latitude')
);
$query = $query->whereHas('locations',function($query) use ($destination) {
$query->where('region', 'like', $destination->location)->orWhere('country', $destination->location);
});
return $query;
}
This is what I get back:
As you can see, I have 2 $query = self::query() quires, but only one is being called (the bottom one). Its ignoring the top self::query.
I was just wondering how would I go about combining these 2 leftJoin queries into one perhaps? Or is there a better way of doing this query?
( I tried doing this: )
$query = self::query()
->leftJoin('trips', 'listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('listings.name,listings.slug,listings.type,listings.id,MIN(trips.cost) as starting_price')
)
->leftJoin('locations', 'listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('locations.longitude as longitude')
)->addSelect(
\DB::raw('locations.latitude as latitude')
)->groupBy('listings.id');
But it gives me Integrity constraint violation: 1052 Column 'listing_id' in on clause is ambiguous error

As stated by #Tim Lewis and #Niklesh, all I had to do was:
trips.listing_id for first query and locations.listing_id for second.
Here is the final query:
public static function findGuidesTrips($destination) {
$query = self::query()
->leftJoin('trips', 'trips.listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('listings.name,listings.slug,listings.type,listings.id,MIN(trips.cost) as starting_price')
)
->leftJoin('locations', 'locations.listing_id', '=', 'listings.id')
->addSelect(
\DB::raw('locations.longitude as longitude')
)->addSelect(
\DB::raw('locations.latitude as latitude')
)->groupBy('listings.id');
$query = $query->whereHas('locations',function($query) use ($destination) {
$query->where('region', 'like', $destination->location)->orWhere('country', $destination->location);
});
return $query;
}

Related

Laravel and PHP - Condition in the SQL request

I have a query
$BaseUsers = DB::table('users', 'users.ustatus', '=', '1')
->join('user_infos', 'user_infos.user_id', '=', 'users.id')
->select('users.*', 'user_infos.add1', 'user_infos.add3')
->paginate(3);
It work fine. But i need insert condition "where" to search in result
i send $request from form. How insert condition to query?
In PHP it looks like this:
if($request['add_1'])
{
$insert1=" and add_1<>'' ";
}
if($request['add_2'])
{
$insert2=" and add_2<>'' ";
}
...
$sql=" SELECT users.*, user_infos.add1, user_infos.add3 FROM users JOIN user_infos where users.ustatus=1 and user_infos.user_id=users.id ".$insert1." ".$insert2."";
How can this be done on laravel in Controller? I mean - just insert the necessary condition insert1, insert2 ... into the query
you can use where() and has() to build your query
$query = DB::table('users');
if($request->has('age')) {
$query->where('age', '>', $request->age);
}
$query = $query->get();
I hope it's helpful
All is simple ) I use when in query
$BaseUsers = DB::table('users', 'users.ustatus', '=', '1')
->join('user_infos', 'user_infos.user_id', '=', 'users.id')
->when($request->input('f_add3'), function ($query) {
return $query->where('user_infos.add3', '<>', '');
})
->select('users.*', 'user_infos.add1', 'user_infos.add3')
->paginate(3);

How i can filter, with Eloquent, either in tables and join tables at the same time?

I have two tables, product_template and shorttitles.
A product can have multiple shorttitles, depending on language
A product has a primary title (called mmac_ebay_titolo), and a shorttitle has a name, that is the title in different language.
My goal is to filter, depending on post input, the shorttitles title and the product_template title with the string posted.
if no filter string is passed, all works fine.
The shorttitles model has this relation:
public function prodotto()
{
return $this->belongsTo('App\Product', 'product_id', 'id');
}
The product_template model has this relation:
public function shorttitle()
{
return $this->hasMany('App\ShortTitle', 'product_id', 'id');
}
But I'm stuck with the code below:
$m = self::MODEL;
$query = $m::select("*");
$data["data"] = $query
->with(["prodotto" => function ($q) use ($params) {
$q->select("id", "name", "mmac_ebay_titolo")
->where("name", "like", "%" . $params["search"] . "%");
}]
)->where("lang_id", "=", 1)
->offset($start)
->limit($limit)
->orderBy("id", "asc")
->get();
This query returns all shorttitles... with "prodotto" = null if the subquery doesn't match the where clause. Why?
After this, I would filter the main shorttitles table with this:
$m = self::MODEL;
$query = $m::select("*");
$data["data"] = $query
->with(["prodotto" => function ($q) use ($params) {
$q->select("id", "name", "mmac_ebay_titolo")
->where("mmac_ebay_titolo", "like", "%" . $params["search"] . "%");
}]
)->where("lang_id", "=", 1)
->where("name", "like", "%" . $params["search"] . "%")
->offset($start)
->limit($limit)
->orderBy("id", "asc")
->get();
I want to reproduce this query:
Select
s.name,
p.name,
p.mmac_ebay_titolo
From
mmac_brx_ebay_shorttitles s Inner Join
product_template p On s.product_id = p.id
where lang_id = 1
and
(
s.name like '%PIGNONE%'
or
p.name like '%PIGNONE%'
or
p.mmac_ebay_titolo like '%PIGNONE%'
)
How can I achieve this?
Thanks!
try this query:
$products = $query->join('product_template','mmac_brx_ebay_shorttitles.product_id','=','product_template.id')
->where(function ($query) {
$query->Where('mmac_brx_ebay_shorttitles.name','like','%PIGNONE%')
->orWhere('product_template.name','like','%PIGNONE%')
->orWhere('product_template.mmac_ebay_titolo','like','%PIGNONE%');
})->where('your_table_name.lang_id',1)
->select('mmac_brx_ebay_shortitles.name','product_template.name','product_template.mmac_ebay_titolo')
->paginate(10);

If using a query builder as to what in the form of its laravel?

I have a query sql like the following may be a bit complex, I am a bit of trouble to convert into a for framework laravel. Please help for everything with framework laravel query results. My problem here is, I do not know how to create a sub select query to laravel framework. Thanks guys.
SELECT
lin_users.status_employee_id,
lin_users.id,
lin_users.username,
lin_users.created,
lin_users.modified,
lin_employee_attributes.unit_code,
lin_employee_attributes.position_code,
lin_employee_attributes.begin_date,
lin_employee_attributes.end_date,
contactnumber.contact_id as phone_number,
contactmobile.contact_id as cell_number,
contactemail.contact_id as email
FROM lin_users
INNER JOIN lin_status_employees
ON lin_users.status_employee_id = lin_status_employees.id
INNER JOIN lin_people
ON lin_status_employees.person_id = lin_people.id
INNER JOIN lin_employee_attributes
ON lin_users.status_employee_id = lin_employee_attributes.status_employee_id
LEFT JOIN lin_contacts AS contactnumber
ON lin_people.id = contactnumber.person_id AND contactnumber.contact_type = 'Work Telephone'
LEFT JOIN lin_contacts AS contactmobile
ON lin_people.id = contactmobile.person_id AND contactmobile.contact_type = 'Mobile'
LEFT JOIN lin_contacts AS contactemail
ON lin_people.id = contactemail.person_id AND contactemail.contact_type = 'Email'
WHERE lin_employee_attributes.begin_date = '2016-11-07'
OR lin_employee_attributes.end_date = '2017-10-21'
GROUP BY lin_users.id,
lin_employee_attributes.unit_code,
lin_employee_attributes.position_code,
lin_employee_attributes.begin_date,
lin_employee_attributes.end_date, lin_people.id,
contactnumber.contact_id,
contactmobile.contact_id,
contactemail.contact_id;
Try this:
const TABLE = 'my_table_name';
return $this
->select(
self::TABLE . 'id as myidalias',
self::TABLE . 'username as myuseralias')
->addSelect(DB::raw(
"
(your custom select here) as mycustomresult
"
));
You can add as many addSelect as you want. Also when you have a lot of complex queries like this, a lot of times you have duplicated parts on them so I highly recommend using scopes it makes your code clean and reusable.
public function scopeLeftJoinCategory($query)
{
return $query
->leftJoin(Category::CONTENTS_CATEGORIES . ' AS cc', 'con.id', '=', 'cc.content_id')
->leftJoin(Category::TABLE . ' AS cat', 'cc.category_id', '=', 'cat.id');
}
Then you just use it like this: ->leftJoinCategory()
Using this work. Finally, with the above query can be solved with the concept query to query in laravel.
$users = $this->db->getTable('users')
->select('users.status_employee_id',
'users.id',
'users.username',
'users.email',
'users.created',
'users.modified',
'users.flag_delete',
'employee_attributes.unit_code',
'employee_attributes.position_code',
'employee_attributes.begin_date',
'employee_attributes.end_date',
'contactnumber.contact_id as phone_number',
'contactmobile.contact_id as cell_number',
'contactemail.contact_id as email'
)
->join('status_employees', 'users.status_employee_id', '=', 'status_employees.id')
->join('people', 'status_employees.person_id', '=', 'people.id')
->join('employee_attributes', 'users.status_employee_id', '=', 'employee_attributes.status_employee_id')
->leftJoin('contacts AS contactnumber', function($join)
{
$join->on('people.id', '=', 'contactnumber.person_id');
$join->on('contactnumber.contact_type','=', DB::raw("'Work Telephone'"));
})
->leftJoin('contacts AS contactmobile', function($join)
{
$join->on('people.id', '=', 'contactmobile.person_id');
$join->on('contactmobile.contact_type','=', DB::raw("'Mobile'"));
})
->leftJoin('contacts AS contactemail', function($join)
{
$join->on('people.id', '=', 'contactemail.person_id');
$join->on('contactemail.contact_type','=', DB::raw("'Email'"));
})
->where(function ($query) use ($begin_date, $end_date) {
$query->where('employee_attributes.begin_date', $begin_date)
->orWhere('employee_attributes.end_date', $end_date);
})
->groupby('users.status_employee_id',
'users.id',
'users.username',
'users.email',
'users.created',
'users.modified',
'users.flag_delete',
'employee_attributes.unit_code',
'employee_attributes.position_code',
'employee_attributes.begin_date',
'employee_attributes.end_date',
'contactnumber.contact_id',
'contactmobile.contact_id',
'contactemail.contact_id'
)
->get();

Concat columns using “with()” function in Laravel Eloquent

I'm trying to concat two columns from different tables into one single column.
$user = User::with(array('Person'=>function($query){
$query->selectRaw('CONCAT(prefix_person.name, " - ", prefix_user.code) as name, prefix_user.id');
}))->lists('name', 'id');
In my person class I have this method:
public function User()
{
return $this->hasOne('User');
}
And in my user class I have this one:
public function Person()
{
return $this->belongsTo('Person', 'person_id');
}
I get the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'name' in 'field list' (SQL: select `name`, `id` from `prefix_user`)
When I tried
$user = User::with(array('Person'=>function($query){
$query->selectRaw('CONCAT(prefix_person.name, " - ", prefix_user.code) as name, prefix_user.id')->lists('name', 'id');
}));
I got this error:
I have used the selectRaw a couple of times, but never needed it into a with (join).
The issue is that Eloquent will first query the users table, and only after, the persons table, so one query is not aware of the other and thus concatenating will not work.
You can use the Query Builder to do this using a join. It will be something like it:
$user = DB::table('users as u')
->join('persons as p', 'p.id', '=', 'u.person_id')
->selectRaw('CONCAT(p.name, " - ", u.code) as concatname, u.id')
->lists('concatname', 'u.id');
EDIT:
And, as suggested by #michel-ayres comment, as long as you have an acessor to the field:
public function getFullNameAttribute() {
return $this->attributes['name'] . ' - ' . $this->attributes['code'];
}
you can use your own model to perform the join and listing:
User::join('person','person.id','=','user.person_id')
->select('person.name', 'user.code', 'user.id')
->get()
->lists('full_name', 'id');
You can solve it simply by using simple query,
User::join('persons as p', 'p.id', '=', 'users.person_id')
->get([
'id',
DB::raw('CONCAT(p.name,"-",users.code) as name')
])
->lists('name', 'id');
Or, see another way
User::join('persons as p', 'p.id', '=', 'users.person_id')
->select(
'id',
DB::raw('CONCAT(p.name,"-",users.code) as name')
)
->lists('name', 'id');
You can solve it by using this sample query
->when($request->value != null, fn ($q) => $q->where(DB::raw("CONCAT(col1,'',col2)"), '=', '' . $request->value.
''))

Laravel: 1066 Not unique table/alias

I have two queries in my controller
if (isset($input['council']) && $input['council'] != '')
{
$query = $query->join('suburb_near', 'titles.suburb', '=', 'suburb_near.suburb')
->select(array('titles.*', 'suburb_near.suburb' , 'suburb_near.council'))
->where('council', 'like', '%'. $input['council'].'%')
->orderBy('views', 'desc');
}
if (isset($input['country']) && $input['country'] != '')
{
$query = $query->join('suburb_near', 'titles.suburb', '=', 'suburb_near.suburb')
->select(array('titles.*', 'a.suburb' , 'suburb_near.country'))
->where('country', 'like', '%'. $input['country'].'%')
->orderBy('views', 'desc');
}
If I run either independently they run fine. But if I run both together, I get an error:
1066 Not unique table/alias
How should I change this?
Use table alias (as)
The first query would look like:
$query = $query
->join('suburb_near as suburb_near_one', 'titles.suburb', '=', 'suburb_near_one.suburb')
->select(array('titles.*', 'suburb_near_one.suburb' , 'suburb_near_one.council'))
// Edit after user3664594s comment
->where('suburb_near_one.council', 'like', '%'. $input['council'].'%')
->orderBy('views', 'desc');
The second query would look like:
$query = $query
->join('suburb_near as suburb_near_two', 'titles.suburb', '=', 'suburb_near_two.suburb')
->select(array('titles.*', 'a.suburb' , 'suburb_near_two.country'))
// the rest of the query

Categories