I hope someone can help with the following... I have multiple product names in a MYSQL database table on one hand and on the other hand I am getting some info such as pricing (excluding product name and some other static info) from xml feeds. The xml feed gives a product code, with which I can match the rows I need in the database because the database includes name of the product but also product code whilst xml doesn't include name of the product.
What I want to do is to fetch the name of the product and some other values from the database and link them with the other info from the xml, so that the end result is that I display the name of the products and the other info on the front-end. There are multiple products from multiple xml's...
If this was single product with a single code, I know I can use the SELECT statement with a where clause, wherein the WHERE clause is the product ID, but because I have multiple products with multiple ID's and I don't need to fetch everything from the database (but only those products displayed/searched for on the front-end), I am a bit stuck and don't know how to do this.
I hope this makes sense. If not, please do let me know.
Thanks in advance.
When you're processing the XML feed, put all the product codes into an array. Then you can construct the SQL query dynamically from this:
$codes_string = implode(', ', $product_codes);
$sql = "SELECT * FROM product_table WHERE product_id IN ($codes_string)";
I'm assuming product IDs are numeric IDs. If they're strings you'll need to put quotes around each of them:
$codes_string = implode("', '", $product_codes);
$sql = "SELECT * FROM product_table WHERE product_id IN ('$codes_string')";
You could likely use an IN query to get the products from the table. Then you'd have to merge them into an object or array of the rows you got via XML.
select * from `mydb`.`myproducts` where product_id in ('key1', 'key2', 'key3');
By your comments across the different answers, if you are looking to build your array of product codes, here's the most viable approach:
$productIds = array();
foreach ($myXmlRecords as $xmlProduct) {
array_push($productIds, $xmlProduct->product_id);
}
$query = 'select * from `mydb`.`myproducts` where product_id in (\'' . implode("', '", $productIds) . '\')';
Taking it a step farther, if you wanted to join the data of the two instead then I'd do the following:
$products = array();
$productIds = array();
foreach ($myXmlRecords as $xmlProduct) {
$p = new stdClass();
$p->product_id = $xmlProduct->product_id;
$p->xmlProp1 = $xmlProduct->prop1;
$p->xmlProp2 = $xmlProduct->prop2; // basically transfer any Xml properties you want to retain to the new $p object
array_push($products, $p);
array_push($productIds, $xmlProduct->product_id);
}
// Now build your query that will grab all matching products you got from Xml
$query = 'select * from `mydb`.`myproducts` where product_id in (\'' . implode("', '", $productIds) . '\')';
// Now match up the results
$results = mysql_query($query);
foreach ($results as $prodRow) {
foreach ($products as $p) {
if ($p->product_id == $prodRow->product_id) {
// These match, now add your db properties to the product
$p->dbProp1 = $prodRow->prop1;
$p->dbProp2 = $prodRow->prop2; // and so on
}
}
}
The end result is an array of products that have the Xml and Db info you want to combine. Before someone corrects me, there is probably a more efficient way than nested foreach statements such as updating the mysql query to use a join against the Xml data and then selecting from both that and your DB. But this is a fast approach that should get you where you need to.
Hope that helps!
Related
I have updated my original post based on what I learned from your comments below. It is a much simpler process than I originally thought.
require '../database.php';
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM Orders WHERE id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($id));
$data = $q->fetch(PDO::FETCH_ASSOC);
echo 'Order Num: ' . $data['id'] . '<br>';
$sql = "SELECT * FROM Order_items
JOIN Parts ON Parts.id = Order_Items.part_id
WHERE Order_Items.orders_id = 430";
$q = $pdo->prepare($sql);
$q->execute(array($line_item_id));
$data = $q->fetch(PDO::FETCH_ASSOC);
while ($data = $q->fetch(PDO::FETCH_ASSOC))
{
echo '- ' . $data['part_num'] . $data['qty'] . "<br>";
}
Database::disconnect();
Unfortunately, only my first query is producing results. The second query is producing the following ERROR LOG: "Base table or view not found: 1146 Table 'Order_items' doesn't exist" but I am expecting the following results.
Expected Results from Query 1:
Order Num: 430
Expected Results from Query 2:
- Screws 400
- Plates 35
- Clips 37
- Poles 7
- Zip ties 45
Now that I understand where you are coming from, let's explain a couple of things.
1.PDO and mysqli are two ways of accessing the database; they essentially do the same things, but the notation is different.
2.Arrays are variables with multiple "compartments". Most typical array has the compartments identified by a numerical index, like:
$array[0] = 'OR12345'; //order number
$array[1] = '2017-03-15'; //order date
$array[2] = 23; //id of a person/customer placing the order
etc. But this would require us to remember which number index means what. So in PHP there are associative arrays, which allow using text strings as indexes, and are used for fetching SQL query results.
3.The statement
$data = $q->fetch(PDO::FETCH_ASSOC)
or
$row = $result->fetch_assoc()
do exactly the same thing: put a record (row) from a query into an array, using field names as indexes. This way it's easy to use the data, because you can use field names (with a little bit around them) for displaying or manipulating the field values.
4.The
while ($row = $result->fetch_assoc())
does two things. It checks if there is a row still to fetch from the query results. and while there is one - it puts it into the array $row for you to use, and repeats (all the stuff between { and }).
So you fetch the row, display the results in whatever form you want, and then loop to fetch another row. If there are no more rows to fetch - the loop ends.
5.You should avoid using commas in the FROM clause in a query. This notation can be used only if the fields joining the tables are obvious (named the same), but it is bad practice anyway. The joins between tables should be specified explicitly. In the first query you want the header only, and there is no additional table needed in your example, so you should have just
SELECT *
FROM Orders
WHERE Orders.Order_ID = 12345
whereas in the second query I understand you have a table Parts, which contains descriptions of various parts that can be ordered? If so, then the second query should have:
SELECT *
FROM Order_items
JOIN Parts ON Parts.ID = Order_Items.Part_ID
WHEERE Order_Items.Order_ID = 12345
If in your Orders table you had a field for the ID of the supplier Supplier_ID, pointing to a Suppliers table, and an ID of the person placing the order Customer_ID, pointing to a Customers table, then the first query would look like this:
SELECT *
FROM Orders
JOIN Suppliers ON Suppliers.ID = Orders.Supplier_ID
JOIN Customers ON Customers.ID = Orders.Customer_ID
WHERE Orders.Order_ID = 12345
Hope this is enough for you to learn further on your own :).
In my app, the user can type in an indefinite amount of categories to search by. Once the user hits submit, I am using AJAX to call my PHP script to query my DB and return the results that match what the user defined for the categories.
My category column is separated as so for each row: "blue,red,yellow,green" etc.
I have two questions:
How can I pass an array to MySQL (like so: [blue,yellow,green]) and then search for each term in the categories column? If at-least one category is found, it should return that row.
Can MySQL add weight to a row that has more of the categories that the user typed in, therefor putting it further to the top of the returned results? If MySQL cannot do this, what would be the best way to do this with PHP?
Thanks for taking the time and looking at my issue.
For the part 1 you can use the function below:
<?php
function createquery($dataarray){
$query="select * from table where ";
$loop=1;
foreach($dataarray as $data)
{
$query.="col='$data'";
if(count($dataarray)<$loop-1){
$query.=' or ';
}
$loop++;
}
return $query;
}
?>
This will return the long query.
use this some like this:
mysql_query("select * from table where category in (".implode($yourarray,',').")");
1)
Arrays are not passed to a MySQL database. What's past is a query which is a string that tells the database what action you want to preform. An example would be: SELECT * FROM myTable WHERE id = 1.
Since you are trying to use the values inside your array to search in the database, you could preform a foreach loop to create a valid SQL command with all those columns in PHP, and then send that command / query to the database. For example:
$array = array('blue', 'red', 'yellow', 'green');
$sql = "SELECT ";
foreach ($array as $value)
{
$sql .= $value.", ";
}
$sql .= " FROM myTable WHERE id = 1";
IMPORTANT! It is highly recommended to used prepared statements and binding your parameters in order not to get hacked with sql injection!
2)
You are able to order the results you obtained in whichever way you like. An example of ordering your results would be as follows:
SELECT * FROM myTable WHERE SALARY > 2000 ORDER BY column1, column2 DESC
im trying to display a tracking number for a product on opencart.
so once the order has been placed. i then add a tracking number to it. from which i wish the customer to be able to see on the order history.
// get tracking details
$sql = 'SELECT * FROM '.DB_PREFIX.'order_history'.`tracking_number`;
$query = $this->db->query($sql);
$rates = array();
foreach($query->rows as $result){
$rates[] = $result;
}
$this->data['tracking'] = $tracking;
this would also go in order.php
this is what ive written but it dont work, im not expert at php, i dabble in it. hopefully someone can point me in the right direction,
so this code would go into controller/account/order.php
then on the template i assume i can just insert
<?php echo $tracking; ?> to display tracking deteails.
thanks in advance.
Off hand, I can see that this code will result in error, because your quotes/backticks are out of place:
$sql = 'SELECT * FROM '.DB_PREFIX.'order_history'.`tracking_number`;
Should be more along these lines:
$sql = "SELECT `tracking_number` FROM `".DB_PREFIX."order_history`";
And, assuming you're going to want to pull an order-specific tracking #:
$sql = "SELECT `tracking_number`
FROM `".DB_PREFIX."order_history`
WHERE `order_id` = 'MUFFINS'";
Do yourself a favor and use the double quotes when preparing a MySQL query. It's easier to wrap your stuff in single quotes without having to escape.
As for the remainder of the code, these are not rates but tracking numbers. Assumedly, there would be one tracking number to return per order, which you could wrap up into a single line of code like so:
$my_tracking_number = $this->db->query("
SELECT `tracking_number`
FROM `".DB_PREFIX."order_history`
WHERE `order_id` = 'MUFFINS'
")->row['tracking_number'];
if ( !empty($my_tracking_number) {
$this->data['tracking_number'] = $my_tracking_number;
}
However, if you're going to associate more than one tracking number with an order you can either insert a BLOB column in your order_history table and insert/query serialized data, or create a separate table entirely where multiple rows can be associated with a single order ID.
I am displaying images on my website with their details, however of late the site is very slow at loading.
The main thing is this foreach loop that loops through 100 times to display 100 posts in a grid. It takes 14 seconds to run
foreach($posts as $post) {
$hashtags[] = $this->HashTagsModel->get_hashtags($post["id"]);
$author[] = $this->UserModel->get_user_details($post["user_id"]);
$comment_count[] = $this->CommentModel->get_comments_count($post["id"]);
$is_favourited[] = $this->FavouriteModel->is_favourited($post["id"]);
$is_reposted[] = $this->RepostModel->is_reposted($post["id"]);
$vote_status[] = $this->vote_status($post["id"]);
$comments[] = $this->count_comments($post["id"]);
}
How can I do this differently to make it more efficient? This worked before our websites database became massive
Any help would be appreciated,
regards,
Almost Fired
The efficient way to foreach loop query database is to not foreach query database. This is because you are allowing an unknown amount of queries to be fired off which will cause massive queueing. What if suddenly 5000 images get added, do you loop through them all? That query will take a very long time.
You have $post["id"] as your where variable I am assuming, so you could reduce this process significantly by doing a single query after formulating an array of post ids, something like this:
$postids = array();
foreach($posts as $post) {
$postids[] = $post['id'];
}
// Selecting from 1 table
$query = 'SELECT * FROM hashtags WHERE id IN ('. implode(",", $postids) .')';
This would fetch all the information on hashtags where the id is is one of your postids. That is just 1 table, you would likely want to fetch multiple, without knowing your database structure I'm going to be generic, so something like:
// Selecting and joining data from multiple tables
$query = ' SELECT author.name, table.col FROM posts
LEFT JOIN author ON author.id = post.author_id
LEFT JOIN table ON table.id = post.table_id
WHERE posts.id IN IN ('. implode(",", $postids) .')';
It is a bit more difficult to be more accuracy. I think joining tables would provide you a better result, you can even join counts for votes/comments. If that is not possible, you could query all data related to your posts and then formulate it in PHP, then you know exactly how many queries you have. For example, change your models to accept an array instead of a single post ID and then change your "WHERE post_id = x" to "WHERE post_id IN (x)" then you can do something like:
$postids = array();
foreach($posts as $post) {
$postids[] = $post['id'];
}
$hashtags = $this->HashTagsModel->get_hashtags($postids);
$author = $this->UserModel->get_user_details($postids);
$comment_count = $this->CommentModel->get_comments_count($postids);
$is_favourited = $this->FavouriteModel->is_favourited($postids);
$is_reposted = $this->RepostModel->is_reposted($postids);
$vote_status = $this->vote_status($postids);
$comments = $this->count_comments($postids);
This gets your queries outside of the loop, and you know there will only ever be 7 SQL queries, and not queries * posts. In PHP you would loop through the results of each array to assign each one back to posts based on its ID.
I'm developing in php/sql a web application where users will be able to post items that they'd like to sell ( kinda like ebay ). I want non-members to be able to comment on the items or ask queries about items.
My problem is I want to display each item as well as any comment/query made about that item, in a similar manner as the way Facebook wall works.
I want to "append comments"(if any) to each item. The comments table is linked to the items table via column item_id. And the items table is linked to users table via column user_id. I have left joined users table with items table to display item details, i tried to left join comments table as well so that there are 3 joined tables.
That fails because no comments are displayed and only one item is displayed, despite there being multiple entries in each table. Here is the code i,m using.
$database->query
('
SELECT sale.*, query.*, users.id AS userid, users.username as user
FROM sale
LEFT JOIN users ON sale.user_id = users.id
LEFT JOIN query on sale.id = query.item_id
where category = "$category" ORDER BY sale.id DESC
');
$show = " "; //variable to hold items and comments
if ($database->count() == 0) {
// Show this message if there are no items
$show .= "<li class='noitems'>There are currently no items to display.</li>" ;
} else {
$show .= "<li>";
while ( $items = $database->statement->fetch(PDO::FETCH_ASSOC) )
{
$show .= "
//show item details in html
";
while( $query = $database->statement->fetch(PDO::FETCH_ASSOC) )
{
$show .= "
//show queries below item details
";
}
$show .= "</li>" ;
}
Welcome to Stackoverflow!
I recommend you taking a look at pdo. If you are already using mysql_ functions, then I recommend you switch. More on that can be found here.
Now that your pointed to the direction of to what functions to use when connecting/running queries, you now should create your tables. I use phpmyadmin for managing my database, I find it very good, but it's up to you what you use. Once you've decided on the service you use to manage your database, you should then learn how to use it by doing some google searches.
Now you need to set up your table and structure it correctly. If you say you're having items, then you should make a table called items. Next create the columns to the properties of the items. Also I recommend reading about Database Normalization, which is a key aspect of setting up your SQL tables Etc.
Once you have everything set up, you've connected to your database successfully Etc. You now need to set up the "Dynamic Page". What I mean by this is, there's only one page, say called 'dynamic', then a variable is passed to the url. These are called GET HTTP requests. Here's an example of what one would look like: http://example.com/item?id=345.
If you've noticed, you'll see the ? then the id variable defined to 345. You can GRAB this variable from the url by accessing the built in PHP array called $_GET[]. You can then type in your variable name you want to fetch into the []'s. Here's an example.
<?php
$data = $_GET['varname']; // get varname from the url
if(isnumeric($data)){ // is it totally made out of numbers?
$query = "SELECT fieldname FROM table WHERE id=:paramname";
$statement = $pdo->prepare($query); // prepare's the query
$statement->execute(array(
'paramname'=>$data // binds the parameter 'paramname' to the $data variable.
));
$result = $statement->fetch(PDO::FETCH_ASSOC); // grabs the result of the query
$result = $result['fieldname'];
echo 'varname was found in the database with the id equal to:'.$data.', and the result being: '.$result;
}
?>
So now you can see how you can grab the variable from the url and dynamically change the content with-in the page from that!
Hope this helped :)