codeigniter join changing id from one table's id to another - php

I have this code for an active record query in codeigniter:
$this->db->join('user', 'user.id = purchase_req.owner_id', 'inner');
$this->db->where('user.employer_id', $User->employer_id);
$Purchase_req = $this->Purchase_req->find();
In a view without the join statement, $Purchase_req->id would return the actual purchase request id. In the view with the join, $Purchase_req->id returns the user id. How can I join the tables together, and still get the purchase request id, instead of it changing to the user.id?

The id you want to achieve is the ambiguous for mysql because the both tables have the id columns therefore when you tries to access the $Purchase_req->id it will return the last id column which is from the purchase_req table you need to assingn the unique aliases for the same columns in the joined table like
$this->db->select('`user`.*,`purchase_req`.*,`user`.id AS user_id')
$this->db->join('user', 'user.id = purchase_req.owner_id', 'inner');
$this->db->where('user.employer_id', $User->employer_id);
$Purchase_req = $this->Purchase_req->find();
Now when you echo $Purchase_req->user_id it will return the user.id

Related

Joining two tables in codeginiter

I have 2 tables that i want to join & show the name of user's role. here's the situation
My 2 tables are users_mlh & user_roles_mlh
on the role column of users_mlh table i'm storing the ID of user role, user_roles_mlh contains the name & id of user role. what i want to do is show the name of the user role in my view.
my tables as follows.
i have tried this in my model
$this->db->select('*');
$this->db->from('user_roles_mlh');
$this->db->join('users_mlh', 'users_mlh.role = user_roles_mlh.id');
$this->db->where('users_mlh.role = user_roles_mlh.id');
$query = $this->db->get();
return $query->result_array();
but from above i get something like this
at the moment it lists all user level not the role of each individual user
Case 1 : If you Directly want to Access all data without using where condition
$this->db->select( "*" );
$this->db->from( 'users_mlh' );
$this->db->join('user_roles_mlh', 'user_roles_mlh.id = users_mlh.role');
Case 2: With Where Condition and specific column data
$this->db->select( 'user_roles_mlh.role_type,users_mlh.name' );
$this->db->from( 'users_mlh' );
$this->db->join('user_roles_mlh', 'user_roles_mlh.id = users_mlh.role');
$this->db->where('users_mlh.id =',1);
And finally get the results by
$query = $this->db->get();
return $query->result();
No need to write separate query for getting role name. Join Roles table when you fetching users data..
$this->db->select('users_mlh.*,user_roles_mlh.role_type');
$this->db->from('users_mlh');
$this->db->join('user_roles_mlh', 'user_roles_mlh.id = users_mlh.role');
$query = $this->db->get();
return $query->result_array();
Try this.
If I use your tables, you should have the following request:
SELECT users_mlh.*, JOIN user_roles_mlh.role_type
FROM users_mlh -- list all users
LEFT JOIN user_roles_mlh -- and joind by roles
ON users_mlh.role = user_roles_mlh.id -- condition for joining
With this request, you will have all your users, with the role text associated.
So, if this request works, use the same logic on your ORM

Laravel 5 - how to perform left join on same table

In my application, there's two tables at the moment: users and employees. The latter is simply a profile table for the boilerplate users table that ships with Laravel.
I have two foreign keys inside of employees, one is user_id that points to id on users table. So basically, the profile data of the registered user. The second foreign key in employees is manager_id. That is the id of the person who is the manager of an employee. Some users are managers and have a blank manager_id field.
I want to retrieve the row from my Employee model where the user_id matches the manager_idand then send them all to my view, where they will see the first_name and last_name of the manager. At the moment I see the manager ID instead of their name.
Sample LeftJoin =>
DB::connection('testing')->table('table1 as t1')
->select('t1.column, t2.column')
->leftJoin('table2 as t2','t2.client_id','=','t1.id')
->get();
Try some thing like this:
$users = DB::table('users t1')
->join('users t2', 't1.id', '=', 't2.user_id')
->select('your column list')
->get();
// here we are creating 2 aliases for users table which make it self join
In your Employees model add the following method:
public function manager()
{
return $this->hasOne('App\User', 'id', 'manager_id');
}
You can then get the name of the Manager like this:
$employee = \App\Employee::find(1);
$manager = $employee->manager()->first();
$manager_name = $manager->name;

Complex Query in CodeIgniter Active Record or Ignited Datatables

Following is the query to take all records from page table and respective access_level from role_page_access table, join together by page.id for a given roleid. $roleid is the parameter to this method.
$query = 'select p.*,t.access_level from page p '.
'left join (SELECT p.id,rpa.role_id,rpa.access_level FROM page p '.
'left join role_page_access rpa on rpa.page_id = p.id '.
'where rpa.role_id = ' . $roleid . ') as t on p.id = t.id';
Actually, I need to use this query for ignited datatables. But at least if I can convert this to active record, that will be very helpful.
Is there a way to just specify regular query in active records?
Otherwise how to convert this to active records?
UPDATE:
page table has pages and role_page_access table has mapping between userrole and page with an integer field "access_level" to specify have access or not. If there are no mapping also considered as no access.
I want all the records from page and matching access_level from role_page_access by pageid and given role. So there will be null access_level if no matching records found in mapping table.
I have to use this in $this->db or $this->datatables.
You can do it with activerecord like this:
$this->-db->select('page.*,role_page_Access.access_level');
$this->db->from('page');
$this->db->join('role_page_access', 'role_page_access.page_id = page.id', 'left outer');
$this->db->where('role_page_access.role_id', $role_id);
$query = $this->db->get();
foreach($query->result() as $row) {
if(empty($row->access_level)) {
echo 'Role does not have access';
} else {
echo 'Role has access';
}
}
That will join the page table records with the role_page_access table records by the page.id field if it matches, filtered by the role_id you pass along.
You can even do method chaining if you have a supported PHP version, check the reference here.
Update
If you still want to retrieve page records even if that role_id does not have access you just have to set the join as left outer:
$this->db->join('role_page_access', 'role_page_access.page_id', 'left outer');
That'll give ALL pages records, even if they don't match a role on role_page_access and the resultset object will have a NULL value on role_page_access. I updated the original code to show you an example.
Update 2
If you want to filter by role_id but still have the unmatched records:
$this->db->where('role_page_access.role_id', $role_id);
$this->db->or_where('role_page_access.role_id', NULL);
But you will have to filter them by the access_level to check if is NULL cause if it is, it means that there was no matching page for the page_id and the role_id (that you passed as param) combination:

CodeIgniter PHP - How to choose which ID to select in a join while using "select *"

Basically, I've got this coding convention that any primary key which is an ID, I will call the column name "id". So here comes my problem. I'm joining two tables and I'm getting the ID of the second table instead of the first table. I know if I use select "artists.id, ..." it will work, but I want to know if there's a fix with using "select *" which would be better for future expansion (new colums will come ...).
Here's my model:
$this->db->select('*');
$this->db->from('artists');
$this->db->join('categories', 'artists.category_id = categories.id');
$this->db->where('id', $id);
$this->db->limit(1);
With Print_R I can see I'm getting all columns (but only 1 id, which is from the categories table instead of artists table) without any table prefix.
You should qualify your columns with a table alias
$this->db->select('a.id as artist_id, c.id as category_id, a.column2,c.column3');
$this->db->from('artists a');
$this->db->join('categories c', 'a.category_id = c.categories.id');
$this->db->where('a.id', $id);
$this->db->limit(1);
If you want to continue using SELECT *
$this->db->select('a.*, c.*, a.id as artist_id, c.id as category_id');
$this->db->from('artists a');
$this->db->join('categories c', 'a.category_id = c.categories.id');
$this->db->where('a.id', $id);
$this->db->limit(1);
Keep in mind, that the LAST duplicate column will be returned. So, a.*,c.* will return c.id as id and c.*,a.* will return a.id as id.
I think to save you trouble and for the future, always use the table in front of the column name.
There is no logic here, when you look for * it means all fields, in Oracle for example you will get all fields with the table in front, i guess in MySQL it doesn't, but if i were you, i would not risk it.

symfony doctrine pagination brings more data than set per page

I am setting 1 row per page in symfony pager but its showing more data than 1. It is because my query is left joining the sfGuardUser table with other tables and it is causing duplication of 'sfGuardUser' row in some cases when there are multiple entries in 'license' table for that particular user ! Here is my query:
$pager = new sfDoctrinePager('sfGuardUser', '1');
$q = Doctrine_Query::create()
->select('u.id, u.username, g.name, l.id, l.status, l.client_id, l.vendor_id, l.applied_date, p.org_name')
->from('sfGuardUser u')
->leftJoin('u.Profile p')
->leftJoin('u.Groups g')
->leftJoin('u.LicensedClients l')
->where('g.name = \'vendor\'')
->orderBy('l.applied_date');
$q->setHydrationMode(Doctrine_Core::HYDRATE_SCALAR);
$pager->setQuery($q);
$pager->setPage($request->getParameter('page', 1));
$pager->init();
The pagination is there, but problem is in some cases there are multiple rows shown in one page when there are multiple rows for a particular user in the license table. How can I implement it in a right way ?
What do you want to achieve with joining user and license table (1:n relation) when paging through (sfGuard)Users ?
If you want to sort users by license type/date/count, you could use
DISTINCT u.id, u.username

Categories