I am developing a web application using codeigniter.In there i am making a part to show images like in facebook as this screenshot.
For that i have created two database table.One to keep album names with user id.One for to keep images names with album id.Here i am providing the screenshot of two table.
I have lot of albums in the album table for one user.now i have entered only one data to this table just for test.how can i select only one image from one album to create album view like in Facebook wish i have shown in the top of this question as screenshot.I create a query like this in the model to select image.
$username=$this->session->userdata('username');
$this->db->select('id');
$this->db->where('email',$username);
$query=$this->db->get('user');
foreach ($query->result() as $row)
{
$user_id= $row->id;
}
$this->db->select('*');
$this->db->where('album_images.user_id',$user_id);
$this->db->from('album_images');
$this->db->join('album', 'album.id = album_images.album_id');
$query = $this->db->get();
return $query->result();
How can improve this code to select only one image from each album and pass all the details of that image such as image id, album_id,album_name,image_name to the view?
try this
$this->db->select('uai.album_id, ua.album_name, uai.id as image_id, uai.image_name');
$this->db->from('user as u');
$this->db->join('album as ua', 'ua.user_id = u.id', 'left');
$this->db->join('album_images as uai', 'uai.user_id = u.id AND uai.album_id = ua.id', 'left');
$this->db->where('u.email',$this->session->userdata('username'));
$this->db->group_by('uai.user_id, uai.album_id');
$this->db->order_by('ua.album_name ASC');
$query = $this->db->get();
return ($query->num_rows() > 0) ? $query->result() : false;
Output will like following
Array
(
[0] => stdClass Object
(
[album_id] => 1
[album_name] => Apple
[image_id] => 1
[image_name] => Apple1.jpg
)
[1] => stdClass Object
(
[album_id] => 2
[album_name] => Orange
[image_id] => 3
[image_name] => Orange1.jpg
)
)
image_name will return one image from album_images table
ex. `[image_name] => Apple1.jpg` from (Apple1.jpg,Apple2.jpg,Apple3.jpg ..etc)
Related
If you get the following code :
$DBConnection =
CreateNewDBConnection(Yii::$app->get('db_cdh'),$aDatabaseName);
$DBConnection->open();
$command = $DBConnection->createCommand($aQuery);
$queryres = $command->queryAll();
If there is result from the query, I get an array, like this
Array
(
[0] => Array
(
[name] => 2.6.084.545
[xdim+2] => 70
)
[1] => Array
(
[name] => 2.5.102.030
[xdim+2] => 60
)
[2] => Array
(
[name] => 2.5.141.560
[xdim+2] => 80
)
)
But if the result of the query is empty, i get an empty array.
How is it possible to get the columns name ?
The reason why I'm asking this, it's because I'm asking queries to multiple DBs and some have results (1 or more lines) and otherd not. The system almost works, but the grid view parse only the first line to find the columns to display. So depending on the order result across the multiple DB, the grid view display the columns or not, depending what come first ....
Any help welcome.
You can take the column names using yii\db\TableSchema and use them afterwards:
$columns = [];
if (empty($queryres)) {
$columns = $DBConnection->getTableSchema('your_table_name')->getColumnNames();
}
public function getInterests($userID) {
$result = $this->tableGateway->select(function (Select $select) use ($userID) {
$select->join('interests', 'users_interests.interest_id = interests.interest_id', array('*'), 'left');
$where = new Where();
$where->equalTo('user_id', $userID);
$select->where($where);
});
return $result;
}
Here is my method. It simply selects all records from users_interests with user_id = $userID and joins the 'interests' table. So far, so good, but when trying to display the fetched results, the fields from the joined table just do not exist. Here is the dump of the $result:
Zend\Db\ResultSet\ResultSet Object
(
[allowedReturnTypes:protected] => Array
(
[0] => arrayobject
[1] => array
)
[arrayObjectPrototype:protected] => Object\Model\UsersInterests Object
(
[settings_id] =>
[user_id] =>
[interest_id] =>
)
[returnType:protected] => arrayobject
[buffer:protected] =>
[count:protected] => 2
[dataSource:protected] => Zend\Db\Adapter\Driver\Pdo\Result Object
(
[statementMode:protected] => forward
[resource:protected] => PDOStatement Object
(
[queryString] => SELECT `users_interests`.*, `interests`.* FROM `users_interests` LEFT JOIN `interests` ON `users_interests`.`interest_id` = `interests`.`interest_id` WHERE `user_id` = :where1
)
[options:protected] =>
[currentComplete:protected] =>
[currentData:protected] =>
[position:protected] => -1
[generatedValue:protected] => 0
[rowCount:protected] => 2
)
[fieldCount:protected] => 6
[position:protected] =>
)
I badly need help on this because I am supposed to finish my project until Sunday. Thanks in advance.
You can use the following to apply left join. $select::JOIN_LEFT instead of 'left'.
public function getInterests($userID) {
$result = $this->tableGateway->select(function (Select $select) use ($userID) {
$select->join('interests', 'users_interests.interest_id = interests.interest_id', array('*'), $select::JOIN_LEFT);
$where = new Where();
$where->equalTo('user_id', $userID);
$select->where($where);
});
return $result;
}
It seems you have a problem in the WHERE clause of the join. This also shows in the error here:
[queryString] => SELECT `users_interests`.*, `interests`.* FROM `users_interests` LEFT JOIN .
`interests` ON `users_interests`.`interest_id` = `interests`.`interest_id`
WHERE `user_id` = :where1
Try this:
$select->from($this->table)
->join('interests', 'users_interests.interest_id = interests.interest_id',
array('*'), 'left');
$where = new Where();
$where->equalTo('user_id', $userID) ;
$select->where($where);
I can not follow your code completely, like here:
$this->tableGateway->select(function (Select $select) use ($userID) {
But, here is a very nice article on this. I think, you can simplify your code a little.
Have you iterated over the resultset? You can see there's two matching rows:
[rowCount:protected] => 2
You have a ResultSet object, but it will not load any of the rows until requested, they are "lazy loaded" when you iterate over the object.
You can force the resultset to get them all for you:
var_dump($resultSet->toArray()); // force load all rows
or iterate over the ResultSet:
foreach($resultset as $row) {
var_dump($row); // each row loaded on request
}
I have written about this before and maybe it will help you as well.
TableGateway with multiple FROM tables
$conditions = Array
(
[table] => products_pages
[alias] => ProductsPage
[type] => inner
[foreignKey] =>
[conditions] => Array
(
[0] => ProductsPage.product_id = Product.id
)
)
I'm trying to set up NOT EXISTS conditions, like the following SQL statement:
SELECT * FROM products_pages,products
WHERE NOT EXISTS (SELECT id
from products_pages
where products_pages.product_id = products.id)
So basically select any product that doesn't exist in the products_pages table.
What is the proper way to format that SQL statement for CakePHP and replace it here:
[conditions] => Array
(
[0] => (What's the proper way to insert above SQL here?
)
Would really appreciate your help guys, I've been trying to figure this out for about 5 hours with no luck. Thanks!
You can always use query if you don't find the way to do it with CakePHP:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query
In this case security wouldn't be compromised as you are not using any input.
Anyway, something simple would be just to do it in more than one step:
//selecting the products in the productcs_pages table
$productsWithPages = /* query to get them*/
//getting an array of IDs
$productsWidthPagesIds = Hash::extract($productsWithPages, '{n}.Product.id');
//doing the NOT IN to select products without pages
$productsWithoutPages= $this->Product->find('all',
array('conditions' =>
array( 'NOT' => array('Product.id' => $productsWidthPagesIds )
)
);
i'm thinking about this for days now and don't come to grasps (since i'm relativley new to MVC and CI). I'm not even sure whether this is an issue with MVC, MySQL or arrays.
Situation: 2 MySQL tables
Table data: id, title, list
Table values: id, name
Querying the data table results in an array like the following (excerpt):
[4] => Array
(
[id] => 3
[title] => Foo
[list] => 1,2,3,4,6,14
)
[5] => Array
(
[id] => 4
[title] => Bar
[list] => 2,6,9,12
)
The field list contains comma separated values that correspond to some IDs of the values table like
[3] => Array
(
[id] => 12
[name] => 'value12'
)
What I try to do for each row is:
take the list-values & explode it into an array
check with the result set from the values-table (via in_array() method)
return the name values of the IDs if
include it somehow into the main result set (e.g. as a 2-dimensional array):
[5] => Array (
[id] => 4
[title] => Bar
[list] => Array (
[0] => value6
[1] => value12
...
)
)
My naive approach so far was to
run a query on each of the 2 tables
compare the 2 result sets via in_array
My main problem (while trying to strictly separate model, controller and view): How can I include the name field from the values-table in the "main loop" of the data table result set?
if($q->num_rows() > 0)
{
$data[] = $q->result_array();
foreach ($q->result() as $row)
{
$data[] = $row;
}
return $data;
}
If I use the following (cumbersome) approach i naturally get a new item each time:
foreach ($q->result_array() as $row)
{
$data[]['id'] = $row['id'];
$data[]['title'] = $row['title'];
$data[]['list'] = $row['year'];
}
Since this is a MySQL database I see no way to do the explode and the comparison in SQL (with LIKE or something else).
Any hint, even a simple link to an info bit, is highly appreciated.
Thanks a trillion!
fab
There is a many-to-many relationship between lists and list values. The conventional way to model this in a relational database is to create a joining table. So I'd structure your schema like this.
lists : list_id, title
values : value_id, name
list_values : list_id, value_id
list_values is the joining table. It links lists with values.
To build a list you could have the following functions in your model
function build_list($list_id)
{
$list = $this->get_list($list_id);
$list->values = $this->get_list_values($list_id);
return $list;
}
function get_list($list_id)
{
$sql = 'select * from lists where list_id=?';
return $this->db->query($sql, array($list_id))->row();
}
function get_list_values($list_id)
{
$sql = 'select v.value_id, v.name
from list_values lv
join values v on v.value_id=lv.value_id
where lv.list_id=?';
return $this->db->query($sql, array($list_id))->result();
}
I've made some search on the forum without any good answers for my problem. If I missed something, feel free to link me to the question!
What I need to do is simple: a function that returns an array of the full tree of my categories and items. I only have 1 depth (item and a cat_id), so no recursion involved (though if you have a recursive solution, I would gladly accept it).
Right now, I've done this, but it's pretty bad, since I do multiple queries...
function build_tree()
{
global $wpdb;
$cats = $wpdb->get_results("SELECT * FROM wp_catering_cats");
foreach($cats as &$cat)
{
$id = $cat->id;
$cat->items = $wpdb->get_results("SELECT * FROM wp_catering_items WHERE cat_id = $id");
}
return $cats;
}
My tables are really simple:
wp_catering_items
id, cat_id, name, price
wp_catering_cats
id, name
Here is an exemple the results array I want:
Array
(
[0] => array
(
[id] => 1
[name] => Cat #1
[items] => Array
(
[0] => array
(
[id] => 1
[cat_id] => 1
[name] => Item #1
[price] => 5
),
...
)
),
...
);
If something is not clear, feel free to comment!
Thanks!
EDIT
I've made some modifications using the code bellow, but I' pretty sure there's a neater way to do this. Having to order one DESC and one ASC just doesn't sounds right..
function build_tree()
{
global $wpdb;
$cats = $wpdb->get_results("SELECT * FROM wp_catering_cats ORDER BY id DESC");
$items = $wpdb->get_results("SELECT * FROM wp_catering_items ORDER BY cat_id ASC");
$item = array_pop($items);
foreach($cats as &$cat)
{
while($item->cat_id == $cat->id)
{
$cat->items[] = $item;
$item = array_pop($items);
}
}
print_r($cats);
}
If you are just trying to optimize, then do the simple thing, instead of only grabbing the items for the specific cat you are on, grab all the items at once, and order them by catID. Then loop through your cats, and pop items off your item results until you hit the next cat.
function build_tree()
{
global $wpdb;
$cats = $wpdb->get_results("SELECT * FROM wp_catering_cats order by cat_id asc");
$items = $wpdb->get_results("SELECT * FROM wp_catering_items ORDER BY cat_id asc");
foreach($cats as &$cat)
{
$id = $cat->id;
$item = array_pop($items)
while($item['cat_id'] == $id)
{
$cats->item[] = $item;
$item = array_pop($items)
}
#do a little bookkeeping so you next cat gets its first item, and zero item cats get skipped.
}
}
Update: Thanks for the comment.. Forgot to add the pop in the while loop!
Second update: use array_shift instead of array_pop if you don't want reverse ordering to be a problem...