Yii2: How to select multiple fields from different tables - mysql

My tables
Category
id_category
name
Post
id_post
category_id
title
My query:
Post::find()
->select('post.*, c.name AS catname')
->leftJoin('category c', 'c.id_category = category_id')
->all();
The output just shown the table fields Post, is not the field catname.

1) Define a relation in Post model named 'category', so:
public function getCategory() {
return $this->hasOne(Category::className(), ['id_category' => 'category_id']);
}
2) Then when you query the posts, use 'with' if you need to get category name for each post:
$posts = Post::find()
->with('category')
->all();
3) You can access to category name with:
$post->category->name

Related

Join and OrderBy within with laravel eloquent query

I want to display ordered list of stores based on cities from a brand.
This is the code I tried
$brand = Brand::where('slug','=',$slugurl)
->with(['stores' => function($q){
$q->where('status', 1)
->join('cities', function ($join){
$join->on('cities.id', '=', 'stores.city_id')->orderBy('cities.sort_number', 'DESC');
});
}])
->firstOrFail();
The relationship of the tables :
Brand hasMany Stores and Stores belongTo Cities
The listings results output is not ordered based on cities sort_number. Any idea how to achieve this ?
It is useless to order in join's closure.
You need to append the orderBy after join:
$brand = Brand::where('slug','=',$slugurl)
->with(['stores' => function($q){
$q->where('status', 1)
->join('cities', 'cities.id', '=', 'stores.city_id')
->orderBy('cities.sort_number', 'DESC');
}])
->firstOrFail();
This query convert to raw sql is:
select * from brands where slug = ? limit 1;
select * from stores
join cities on cities.id = stores.city_id
where status = 1 and stores.brand_id in (?)
order by cities.sort_number desc;

Compare two fields within different table using Laravel

I have two tables employees and customers , i've gave the schema below.
Customers('id' , 'username', 'location');
Employees('id' , 'EmployeeID' , 'CustomerID', 'location');
Currently I can use a query to retrieve customers details like the below query , note this is when the user is logged into the system hence the Auth::
$customerQuery1 = DB::table('customer')
->where('id', '!=', Auth::id())
->where('item', '=' , Auth::customer()->recommendation)
->get();
Each Employee has many customers ,I want other customers to see other customer items so i have attach the CustomerID field which is a foreign key and relates to the id field within the Customer table.
I've tried something like the below however I think I may need a join query but i'm unsure.
$query2 = DB::table('Customer','Employee')
->select('username')
->where(['EmployeeID' => Auth::id(), 'CustomerID' => 'id'])
->get();
$query2 = DB::table('Customer')
->select('username')
->join('Employee', 'Customer.id', '=', 'Employee.CustomerID')
->where(['EmployeeID' => Auth::id(), 'CustomerID' => 'id'])
->get();
I am then returning the values to my blade file like the below
return view ('pages.dashboard')
->with('query1',$query1)
and then Im using php indentation within my blade file to return the users data
#foreach ($query1 as $Userfound)
{{ $Userfound->username}}</p>
#endforeach
Actual Query needed in plain english
so I need to select a customer , where CustomerID == id
NOTE: id is from the customers table, CustomerID stored in the Employees table.
You can create Models using Laravel, for example:
Employee.php
public function customers()
{
return $this->hasMany('App\Customer');
}
Customer.php
public function employee()
{
return $this->belongsTo('App\Employee');
}
Which you can access like so:
$customer = Customer::where('id',Auth::user()->id)->firstOrFail();
or
$employee = Employee::where('id',Auth::user()->id)->firstOrFail();
And to see an employee's customers:
$employee->customers()->get();
Or to see the other customers of $customer's employer:
$customer->employee()->customers()->get();

Laravel Many to Many How to form query in eloquent or in query builder

From the following query im getting the expected result:
SELECT *
FROM rooms r
JOIN amenities_room am
ON r.id = am.room_id
JOIN amenities a
ON am.amenities_id = a.id
AND a.id IN (2,3)
GROUP BY r.id
HAVING COUNT(*)=2;
How can i for the query in laravel way in (Eloquent or in Query Builder)
Note:
The following tables are involved:
rooms
id
number
name
amenities
id
name
amenities_room
room_id
amenities_id
$rooms = Room::with('amenities')
->withCount('amenities', function($query){
$query->whereIn('id', [2, 3]);
})
->where('amenities_count', 2)
->get()
Docs for counting related models: https://laravel.com/docs/5.5/eloquent-relationships#counting-related-models
You got this error mb_strpos() expects parameter 1 to be string, object given because your eloquent is expecting a string but you have passed an object here in withCount() try this
$rooms = Room::with('amenities')
->withCount('amenities')->where(function($query){
$query->whereIn('id', [2, 3]);
})
->where('amenities_count', 2)
->get()

Column 'name' in field list is ambiguous codigniter

this is my table structure.
tbl_user:
companyname,name,email.
tbl_userinfo:
phone,address,area,state,city,description.
tbl_category:
category_id,name.
i am joining three tables here is my model
$this->db->select(array('name', 'companyname','phone','address','email','state','city','pincode','area','description','image', 'c.name AS categoryname'));
$this->db->from('tbl_user');
$this->db->join('tbl_userinfo', 'tbl_userinfo.user_id = tbl_user.user_id');
$this->db->join ('tbl_category', 'tbl_category.category_id = tbl_userinfo.service_category');
$this->db->group_by(array('name', 'companyname', 'phone', 'address', 'email','state','city','pincode','area','description','image','categoryname'));
//$this->db->order_by('tbl_category.category_id');
$this->db->where(array('tbl_user.user_id' => 16));
i wanted third column name as well but i m getting Column 'name' in field list is ambiguous codigniter
another code that i did use but it wont show me any values for joining of two table.
$this->db->select(array('tbl_user.name', 'tbl_user.companyname','tbl_userinfo.phone','tbl_userinfo.address','tbl_user.email','tbl_userinfo.state','tbl_userinfo.city','tbl_userinfo.pincode','tbl_userinfo.area','tbl_userinfo.description','tbl_userinfo.image', 'tbl_category.name'));
$this->db->from('tbl_user');
$this->db->join('tbl_userinfo', 'tbl_userinfo.user_id = tbl_user.user_id');
$this->db->join ('tbl_category', 'tbl_userinfo.service_category = tbl_category.category_id');
$this->db->group_by(array('tbl_user.name', 'tbl_user.companyname','tbl_userinfo.phone','tbl_userinfo.address','tbl_user.email','tbl_userinfo.state','tbl_userinfo.city','tbl_userinfo.pincode','tbl_userinfo.area','tbl_userinfo.description','tbl_userinfo.image', 'tbl_category.name'));
$this->db->where(array('tbl_user.user_id' => 16));
This is most likely happening because two of your tables both have a 'name' column. I would suggest explicitly selecting the column by using [table name].[column].
$result = $this->db->query('past your query here after checking it in an sql browser');
Try this:
$user_id = '16';
$query = $this->db->select('tbl_user.companyname, tbl_user.name as UserName, tbl_user.email, tbl_userinfo.phone, tbl_userinfo.address, tbl_userinfo.area, tbl_userinfo.state, tbl_userinfo.city, tbl_userinfo.description, tbl_category.category_id, tbl_category.name as CategoryName')
->from('tbl_user')
->join('tbl_userinfo', 'tbl_userinfo.user_id = tbl_user.user_id')
->join ('tbl_category', 'tbl_category.category_id = tbl_userinfo.service_category')
->where('tbl_user.user_id', $user_id)
->group_by('tbl_user.companyname')
->get()
->result();
You can replate 'tbl_user.*' with the columns names you want to get from that table, example: 'tbl_user.user_id, tbl_user.name as UName, tbl_category.name as CName' change the name of column if you have 2 or more columns with the same name in diferent tables you are joining, it will create always an ambiguous error because there are 2 columns with the same name and codeigniter doesn't know which one you want, if you want both you need to rename the both columns.
Also add the join to left because if there is no user_id or category_id it will not display you the result.
Hope this will help you.
comes with my own code.
$this->db->select(array('u.name', 'u.companyname','i.phone','i.address','u.email','i.state','i.city','i.pincode','i.area','i.description','i.image', 'c.name AS categoryname'));
$this->db->from('tbl_user as u');
$this->db->join('tbl_userinfo as i', 'i.user_id = i.user_id');
$this->db->join ('tbl_category as c', 'c.category_id = i.service_category');
$this->db->group_by(array('u.user_id'));
$this->db->where(array('u.group_id' => 16));
$query = $this->db->get ();
return $query->result();

CakePHP sub query SQL in HABTM relation

I want to suggest related products by tags and sort order by the most matched.
the HABTM model association between Product and Tag
class Product extends AppModel {
//..
var $hasAndBelongsToMany = array("Tag");
//..
}
and vice versa in Tag model. also join-table name is "products_tags".
for Ex.sample..
//just sample of Product contain Tag data
$products[0]['Tag'] = array('touch', 'phone', '3G', 'apple'); //iPhone
$products[1]['Tag'] = array('phone', '3G', 'BB'); //BB
$products[2]['Tag'] = array('touch', '3G', 'apple'); //iPad
$products[3]['Tag'] = array('3G', 'air card'); //3G air card
in this sample the most related to iPhone sort by priority are..
ipad (found in 3 tags)
BB (found in 2 tags)
aircard (only 1 matched)
How Cake's way using Model find() to get sub-query like this:
SELECT DISTINCT (product_id) AS id, (
/* sub-query counting same tags*/
SELECT COUNT(*) FROM tags as Tag
LEFT JOIN products_tags AS ProductTag ON ( Tag.id = ProductTag.tag_id )
WHERE product_id = id
AND Tag.name IN ( 'touch', 'phone', '3G', 'apple' )
) AS priority /*this is weight count by how many same tags*/
FROM `tags` as Tag
LEFT JOIN products_tags AS ProductTag ON ( Tag.id = ProductTag.tag_id )
WHERE Tag.name
IN ( 'touch', 'phone', '3G', 'apple' )
ORDER BY priority DESC
SQL query above return exactly what I needed. but I can't find the way to parse params to CakePHP's AppModel->find() method.
If the result of this sql does not use pagination (assuming that related products in a normal webpage are 3-5 entries) why don't you use this complex SQL instead?
i.e. create a function relatedProducts() in your Product model
then use $this->query($sql)
sample code will be:
class Product extends AppModel {
//..
var $hasAndBelongsToMany = array("Tag");
//..
function relatedProducts($parameters){
$sql = "select..... where ....$parameters...";
return $this->query($sql);
}
}
Then you can use it in the controller by
$this->Product->relatedProducts($some_parameters);