Blueimp SELECT only specific rows - php

this is what I'm struggingling with: https://github.com/blueimp/jQuery-File-Upload
I came across this topic which is simarlar to my problem:
I have some products where you should be able to associate more than one image.
I have 3 tables
products ------------------ img_connecter ------------------- images
p_id p_name fk_p_id fk_i_id i_id i_name
1 Car 1 1 1 car_1.jpg
2 Bus 1 2 2 car_2.jpg
3 Truck 2 3 3 bus_1.jpg
.
This is the code from the UploaderHandler.php file:
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
return array();
}
return array_values(array_filter(array_map(
array($this, $iteration_method),
scandir($upload_dir)
)));
}
The scandir function is showing all the images in the folder so i was trying to change it to:
protected function get_file_objects() {
$files = $this->query(" SELECT i_name FROM images i
LEFT JOIN img_connector c ON (c.fk_i_id = i.i_id)
LEFT JOIN products p ON (c.fk_p_id = p.p_id)
WHERE p_id = 1");
$files_array=array();
while($row = $files->fetch()){
array_push($files_array, $row['i_name']);
}
return array_values( array_filter( array_map(
array($this, 'get_file_object'),
$files_array
) ) );
}
The query where it says "WHERE p_id = 1"
1 is going to be a $_GET[] variable. For now I'm just giving it a static number.
I cant figure out why it dosent show the images that the query is pointing too ??
Am I missing something ?

You are only selecting columns id and name (which don't seem to be mentioned in your DB schema above) but then you're referring to a row called i_name in your result set. The query you're looking for is this one:
$files = $this->query("SELECT i_name FROM images i
LEFT JOIN img_connector c ON (c.fk_i_id = i.i_id)
LEFT JOIN products p ON (c.fk_p_id = p.p_id)
WHERE p_id = 1
");
So, next you're (very verbosely) sticking them into an array. Assuming you took my advice and went with PDO for database access, doesn't hurt to grab all the filenames at once:
$files_array = $files->fetchAll(PDO::FETCH_COLUMN);
Then you're passing every instance of the array through $this->get_file_object(), removing any empty ones, and returning the remaining values.
return array_values(
array_filter(
array_map([$this, 'get_file_object'], $files_array)
)
);
So the only thing left to check is what get_file_object is doing. The only instance under which it will return false is if the file doesn't exist in the upload directory. So, ensure the file is where it should be.
All this presupposes that you actually have a valid database connection; doing a var_dump($files_array) should tell you that pretty quickly.

Related

How to group my results and have all rows shown?

SELECT i.itemsname
, i.itemsprice
, i.itemsdescrip
, c.catname
, c.catdes
, c.status
, c.collapse
, c.catid
FROM items i
LEFT
JOIN categories c
ON c.catid = i.catid
WHERE i.restid
AND c.restid =12
GROUP
BY c.catid
that is my query at the moment but I would like to have something like this....
but this is what I'm getting:
Ok, I lied in the comments, so With PDO (haven't tested it)
$stmt = $PDO->prepare('SELECT
categories.catname,
items.itemsname,
items.itemsprice,
items.itemsdescrip,
categories.catdes,
categories.status,
categories.collapse,
categories.catid
FROM items
LEFT JOIN categories ON items.catid=categories.catid
WHERE items.restid AND categories.restid = :restid');
$stmt->execute([':restid' => 12]);
$data = $stmt->fetchAll(\PDO::FETCH_GROUP);
foreach($data as $catname => $rows){
//echo group html stuff
//echo "<dl>";
//echo "<dt>$catname</dt>".;
foreach($rows as $row){
//echo row data stuff
// echo "<dd> {stuff} </dd>";
}
//echo "</dl>";
}
I'll leave the html up to you. But as I said you want a data structure like this
[
'BREAKFASTS' => [
0 => [ name => "wimpy hamburger", description => "bla bla", price => "$100,000"],
1 => [ ... ]
],
'SINGLE BURGERS' => [ ...]
]
note that the first field after "SELECT" is by default the field used by FETCH_GROUP
See in this way, the first foreach can output the title of the category, which is BREAKFASTS for example. Then the inner foreach can do the individual rows in the table.
Personally I would use a dl, dt, dd tag setup as my structure (hinted in the comments, i really am to lazy today to code all the html, <sigh>)
https://www.w3schools.com/tags/tag_dt.asp
UPDATE
You may want to check your query
...
WHERE
items.restid AND ...
Seems to be flawed, just saying. I saw this while optomizing the query for sorting.
SELECT
c.catname,
i.itemsname,
i.itemsprice,
i.itemsdescrip,
c.catdes,
c.status,
c.collapse,
c.catid
FROM
(
SELECT c0.catid FROM categories AS c0 WHERE c0.restid = :restid SORT BY c0.catname
) AS t
JOIN
categories AS c ON t.catid=c.catid
LEFT JOIN
items AS i ON items.catid=categories.catid
WHERE
items.restid = ? //< this is the error/omission/strangeness i pointed out above.
So a few things to note, first you should base the query off the categories, as an empty category should be shown, while an item without a category will blow it all to bits ( basically, ie how can you group them by the category if they have none ) You'll wind up with some hodgepoge of items with no category at the end, of course based on your example I'm assuming a Many to One relationship. For example One category can have Many items, and Many items can belong to a category. (it's probably more ideal to do a Many to Many, but that's another story for another day)
The reason the above query is more optimized is the inner query, creates only a small temp table using the catid, And sorts on just the data from the cat table and only the data that is pulled by the where.
Then as we move to the outer query, they basically inherent the sort from the join, and we can pull the rest of the data from that. It's typically about 2-10x faster this way (of course I haven't test this particular query) in theory. Of course this is a bit more complex/advanced query and is optional, but it should improve sort performance if my mind is in the right place tonight... lol
Also I abbreviated your table names (alias), as I said I am lazy like that. Sadly my answers are always so long, dont ask me how I see all these issues, it's just experience or how my dyslexic brain works?
Lastly, if you really must use mysqli, you can manually group them with something like this.
$data = [];
while(false !== ($row = $res->fetch_assoc())){
$key = $row['catname'];
if(!isset($data[$key])) $data[$key] = [];
$data[$key][] = $row;
}
It's all so prosaic (common place, non-poetic) at this point for me.
Good luck.
$cat = mysqli_query($connect, "SELECT
categories.catname,
items.itemsname,
items.itemsprice,
items.itemsdescrip,
categories.catdes,
categories.catid
FROM items
LEFT JOIN categories ON items.catid=categories.catid
WHERE items.restid AND categories.restid = 12");
if($cat === FALSE) {
die(mysqli_error());
}
$data = [];
while ($rowb = mysqli_fetch_array($cat)) {
$key = $rowb['catname'];
if(!isset($data[$key])) $data[$key] = [];
$data[$key][] = $rowb;
foreach($data as $catname => $rowbs){
echo "
<dl><button class='accordiontry'><dt>$catname</dt></button>";
<div class='panel1'>
foreach($rowbs as $rowb){
echo"<div class='rmenu'>
<dd><span class='item'>{$rowb['itemsname']}</span>
<span class='price'>£{$rowb['itemsprice']}</span><br>
<span class='des'>{$rowb['itemsdescrip']}</span> ";
}
echo"</div></dd>
</div></dl>";
}
}
}

SQL query to get value from referenced table

I have two tables called mg_product and mg_product_user_property.
In mg_product there are 3 columns: id, title, price as
In mg_product_user_property table product_id corresponds with id column in mg_product table.
So my goal is to get the value of property_id of "15", which in the picture above will be "Mediatek".
This is my SQL:
$sql = "SELECT *
FROM mg_product AS products
INNER JOIN mg_product_user_property AS properties
ON products.id = properties.product_id
WHERE title LIKE '%$search%')";`
PHP:
$resultSet = DB::query($sql);
if ($resultSet->num_rows > 0) {
while ($rows = $resultSet->fetch_assoc()) {
$title = $rows['title'];
$price = $rows['price'];
}
} else {
$output = "No results";
}
Now I need to assign to a php variable the value of property_id=15 so I will be able to print "Mediatek" on my website. How can I achieve that? Sorry for my English.
You are pretty close to what you want, but a couple things are going to either be a mess, or unwanted. So, since there are different ways one can go with this, I will only present a very stripped example (and am INTENTIONALLY leaving out a bunch of code here).
You may not want to do a JOIN like that in the initial search, as for each property, it will also return another of the same product. So looping through that will result in dozens of the same product.
However, if _ALL_YOU_WANT_ is to show the Product Title, Price, and Property 15... you can reduce some headwork with a simpler query:
SELECT p.title, p.price, pr.value
FROM mg_product AS p
LEFT JOIN mg_product_user_property AS pr
ON p.id = pr.product_id AND pr.property_id = 15
WHERE p.title LIKE '%$search%'
The LEFT JOIN means if the property doesn't exist, it will still return the product. But with an empty property value. And this should not return dozens of the same product for every other property in the table.
--
The OTHER way you could go about doing it, using the SQL query you already have (and the dozens of results of the same product it will return), you can alter your php loop like so:
$found_products = array();
while ($row = $resultSet->fetch_assoc()) {
if ($row['property_id'] == 15) {
$found_products[$row['product_id']] = array(
'title' => $row['title'],
'price' => $row['price'],
'prop' => $row['value']
);
}
}
// now you have a clean array of found products that have the property
--
Also I am forced to point out that you should use a prepared statement here, replacing inserting $search directly into the code. But showing you all of how to do that is beyond the scope of this question/answer.

How to separate the rows depending of the column's value witin two tables in CodeIgniter?

I have two tables: markers and markers_types.
markers
id, type_id, lat, lng
1 1 42.000 2.500
2 1 41.000 2.400
3 2 40.000 2.300
markers_types
id, name, image
1 TYPE1 type1.png
2 TYPE2 type2.png
How can I retrieve the rows from the DB correctly, so for example, if first row from markers have column type_id set to 1, I want to output an image from corresponding ID from the others table markers_types where markers.type_id is equal to markers_types.id ? Sorry for dumb question, but can't get it.
Here is my map_model.php:
class Map_model extends CI_Model{
...
function get_coordinates(){
$this->db->select('*');
$this->db->from('markers');
$query = $this->db->get();
if($query->result() < 1)
return false;
else{
$results = $query->result();
return $results;
}
}
}
And here is my app/controllers/map.php:
$dbresults = $this->map_model->get_coordinates();
foreach($dbresults as $item){
$marker = array();
$marker['position'] = $item->lat.','.$item->lng;
$marker['icon'] = base_url().'assets/img/ico/'.$item->image; // <-- I need to output here correct type image
$marker['infowindow_content'] = $item->description;
$this->googlemaps->add_marker($marker);
}
How can I mix them, so it will output appropriate image depending on the marker's type ?
I'am complete newbie at MySQL, so pls sorry in advance for that kind of basic question, I tried but didn't succeed to find out the right answer.
$query = $this->db->query("SELECT * FROM markers LEFT JOIN marker_types ON markers.type_id = markers_types.id");
// RETURNS AN ARRAY
$query->result_array();

MySQL join results different in PHP?

I have a query:
SELECT * FROM categorys
LEFT JOIN category_info ON categorys.cat_id=category_info.cat_id
WHERE `cat_name` = 'aname'
ORDER BY `cat_order`
When I run this in phpMyAdmin I get an cat_id back regardless of if there is a match in the second table.
However, when I run this query in my PHP code I get a blank cat_id back, as shown by this print_r():
Array ( [cat_id] => [cat_name] => baths [type] => main [cat_order] =>
99 [cat_img] => [display] => 1 [deleted] => 0 [desc_id] => [desc] =>
[text] => )
Why would there be a different result when the query is exactly the same?
EDIT:
My PHP code:
$getcatidsql = "SELECT * FROM categorys
LEFT JOIN category_info ON categorys.cat_id=category_info.cat_id
WHERE `cat_name` = '{$cname}'
ORDER BY `cat_order";
$getcatidresult = $db->query( $getcatidsql );
$catdata = $db->fetchRow( $getcatidresult );
function query() {
$this->query_total++;
if (func_num_args() == 1) {
$sql = func_get_arg(0);
} else {
$args = func_get_args();
for ($i=1;$i<count($args);$i++) if (!is_numeric($args[$i])) $args[$i] = '"'.mysql_real_escape_string($args[$i]).'"';
$sql = vsprintf(array_shift($args),$args);
}
if ($result = mysql_query($sql,$this->db_connection)) {
return $result;
} else {
$this->dberror( $this->db_connection, $sql );
}
}
function fetchRow($result,$type=MYSQL_ASSOC)
{
if($result)
$row = mysql_fetch_array($result,$type);
return $row;
}
I think you must not use select * (also because of same column names in both tables) , but select exactly fields for your needs
select table_name.field, table_name.field2, other_table_name.field1
.. and you'll get right results from both php code and phpmyadmin
I think it is because 'cat_id' is the same field name in both tables => the same index in result array.
Try to modify query like : " Select categorys.cat_id AS category from categorys ..... "
You're SELECTing * from categorys and category_info. They both have a cat_id column. So you'll get two cat_id columns back.
The question is: what does the SQL library/driver you're using do when it encounters two columns with the same name in your SELECT list?
Looks like it's probably overwriting the first one it comes across with the second one... What happens if you use an explicit SELECT list, specifying categorys.cat_id and not bringing in category_info.cat_id?
When you state
When I run this in phpMyAdmin I get an cat_id back
Do you mean that you get a VALUE for cat_id or do you get it as NULL? Because that is what you get with php, a NULL value for cat_id (as you see in print_r it still appears there).
If you don't want to get lines from categorys where there is no existing line in category_info for that category, then you have to use RIGHT JOIN instead of LEFT JOIN.

How do I retrieve items belonging to sub categories by selecting a top level category?

Please see the data tables and query below ..
Items
Id, Name
1, Item 1
2, Item 2
Categories
Id, Name, Parent ID
1, Furniture , 0
2, Tables, 1
3, Beds, 1
4, Dining Table, 2
5, Bar Table, 2
4, Electronics, 0
5, Home, 4
6, Outdoors, 4
7, Table lamp, 4
ItemCategory
ItemId, CategoryId
1, 2 .. Row1
2, 4 .. Row 2
2, 5 .. Row 3
ItemCategory table stores which items belongs to which category. An item can belong to top level and or sub category. there are about 3 level deep categories, that is, Tob level, sub level, and sub sub level.
Users select all of the categories they want to view and submit and I can query the database by using a sample query below..
SELECT * FROM items i INNER JOIN ItemCategory ic ON
ic.itemId = i.itemId AND ic.itemId IN ('comma separated category ids')
This works fine.
My question is that Is it possible to view all the items under a top level category even though it has not been directly assigned to the item. For example, if users select Furniture above, then it lists all the items belonging to its sub categories (even though the ItemCategory doesn't contain any record for it)??
I'm open to making necessary amendements to the data table or queries, please suggest a solution. Thank you.
Watcher has given a good answer, but I'd alter my approach somewhat to the following, so you have a structured recursive 2-dimensional array with categories as keys and items as values. This makes it very easy to print back to the user when responding to their search requirements.
Here is my approach, which I have tested:
$items = getItemsByCategory($topCategory);
//To print contents
print_r($items);
function getItemsByCategory($sid = 0) {
$list = array();
$sql = "SELECT Id, Name FROM Categories WHERE ParentId = $sid";
$rs = mysql_query($sql);
while ($obj = mysql_fetch_object($rs)) {
//echo $obj->id .", ".$parent." >> ".$obj->name."<br/>";
$list[$obj->name] = getItems($obj->id);
if (hasChildren($obj->id)) {
array_push($list[$obj->name],getItemsByCategory($obj->id));
}
}
return $list;
}
function getItems($cid) {
$list = array();
$sql = "SELECT i.Id, i.Name FROM Items p INNER JOIN ItemCategory ic ON i.id = ic.ItemId WHERE ic.CategoryId = $cid";
$rs = mysql_query($sql);
while ($obj = mysql_fetch_object($rs)) {
$list[] = array($obj->id, $obj->name);
}
return $list;
}
function hasChildren($pid) {
$sql = "SELECT * FROM Categories WHERE ParentId = $pid";
$rs = mysql_query($sql);
if (mysql_num_rows($rs) > 0) {
return true;
} else {
return false;
}
}
Hope this helps.
With recursion, anything is possible:
function fetchItemsByCat($cat, &$results) {
$itemsInCat = query("SELECT Items.Id FROM Items INNER JOIN ItemCategory ON ItemCategory.ItemId = Items.Id WHERE CategoryId = ?", array($cat));
while($row = *_fetch_array($itemsInCat))
array_push($results, $row['Id']);
$subCategories = query("SELECT Id FROM Categories WHERE Parent = ?", array( $cat ));
while($row = *_fetch_array($subCategories))
$results = fetchItemsByCat($row['Id'], $results);
return $results;
}
$startCat = 1; // Furniture
$itemsInCat = fetchItemsByCat($startCat, array());
The function is somewhat pseudo-code. Replace *_fetch_array with whatever Database extension you are using. The query function is however you are querying your database.
Also, this is untested, so you should test for unexpected results due to using an array reference, although I think it's good to go.
After calling the function, $itemsInCat will be an array of integer ids of all of the items/subitems that exist in the given start category. If you wanted to get fancy, you can instead return an array of arrays with each 2nd level array element having an item id as well as that item's assigned category id, item name, etc.
If you use MySQL, you're out of luck short of indexing your tree using typical techniques, which usually means pre-calculating and storing the paths, or using nested sets:
http://en.wikipedia.org/wiki/Nested_set_model
If you can switch to PostgreSQL, you can alternatively use a recursive query:
http://www.postgresql.org/docs/9.0/static/queries-with.html
Evidently, you can also recursively query from your app, but it's a lot less efficient.

Categories