Codeigniter JOIN dont back db result - codeigniter

Codeigniter dont back database result.
Database table "Category" and "Sub Category"
DB Shema:
Categor
-----------------------------
ID Name
----------------------------
1 Fishing
2 Hunting
3 Test Category
Sub_category
-----------------------------
ID cat_id name
----------------------------
1 1 Fishing rod
2 2 Hunting ammunition
3 3 Test sub category
I want list all sub category for some category. When some1 click on Fishing category i want show all sub category for fishing. My code is this:
Controller:
public function get_sub_category($id = 0)
{
$this->load->model('front_m');
$data['sub_cat'] = $this->front_m->show_sub_cat($id);
$this->template->set_theme('zend')->set_layout('front.html')
->build('sub_category',$data);
}
MODEL:
public function show_sub_cat($id=0)
{
$this->query = $this->db->select('*');
$this->query = $this->db->from('category');
$this->query = $this->db->where('id='.$id');
$this->query = $this->db->join('sub_category', 'sub_category.cat_id=category.id');
$this->query = $this->db->query('SELECT * FROM category');
$this->query = $this->db->get();
if ($this->query->num_rows() > 0) {
$this->query->result();
}
return $this->query ;
}
What is wron i all time have DB error or blanko page.

Based on your question it sounds like your over thinking it, but I'm a bit confused as well. What I'm hearing is: How can I get my sub categories based on someone clicking on a main category id? If that's the case then your making it way more complicated than it needs to be.
MODEL
public function show_sub_cat($catid=NULL)
{
$result = $this->db->get_where('sub_category',array('cat_id'=>$catid));
if ($result->num_rows()>0)
{
return $result->result();
}
}

$sql_query ="SELECT
c.name,
sc.*
FROM Category as c
LEFT JOIN Sub_category as sc ON sc.cat_id = c.ID
WHERE c.ID = $id";
return $this->db->query($sql_query)->result();

Related

Laravel 7: How to match two tables column?

Please see my code first,
Measurement Table:
id
customer_id
service_id
1
1
2
2
1
3
2
2
Controller:
$customer = Customer::findOrFail($id);
$ex = Measurement::where('customer_id', $id)->pluck('service_id');
if(count($ex) == 0){
$service = Service::where('status', 0)->get();
}
else{
$service = Service::where('id', '!=', $ex)->where('status', 0)->get();
}
In Measurement table, if a customer doesn't have any service_id then $service = Service::where('status', 0)->get(); this will pass in view file.
If a customer have a service_id, then in view file all services will pass except that service_id.
Can anyone suggest me a better way for this?
How about this
$customer = Customer::with('services')->where('customer_id', $id)->first();
$serviceRowCount = 0;
if ($customer->services->count() > 0) {
$services = $customer->services->whereNotNull('service_id');
$serviceRowCount = $services->count();
}
if ($serviceRowCount > 0) {
$services = Service::whereNotIn('id', $services->pluck('service_id'))->get();
} else {
$services = Service::where('status', 0)->get();
}
return view('test')->compact('services');
I am assuming that Customer has primary key as customer_id, has relation with Measurement model as services and service_id has default value as null.

Laravel Pivot Table, Get Room belonging to users

The structure of my pivot table is
room_id - user_id
I have 2 users that exist in the same room.
How can I get the rooms they both have in common?
It would be nice to create a static class to have something like this.
Room::commonToUsers([1, 5]);
Potentially I could check more users so the logic must not restrict to a certain number of users.
Room::commonToUsers([1, 5, 6, 33, ...]);
I created a Laravel project and make users, 'rooms', 'room_users' tables and their models
and defined a static function in RoomUser Model as below :
public static function commonToUsers($ids)
{
$sql = 'SELECT room_id FROM room_users WHERE user_id IN (' . implode(',', $ids) . ') GROUP BY room_id HAVING COUNT(*) = ' . count($ids);
$roomsIds = DB::select($sql);
$roomsIds = array_map(function ($item){
return $item->room_id;
}, $roomsIds);
return Room::whereIn('id', $roomsIds)->get();
}
in this method, I use self join that the table is joined with itself, A and B are different table aliases for the same table, then I applied the where condition between these two tables (A and B) and work for me.
I hope be useful.
I don't know the names of your relations, but I guess you can do like this :
$usersIds = [1, 5];
$rooms = Room::whereHas('users', function($query) use ($usersIds) {
foreach ($usersIds as $userId) {
$query->where('users.id', $userId);
}
})->get();
It should work. whereHas allows you to query your relation. If you need to have a static method, you can add a method in your model.
There might be a more efficient way but laravel collection does have an intersect method. You could create a static function that retrieves and loop through each object and only retain all intersecting rooms. something like this
public static function commonToUsers($userArr){
$users = User::whereIn('id',$userArr)->get();
$rooms = null;
foreach($users as $user){
if($rooms === null){
$rooms = $user->rooms;
}else{
$rooms = $rooms->intersect($user->rooms);
}
}
return $rooms;
}
This code is untested but it should work.
Room has many users, user has many rooms, so you can find the room which have those two users.
If your pivot table's name is room_users, then you can easily get the common room like this:
public static function commonToUsers($user_ids) {
$room = new Room();
foreach($user_ids as $user_id) {
$room->whereHas('users', function($query) use ($user_id) {
$query->where('room_users.user_id', $user_id);
});
}
return $room->get();
}
This code will convert to raw sql:
select *
from `rooms`
where exists (
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 1
)
and exists
(
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 5
)

Get User Ranking based on number of posts (Codeigniter)

I have a number of users who are posting content to the POSTS Table.
id user_id content
1 1 text
2 3 text
3 1 text
4 1 text
5 2 text
6 3 text
Now, I would like to get a single user rank by highest posts(row). I'm confused about how to get the result!
Asuming that you are using the query builder, from the model, you can use the following statement to obtain the required result:
$this->db->select('user_id, count(content) as total_posts')
->group_by('user_id')
->order_by('total_posts', 'DESC')
->limit(1)
->get('POSTS')
->row();
The issue has been solved. Here is the explanation of how I've done this:
model
public function get_user_ranking()
{
$this->db->select('user_id, count(id) as total_posts');
$this->db->group_by('user_id');
$this->db->order_by('total_posts', 'DESC');
$query = $this->db->get('posts');
return $query->result();
}
controller
$data['user_ranking'] = $this->post_model->get_user_ranking();
view
$rank = 1; foreach($user_ranking as $row)
{
if( $row->user_id == $user->id)
{
echo $rank;
break;
}
$rank++;
}
public function get_user_ranking()
{
$this->db->select('user_id, count(id) as total_postings');
$this->db->from('posts');
$this->db->group_by('user_id');
$this->db->order_by('total_posts', 'DESC');
return $this->db->get()->result();
}

Self Join in Eloquent - How To Call

I recently asked a question regarding a self join
SO
I got a great answer but I'm not sure how to call it.
I need to do this query:
SELECT t2.title FROM products t1, products t2
WHERE t1.id = $id
AND t2.color_id = t1.color_id AND
t2.id != $id
I now have this on my products model:
public function parent()
{
return $this->belongsTo(self::class, 'color_id');
}
public function children()
{
return $this->hasMany(self::class, 'color_id');
}
But how do I call this?
Product::with('children')->find(1);
The above gets the product with id 1 but also gets children that have a color_id of 1, I need to get children who have a color_id the same as the id as product 1.
eg.
Products
id | title | color_id
1 dvd 2
When I select row 1 it should select all other products with a color_id of 2.
I believe your relations are not the way they're supposed to be. Usually it's one column (foreign key - color_id in your case) having a value of the other one (usually primary key - id in your case).
What you have is basically a value the records share or a "category". So your products are not "children" but rather siblings (have the same parent color).
Since with method is not build as a JOIN statement but as eager loading (separate query) you can do that manually.
Probably the most straight forward way:
$product1 = Product::find(1);
$children = Product::where('id', '<>', $product1->id)->
where('color_id', $product1->color_id)->
get();
You can add select('title') to the second "builder" to get only title but that would not be your model anymore. Or you can use lists('title') to extract only titles if that's what you need.
UPDATE:
If you decide you need the JOIN after all I'd suggest going with raw query builder and leave the Eloquent out of it:
$res = DB::table('products as t1')->
select('t2.title')->
join('products AS t2', 't2.color_id', '=', 't1.color_id')->
where('t1.id', 1)->
where('td2.id', '<>', 't1.id')->
get();
I believe it should build something similar to what you need.
You can try this way:
// Category.php
public function children()
{
return $this->hasMany(Category::class, 'parent_id');
}
public function parent()
{
return $this->belongsTo(Category::class, 'parent_id');
}
// To access
$category->children; // sub-categories collection
$category->parent; // parent instance
based on : https://laracasts.com/discuss/channels/eloquent/self-join-in-eloquent-model?page=1
You might want to do as follow :
$id = 1;
$product = Product::with('children')->whereHas('children', function($q) use ($id)
{
$q->where('color_id', $id);
})->find($id);
See Advanced Join Clauses and adapt from my example here.
It took me a long time to wrap my head around Laravel joins.
This:
$postIds = DB::table('comments as t1')
->select('t1.*')
->leftJoin('comments as t2', function ($join) {
$join->on('t1.postId', '=', 't2.postId')
->on('t1.created_at', '<', 't2.created_at');
})
->where('t2.id', '=', null)
->orderBy('t1.created_at', 'DESC')
->simplePaginate(20)
->pluck('postId');
seems to be the way to get an array of the postIds that would be revealed by this:
SELECT t1.*
FROM comments a
LEFT OUTER JOIN comments b
ON t1.postId = t2.postId
AND t1.created_at < t2.created_at
WHERE t2.id IS NULL
ORDER BY t1.created_at DESC
SELECT subcat.CategoryName as SubCat cat.CategoryName as Category FROM bn_bas_categories cat, bn_bas_categories subcat WHERE cat.CategoryID = subcat.ParentID;

codeigniter LEFT JOIN array issue

Can someone tell me how to write this properly?
function get_tech() {
$this->db->select('u.id
,u.first_name
,us.id
,us.group_id');
$this->db->from('users u');
$this->db->join('users_groups us','us.id = u.id','left');
$records = $this->db->where('us.group_id', '3');
$data=array();
foreach($records->result() as $row)
{
$data[$row->id] = $row->first_name;
}
return ($data);
}
I'm trying to populate a drop down menu using an array, but i need to only grab users that are part of users_group/group_id = 3
therefore in my very limited knowledge I'm needing:
select X from Users LEFT JOIN users_groups WHERE group_ID = 3
You need to call $this->db->get() in order to actually run your query.
function get_tech() {
$this->db->select('u.id
,u.first_name
,us.id
,us.group_id');
$this->db->from('users u');
$this->db->join('users_groups us','us.id = u.id','left');
$this->db->where('us.group_id', '3');
$records = $this->db->get();
$data = array();
foreach($records->result() as $row){
$data[$row->id] = $row->first_name;
}
return $data;
}

Resources