f3 framework sql query join - php

I have the following tables:
tbl_users
===============
uid
username
password
gid
tbl_groups
===============
gid
name
type
I am trying to figure out how to use the sqlmapper in f3 to be able to query both tables where username equals $_POST["username"] and be able to get the group name and type as well. Is it possible to join like queries using this framework with sqlmapper?
I've been searching around and can't find any examples on that.

you can try to setup some virtual fields for this:
$mapper->group_name = 'select name from tbl_groups where tbl_groups.gid=tbl_users.gid';
$mapper->group_type = 'select type from tbl_groups where tbl_groups.gid=tbl_users.gid';
$mapper->load(array('uid = ?',123));
echo $mapper->group_name;

Here is the example with {VIEW}:
I have implemented here pagination with SQL Mapper using View view_user_list_with_referral
$dropInstantWinnerView = $this->db->exec("DROP VIEW IF EXISTS view_user_list_with_referral;");
$createInstantWinnerView = $this->db->exec("CREATE VIEW view_user_list_with_referral AS SELECT u.fb_id, fb_link, name, r.referred_by, u.created FROM users u LEFT OUTER JOIN referral r ON u.fb_id=r.joinee ");
$user = new \DB\SQL\Mapper($this->db,'view_user_list_with_referral');
$limit = 20;
$page = Pagination::findCurrentPage();
$order_condition = F3::get("PARAMS.order_condition");
$order_class= "";
if(!empty($order_condition)){
$cond = explode(":", $order_condition);
$option = array('order' => $cond[0].' '.$cond[1]);
if($cond[1]=='ASC'){
$order_condition = $cond[0].':DESC';
$order_class = ":DESC";
}else{
$order_condition = $cond[0].':ASC';
$order_class = ":ASC";
}
}else{
$option = array('order' => 'created DESC');
}
$subset = $user->paginate($page-1, $limit, null, $option);
$pages = new Pagination($subset['total'], $limit);
$pages->setTemplate("admin/pagebrowser.html");
F3::set('pagebrowser', $pages->serve());
//echo "<pre>";print_r($subset);exit;
F3::set('page', $page);
F3::set('order_condition', $order_condition);
F3::set('total_found_records', $user->count());
I hope it will save someones time :)

Related

Mysql get all rows but join if possible [duplicate]

I have 3 mysql tables.
Table 1 user
id | name
Table 2 emails
id | email
Table 3 user_email
user_id | email_id
I have no experience in query multi tables.
Using codeigniter active record, i want to find out the user email address based on the user id, pls advise if the below code is correct ?
$CI->db->select('email');
$CI->db->from('emails');
$CI->db->where('id', $userid);
$CI->db->join('user_email', 'user_email.user_id = emails.id', 'left');
$query = $CI->db->get();
You have wrong where clause you need to compare user_id from your table ,you are comparing the id of email to the provided $user_id
$CI->db->select('email');
$CI->db->from('emails');
$CI->db->where('user_id', $userid);
$CI->db->join('user_email', 'user_email.user_id = emails.id', 'left');
$query = $CI->db->get();
A more useful way is to give aliases to your tables so the tables with same columns will not have any confusion
$CI->db->select('e.email');
$CI->db->from('emails e');
$CI->db->join('user_email ue', 'ue.user_id = e.id', 'left');
$CI->db->where('ue.user_id', $userid);
$query = $CI->db->get();
#m khalid 's answer is correct but I have created a dynamic function to achieve join with multiple tables. Check this out.
function join_records($table, $joins, $where = false, $select = '*', $orderBy = false, $direction = 'DESC'){
$CI->select($select);
$CI->from($table);
foreach($joins as $join){
$CI->join($join[0], $join[1], $join[2]);
}
if($where) $CI->where($where);
if($orderBy) $CI->order_by($orderBy, $direction);
$query = $CI->get();
return $query->result_array();
}
Applying your question to this.
$table = 'emails';
$joins[0][0] = 'user_email';
$joins[0][1] = 'user_email.user_id = emails.id';
$joins[0][2] = 'left';
$where['user_id'] = $userid;
You may add more join like $join1[0]..
If you need to select some specific column you can define in following manner
$select = 'table1.column1, table1.column2, table2.column1, table2.column2'
Or if you want all the columns put a *
$this->join_records($table, $joins, $where, $select);
You may also find it here.

Wordpress/PHP/MySql sort results

I have a query that loads values from the database based upon a province a user lives:
$query = "SELECT * FROM $wpdb->usermeta WHERE meta_key='provincie' AND ( ".$provincie_check.")";
This loads all provinces that a user holds.
Based upon this I load the users:
for($p=0; $p <count($personen); $p++){
$persoon = $personen[$p];
if ($p % 2 == 0){
$oddeven = 'even';
}else{
$oddeven = 'odd';
}
$id = $persoon->user_id;
$user_info = get_userdata($id);
$p_fname = get_user_meta($id, 'first_name', true);
$p_fname = array($p_fname);
sort($p_fname);
}
For every user I create a table to view them. I want them sorted upon ther first name. So I thought I create an array of all first names and sort that.
But no luck.
How can I sort the for-loop to view my users sorted by their first name?
Why you don`t extract them directly with SQL?
$query = "SELECT user_id, meta_value as name
FROM $wpd->usermeta
WHERE meta_key
LIKE 'first_name'
AND user_id
IN (SELECT user_id
FROM $wpdb->usermeta
WHERE meta_key='provincie'
AND ( ".$provincie_check."))
ORDER BY name";

codeigniter active record left join

I have 3 mysql tables.
Table 1 user
id | name
Table 2 emails
id | email
Table 3 user_email
user_id | email_id
I have no experience in query multi tables.
Using codeigniter active record, i want to find out the user email address based on the user id, pls advise if the below code is correct ?
$CI->db->select('email');
$CI->db->from('emails');
$CI->db->where('id', $userid);
$CI->db->join('user_email', 'user_email.user_id = emails.id', 'left');
$query = $CI->db->get();
You have wrong where clause you need to compare user_id from your table ,you are comparing the id of email to the provided $user_id
$CI->db->select('email');
$CI->db->from('emails');
$CI->db->where('user_id', $userid);
$CI->db->join('user_email', 'user_email.user_id = emails.id', 'left');
$query = $CI->db->get();
A more useful way is to give aliases to your tables so the tables with same columns will not have any confusion
$CI->db->select('e.email');
$CI->db->from('emails e');
$CI->db->join('user_email ue', 'ue.user_id = e.id', 'left');
$CI->db->where('ue.user_id', $userid);
$query = $CI->db->get();
#m khalid 's answer is correct but I have created a dynamic function to achieve join with multiple tables. Check this out.
function join_records($table, $joins, $where = false, $select = '*', $orderBy = false, $direction = 'DESC'){
$CI->select($select);
$CI->from($table);
foreach($joins as $join){
$CI->join($join[0], $join[1], $join[2]);
}
if($where) $CI->where($where);
if($orderBy) $CI->order_by($orderBy, $direction);
$query = $CI->get();
return $query->result_array();
}
Applying your question to this.
$table = 'emails';
$joins[0][0] = 'user_email';
$joins[0][1] = 'user_email.user_id = emails.id';
$joins[0][2] = 'left';
$where['user_id'] = $userid;
You may add more join like $join1[0]..
If you need to select some specific column you can define in following manner
$select = 'table1.column1, table1.column2, table2.column1, table2.column2'
Or if you want all the columns put a *
$this->join_records($table, $joins, $where, $select);
You may also find it here.

Unnexpected item-comments depending on query of items

I am using this function to list items from table helps depending on parameters: (I included most of code but you can really just focus on the mysql querys)
function list_helps($by,$value,$page = -1,$ipp = 20){
/* Yes I concatenate querys... so i use some variables to help it a bit */
$sql = 'SELECT helps.* FROM helps ';
$where = ''; $orderBy = ''; $in = ''; $join = ''; $limit = ''; $resultitems = ''; $header = '';
if($page > 0) $limit = 'LIMIT '.$page*$ipp.', '.($page+1)*$ipp; else $limit = 'LIMIT 10';
switch($by){
case 'byuser':
$where = 'WHERE id_user ='.$value;
$orderBy = 'ORDER BY id DESC';
break;
case 'byfriend':
$sql = 'SELECT
h.*,
f.*
FROM (
SELECT
id,
CASE followerid WHEN '.$value.' THEN followingid ELSE followerid END AS friend_id
FROM friends
WHERE acepted = 1
AND (followerid = '.$value.' OR followingid = '.$value.')
) AS f
INNER JOIN helps AS h ON h.id_user = f.friend_id
ORDER BY h.id DESC';
break;
default:
break;
}
$sql .= $where.' '.$orderBy.' '.$limit;
$res = cache_query($sql,'',60*60*5);
/* checks in cache first, if not; executes query.. next code it's to render content */
}
There are more cases but lets focus on those two.
They both serve the 'helps' that are being requested (if user, or if users's friend); The problem is when i am trying to retrieve the comments of those (like if it where a blog post); which I am doing like so:
res = cache_query('SELECT help_replies.content, help_replies.date,
help_replies.offers, help_replies.accepted, help_replies.id_responds,
usuarios.first_name, usuarios.last_name, usuarios.avatar,usuarios.id
FROM help_replies left join usuarios
ON help_replies.id_user = usuarios.id
WHERE help_replies.id_responds = '.$this->id.'
ORDER BY help_replies.id ASC', '', 30);
foreach($res as $obj) {
/* $obj['id_responds'] */
}
}
The thing is that the help_replies.id_responds makes reference to the item, so when the case is 'byuser' is fine; but when the case is 'byfriend' this field is lost (so is showing always the same comments)
Conclusion:
byuser -> helps fine & comments fine
byfriend -> helps fine (which is wierd) & comments wrong
Any Idea why $this->id is not as expected from the (JOINED) query?
-EDIT-
$this->id comes from this construct method (i ommited many atributes)
function __construct($item) {
$this->id = $item['id'];
$this->id_user = $item['id_user'];
..
}
And $item is one iteration of the foreach (so its the returned row converted to array)
Muchas Gracias
Your byfriends query executed by function list_helps(...) appears to return a field labelled id twice; once for your helps table and then again for f the alias of the friends table, as part of the sub-query.
I can imagine that if $this->id contains a friends id and not the helps id then your comments query (help_replies) will return the wrong results.
So perhaps changing your sub-query with an alias for the friends id as shown ie id AS friendsId, everything will work as expected?
function list_helps($by,$value,$page = -1,$ipp = 20){
...
...
case 'byfriend':
$sql = 'SELECT
h.*,
f.*
FROM (
SELECT
id AS friendsId,
CASE followerid WHEN '.$value.' THEN followingid ELSE followerid END AS friend_id
FROM friends
WHERE acepted = 1
AND (followerid = '.$value.' OR followingid = '.$value.')
) AS f
INNER JOIN helps AS h ON h.id_user = f.friend_id
ORDER BY h.id DESC';
break;
I've got into the habit of naming my table identifier field <tablename>Id for this very reason and saves having to use alias everywhere.

PHP: Active record table joins

I have an app that uses the codeigniter CXTags tagging library.
The database structure is as follows:
posts
id
tags_ref
row_id
table
tag_id
tags
id
safe_tag
tag
My query basically goes if $safe_tag is not null then join tags_ref on post.id = tags_ref.row_id, join tags on tags_ref.tag_id = tags.id, where tags_ref.table = 'posts' and tags.safe_tag = 'food'
SELECT * FROM posts
JOIN tags_ref ON posts.id = tags_ref.row_id
JOIN tags ON tags_ref.tag_id = tags.id
WHERE tags.safe_tag = $safe_id
Unfortunately the query I've written in active record is not functioning properly. The query works perfectly when £safe_tag is null but when it's not I get wrong results.
function get_posts($id = NULL, $safe_tag = NULL) {
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
}
//if an id was supplied
if ( $id != NULL ) {
$this->db->where('posts.city_id',$id);
}
// execute query
$query = $this->db->get('posts');
...
Here is the query with profiling on:
SELECT *
FROM (`posts`)
INNER JOIN `tags_ref` ON `posts`.`id` = `tags_ref`.`row_id`
INNER JOIN `tags` ON `tags_ref`.`tag_id` = `tags`.`id`
WHERE `tags_ref`.`table` = 'posts'
AND `tags`.`safe_tag` = 'food'
AND `posts`.`city_id` = '2'
Can someone have a look? I think I need a fresh set of eyes on it.
Your forgot to actually run the query inside your first if{}
if($safe_tag != NULL){
echo $safe_tag;//debugging
$table = 'posts';
$this->db->join('tags_ref', 'posts.id = tags_ref.row_id');
$this->db->join('tags', 'tags_ref.tag_id = tags.id');
$this->db->where('tags_ref.table', $table);
$this->db->where('tags.safe_tag',$safe_tag);
$this->db->get(); // here
}

Categories