I'm trying to build a simple select list in Joomla 2.5 with php and mysql, but I've got a problem: it doesen't load the options name... are there any error?
<?php
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('optValue');
$query->from('#__sobipro_field_option');
$query->where("fid='38'");
$db->setQuery((string)$query);
$results = $db->loadObjectList();
if ($results){
echo "<select>";
foreach($results as $result){
foreach($result as $value) {
$query->select('sValue');
$query->from('#__sobipro_language');
$query->where("fid='38' and language='it-IT' and sKey='".$value."'");
$db->setQuery((string)$query);
$name = $db->loadResult();
echo "<option value=\"$value\">".$name."</option>";
}
}
echo "</select>";
}
else {
echo 'Error';
}
?>
Whenever you're trying to debug Joomla! code turn on debug mode (Global Configuration->System->Debug Settings) and turn Error Reporting up to Development (Global Configuration->Server->Error Reporting), then you would have seen your problem straight away.
$query is a actually an object of type JDatabaseQuery and should be used as is in the $db->setQuery($query) call without casting to a (string).
When referencing a database, table or column name it's a good idea to use Joomla's mechanism for wrapping the name is the correct quotes e.g.
$query-select($db->quoteName('optValue'))
Amongst other things this will insure that SQL keywords aren't a problem.
Likewise for values, use the Joomla! provided $db->quote() method. e.g.
$query->where($db->quoteName('fid') . '=' . $db->quote('38'));
When building a WHERE query with multiple values ANDed together you can simply add each item as it's own ->where() clause.
So your where before I would tend to write as:
$query->where($db->quoteName('fid') . '=' . $db->quote('38'));
$query->where($db->quoteName('language') . '=' . $db->quote('it-IT'));
$query->where($db->quoteName('sKey') . '=' . $db->quote($value));
Finally, as you've said both of your $queries work by themselves, but when put together in your code as shown they don't.
The reason for this is that after you configure $query for your first statement (and run it), you continue to add to the second statement to the original $query object. So, that when you do the second, third etc setQuery($query) the SQL is getting longer and longer and unlikely to return any results.
As you don't test for success of each $db->loadResult() in the inner-most foreach loop you never see the error.
At the very least you need to add a new $db->getQuery(true) at the beginning of your inner loop, like this:
<?php
// Get default database object
$db = JFactory::getDBO();
// Get a new JDatabaseQuery object
$query = $db->getQuery(true);
// Build the query
$query->select($db->quoteName('optValue'));
$query->from($db->quoteName('#__sobipro_field_option'));
$query->where($db->quoteName('fid') .'=' . $db->quote('38'));
// Set the query for the DB oject to execute
$db->setQuery($query);
// Get the DB object to load the results as a list of objects
$results = $db->loadObjectList();
if ($results){
echo "<select>";
foreach($results as $result)
{
foreach($result as $value)
{
// Get a new query object
$query = $db->getQuery(true);
// Build the query
$query->select($db->quoteName('sValue'));
$query->from($db->quoteName('#__sobipro_language'));
$query->where($db->quoteName('fid') .'=' . $db->quote('38'));
$query->where($db->quoteName('language') .'=' . $db->quote('it-IT'));
$query->where($db->quoteName('sKey') .'=' . $db->quote($value));
$db->setQuery($query);
$name = $db->loadResult();
echo "<option value=\"$value\">$name</option>";
}
}
echo "</select>";
}
else
{
echo 'Error';
}
This is going to potentially create a lot of objects, so, you should consider if there's a way to restructure it all into one SQL query this will make it significantly faster and reduce the load on your server.
Related
If I were to echo the result of this query:
//Find membertype from community builder
$db->setQuery('Select cb_membertype From #__comprofiler Where id='.$user->id);
$membertype = $db->loadResult(); //load the result from the query
I would use:
echo "Your member type is: $membertype";
I'd rather not use a new query for every variable thought since they are all in the same table.
I'd rather run a single query like this:
//Find all 3 from one query
$db->setQuery('Select cb_membertype, cb_2015vopac, cb_2015llf
From #__comprofiler Where id='.$user->id);
$result = $db->loadResult(); //load the result from the query
How do I echo the specific fields from that query when using the single $result variable?
First, let me just say that should should quote your values/columns/table names.
Secondly, if you want to get multiple values, you need to use loadObjectList instead of loadResult.
The following will do it for you:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('cb_membertype', 'cb_2015vopac', 'cb_2015llf')))
->from($db->quoteName('#__comprofiler'))
->where($db->quoteName('id') . ' = '. $db->quote($user->id));
$db->setQuery($query);
$results = $db->loadObjectList();
foreach ($results as $result)
{
echo $result->cb_membertype;
echo $result->cb_2015vopac;
echo $result->cb_2015llf;
}
So loadObjectList give you an object, then you can loop though it using foreach loop.
Hope this helps
I have a project here that has a LOT of this kind of code below.
It is everything in mysql and I want to change do mysqli or PDO.
The problem is that the code make the fields of the table be variables, inside the loop. So, If I need to change to something different, I will have to re-write thousand of lines of code. Because inside the loops below I will change every call of the var. Example: $row["product_name"] instead of $product_name
This is the code:
$query = "SELECT product_name, product_price from products";
$result = mysql_query($query_sql);
while($row = mysql_fetch_array($result)) {
$j = mysql_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysql_field_name($query,$i);
$$k = $row[$k];
}
//Here, inside the loop, I use $product_name instead of $row["product_name"]
}
It there a way to change the code to do the same with mysqli or PDO? I want to keep using $field_name instead of $row["field_name"].
mysqli object method shown. I don't recommend doing it this way, but it can be done. I would highly suggest you learn how to deal with either a result object or array directly. Dynamically setting variables like this will introduce a lot of unnecessary overhead.
$result = $mysqli->query($query_sql);
while($row = $mysqli->fetch_assoc($result)) {
extract($row);
//Here, inside the loop, I use $product_name instead of $row["product_name"]
}
Here is what you are looking for: http://www.doctrine-project.org/
I specifically do not like this specific project, because it tends to be slow with larger amounts of data, but provides what you need:
You specify domain classes (understand map database lines to php objects) and you only have to specify the exact name of the table column, if it does not match up with the class variable name.
So you set every column once for every object type and you use that definition throughout you code, you are making a request for the object, that has a mapping to the database.
so it goes like: $entitiy_manager->getReference('myobject', $objectid = 1 );
Creating a new object is just adding a new instance of the class.
If I understood you properly this should be you are looking for.
Thank you for every answer and opinion, but I just found the solution for my question.
I will leave here, for future reference.
This code is in mysql:
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
$j = mysql_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysql_field_name($query,$i);
$$k = $row[$k];
}
}
And this would be the same in mysqli:
$result = mysqli_query($link, $query);
while($row = $query->fetch_assoc())
{
$j = mysqli_num_fields($query);
for($i=0;$i<$j;$i++) {
$k = mysqli_fetch_field_direct($query, $i)->name;
$$k = $row[$k];
}
}
I have in using joomla, have a input field and must add on result page of com_search a additional query, if i run this query in a sql editor i get 2 results, but in joomla is my foreach every time skipping.
If i do $db->getPrefix(); i see table prefix, so i thing to $db and $query are true.
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*');
$query->from('#__k2_categories');
$query->where("`name` LIKE '%MY_SEARCH_WORD%'");
$db->setQuery($query);
$results = $db->loadObjectList();
foreach($results as $entry) :
echo $results->name . "<br />";
endforeach;
I want to run a query using PDO, based on data in the URL paramater (yes, I know that this is prone to attacks, but its internal code for a utility).
$user = 'USER';
$pass = 'PASSWORD';
$dsn = 'mysql:dbname=PRODUCTS;host=HOST';
try {
$productDB = new PDO($dsn, $user, $pass);
$productDB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
$msg = 'PDO ERROR' . $e->getFile() . ' L.' . $e->getLine() . ' : ' . $e->getMessage();
die($msg);
}
if(isset($_GET['cat']))
{
$cat = $_GET['cat'];
print "cat = $cat <br>";
$products = $productDB->prepare('SELECT * FROM products WHERE cat_id LIKE ?');
$products->execute(array($cat));
$rows = $products->rowCount();
print "$rows rows returned";
?>
<table border="1">
<tr>
<td>product_id</td>
<td>product_name</td>
</tr>
<?php
foreach ($products->fetchAll() as $row) {
$id = $row['product_id'];
$product_name = $row['product_name'];
print "<tr>";
print "<th scope=\"row\"><b>$id</b></th>";
print "<td> $product_name </td>";
print "<tr>";
}
print "</table>";
}
?>
When I run this code, it prints the correct number of rows depending on the query, but does not populate the table.
I have also tried replacing the prepare and execute lines with:
$products = $productDB->query("SELECT * FROM products WHERE cat_id LIKE $cat");
Which returns the correct row count, but doesn't otherwise help.
And finally, I've tried replacing the foreach line with something like:
$rows = $products->fetchAll();
foreach ($rows as $row) {
My attempts to do the same with a fixed query all work fine, but I am having trouble working out how to place a variable element in a query, and then iterate over the results.
You're not doing anything to store the result:
$products->execute(array($cat));
needs to go in a variable:
$result = $products->execute(array($cat));
Then, instead of calling $products->fetchAll(), use $results->fetchAll():
foreach ($result->fetchAll() as $row)
I find it easier to use a $query variable (for prepare, etc) and then get the result into something like $result or $product. Makes the code a bit easier to read.
Try this (If I understood correctly) :
$products = $productDB->prepare("SELECT * FROM products WHERE cat_id LIKE :cat");
// Now, you can either do this :
$products->bindParam('cat', '%'.$cat.'%');
$products->execute();
// or you can call execute with an associative array of your parameterized query.
$products->execute(array('cat' => '%'.$cat.'%'));
// Then, get all the results like this :
$rows = $products->fetchAll();
foreach ($rows as $row) {
// Do work here ..
}
// Or, like this :
while ($row = $products->fetch(PDO::FETCH_ASSOC)) {
// Do work here ..
}
I personaly prefer the while, because you don't fetch the whole query in one var, reducing the amount of memory needed.
I also recommend you to use the FETCH_* parameter, to get only the kind of array you want.
By the way, you need to know that rowCount should not be used to count the rows returned by a SELECT. As said by php.net :
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.
I'm currently updating my app by switching to PDO. I have the following code:
$stmt = $db->prepare("select * from `product` where productid in (:productidLst)");
$stmt->bindParam(":productidLst",$productidLst, PDO::PARAM_INT);
$stmt->execute();
The var $productidLst is 1,2 after the above code I would like to use the PDO equivalent of this:
while($rs=mysql_fetch_assoc($res)){
$rs['qty']=$_SESSION['basket'][$rs['productid']];
$rs['total'] += $rs['qty']*$rs['price'];
$total += $rs['total'];
$a[] = $rs;
}
I have tried numerous combinations but not been successful so any help with this would be appreciated (in the 2nd code block $res was the sql). Secondly I have set the Parameter $productidLst to INT is this correct or should it be a string?
--------------------UPDATE 1----------------------------------------------------
I have tried the following code:
$stmt = $db->prepare("select * from `product` where productid in (:productidLst)");
foreach ($stmt->execute(array(':productidLst' => $productidLst)) as $row)
{
$total += $row['total'];
}
Which returns: Invalid argument supplied for foreach() error
The standard documentation in the PHP manual is usually pretty helpful. There is an example of executing a for loop with PDO in the PHP manual, PDO Details.
function getFruit($conn) {
$sql = 'SELECT name, color, calories FROM fruit ORDER BY name';
foreach ($conn->query($sql) as $row) {
print $row['name'] . "\t";
print $row['color'] . "\t";
print $row['calories'] . "\n";
}
}
With a few changes, the example can be made to use a prepared statement.
function getFruit($conn) {
$query = $conn->prepare('SELECT name, color, calories FROM fruit WHERE kind=:kind ORDER BY name');
$query->execute(array(':kind' => 'drupe'));
// alternatively you could use PDOStatement::fetchAll() and get rid of the loop
// this is dependent upon the design of your app
foreach ($query as $row) {
print $row['name'] . "\t";
print $row['color'] . "\t";
print $row['calories'] . "\n";
}
}
You can also use a while loop and PDOStatement::fetch to get each row.
function getFruit($conn) {
$query = $conn->prepare('SELECT name, color, calories FROM fruit WHERE kind=:kind ORDER BY name');
$query->execute(array(':kind' => 'drupe'));
// alternatively you could use PDOStatement::fetchAll() and get rid of the loop
// this is dependent upon the design of your app
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
print $row['name'] . "\t";
print $row['color'] . "\t";
print $row['calories'] . "\n";
}
}
The PHP manual remains quite helpful in providing all the necessary information to create the latter two versions.
Explanation of the last version: assuming $conn is a valid PDO object. $conn->prepare($sql) returns a PDOStatement object if successful, false on failure OR an exception based on your error handling. So, assuming success we would want to actually get the data from the object. We can use $query->fetch() in a loop or $query->fetchAll() to get the data dependent upon your app. Passing in the class constant PDO::FETCH_ASSOC will return, you guessed it, an associative array of data.
Functionally, the foreach and while implementations are equivalent. Conceptually, a foreach is more appropriate, as a while loop has connotations of looping while a static condition holds, whereas foreach loops over elements of a collection. Read "Differences between a while loop and a for loop in PHP?" for part of the story.
Be sure to read the php.net reference on PDO
You should be using PDOStatement::fetch() to fetch the row. It fetches (by default) both numerically and associatively. You can change that as well.
With your code:
while($rs=$stmt->fetch()){
$rs['qty']=$_SESSION['basket'][$rs['productid']];
$rs['total'] += $rs['qty']*$rs['price'];
$total += $rs['total'];
$a[] = $rs;
}
Manual Reference.