I am moving a PHP page to my Joomla website and I was advised that I "should use Joomla's coding standards and methods for everything, this includes database queries"
My question is:
How should I transform my old PHP code regarding Joomla standards:
$query = "SELECT * FROM `TABLE 2` WHERE Power=".$input->get('Power', '', 'RAW')." AND Poles=".$input->get('Poles', '', 'RAW')."";
$results = mysql_query($query)
or die(mysql_error());
while ($row = mysql_fetch_array($results))
{
extract($row);
}
?>
This is the TABLE 2 contents. I use the values of each row as a variables on my page.
Most importantly make sure to filter the input to disallow sql injections. Seems both your inputs are numbers (Power is a float and Poles possibly an int?). Also use the #__ - in table names, it will be replaced by the table prefex when you use it in joomla functions. Simplest way to transform your code would be something like:
$app = JFactory::getApplication();
$power = $app->input->getFloat('Power'); // use the correct function
$poles = $app->input->getInt('Poles'); // for the datatype you want
see here for JInput docs
$db = $app->getDbo();
//short variant
$sql = "SELECT * from `#__table 2` WHERE power = "
. $db->quote($power) . " AND poles = " . $db->quote($poles);
$db->setQuery($sql);
$result = $db->loadRowList();
foreach($result as $array){
print_r($array);
}
It should be noted that there are more useful methods for retrieving the data, loadAssoc/loadAssocList for associative arrays, loadObject/loadObjectList for objects. Check the docs for JDatabaseDriver
Alternatively you could transform the query to a "Joomla query" like:
$q = $db->getQuery();
$q->select("*")->from($q->quoteName("#__Table 2"));
$q->where("Power = " . $db->quote($power));
$q->where("Poles = " . $db->quote($poles));
$db->setQuery($q);
...
Docs to JDatabaseQuery
Related
<?php
$userData = array();
while (anything to create a loop) {
$value1 = $result1_from_loop;
$value2 = $result2_from_loop;
$value3 = $result3_from_loop;
$userData[] = '("'.$value1.'", "'.$value2.'", "'.$value3.'")';
} // THIS ENDS THE WHLE OR FOR LOOP
$query = 'INSERT INTO users (data1,data2,data3) VALUES' . implode(',', $userData);
mysql_query($query);
?>
The above code works perfectly for inserting multiple records into table users as seen above and it's very fast as well.
However, I am trying to use the same method to update after going through a loop as before. I have no idea how to achieve this.
I want something like this:
<?php
$userData = array();
while (Loop statement) {
$value1 = $result1_from_loop;
$value2 = $result2_from_loop;
$value3 = $result3_from_loop;
$userData[] = '("'.$value1.'", "'.$value2.'", "'.$value3.'")';
} // This ends the WHLE or FOR loop
$query = 'UPDATE users SET(data1,data2,data3) VALUES' . implode(',',$userData) WHERE data2=$value2
mysql_query($query);
I know the above code is not close to correct, syntax is even wrong. I just pasted it to show the idea of what I want achieved. In the WHERE statement how will data2 get to know the value of each $value2?
UPDATE uses a different format to INSERT. For UPDATE, your code should look something like this:
$query = 'UPDATE users SET data1 = $userData[0], data2 = $userData[1], data3 = $userData[2] WHERE data2=$value2';
Although just as a note, using mysql_query is not advised as it is deprecated (and will be removed altogether in later PHP versions) and your code is vulnerable to SQL injection. At a minimum I'd recommend using mysqli_query instead and looking into using prepared statements.
i'm using K2 in Joomla 3.3.
I'm trying to set params (items ids ) to module k2_content from item.php file.
The result must to be between brackets, something like:
["96","68"]
My code is:
$query = "SELECT * FROM #__k2_items WHERE extra_fields_search = '$myautor' AND catid !=1 " ;
$db->setQuery($query);
$losautores = $db->loadObjectList();
$result = array();
foreach ($losautores as $key => $value) {
$result[] = '" '.$value->id.' "';
}
$string_version = implode(',', $result);
$autoresfinal = '['.$string_version.']';
If i test using print, looks ok.
But passing the var to pramas, i get 1064 error.
$params->set('items', $autoresfinal);
To test I tried
$autoresfinal = ["96","68"];
And works fine.
Any idea why doesn't work?
Thank you.
If you assign ["x","y"] you are assigning an array. Here you are transforming the array in a string.
Try simply
$result = [ ];
foreach ($db->loadObjectList() as $key => $value) {
$result[] = $value->id;
}
$params->set('items', $result);
Also, if you wanted to convert the array into a string (possibly JSON), a faster and safer way is to use json_encode (with the appropriate options).
UPDATE
The above remains true, but I had missed your complaint about error 1064. That is a SQL syntax error and it happens before you encode the results.
The reason - as noticed by Fred -ii- - is that in this query, #__k2_items needs escaping with backticks:
$query = "SELECT * FROM #__k2_items WHERE
extra_fields_search = '$myautor' AND catid !=1 " ;
should be:
$query = "SELECT * FROM `#__k2_items` WHERE
extra_fields_search = '$myautor' AND catid !=1 " ;
Also, you probably want to use prepared statements and parameterized queries (find an example here) instead of just plugging $myautor into a string. If you had an author called D'Artagnan, the query would become
....search = 'D'Artagnan' AND ...
which would again fail. Or if I called an author ' OR ''=', the query would become
...search = '' OR ''='' AND ...
which, since '' is always equal to '', would match for all the records in your table.
I have large tables in my database and instead of specifying each column name I am trying to build the query dynamically.
I am trying to do an update in the 'motherboard' table based on the POST data received. The $data object i receive has more fields than the table has. (I added some fields for some flags.)
Hence, I am retrieving the record I'm about to update and by comparing each of it's columns with my $data object fields I am constructing the UPDATE query.
I'm new to php, therefore I don't know the syntax well.
This is the code:
<?php
$data = json_decode($_POST["data"], true);
$id = $data["ID"];
include_once 'dbconnect.php';
$query = sprintf("SELECT * FROM `motherboard` WHERE ID = " . $id . ";");
$result = mysqli_query($con, $query);
$existingData = mysqli_fetch_assoc($result);
include_once 'dbclose.php';
$statement = "";
$statement = "UPDATE motherboard SET ";
$flag = false;
foreach ($existingData as $key => $value) {
if ($existingData->$key != $data->$key) {
$statement .= $key . " = " . $data->$key . " , ";
$flag = true;
}
}
if ($flag)
$statement = substr($statement, 0, strrchr($statement, ',') - 1);
$statement .= " WHERE ID = " . $id . ";";
echo $statement;
?>
My main problem is in the foreach loop. I don't know how can I compare and then use for building the query the $existingData and $data variables.
How can I achieve this?
Don't use this approach please, if you want a SOLID application that will outrun the ages, use specific column names and not some junkish foreach loop that builds your SQL for you. If you want to evade the writting of SQL, use an ORM, there are ton's that exist out there and most of them are bundled with a framework right off the start making it simpler to learn the ropes!
Examples of simple to learn frameworks: (But not necessarely weak frameworks)
Cake PHP
Laravel
Good luck
You need to change some code ...
$result = mysqli_query($con, $query);
$existingData = mysqli_fetch_assoc($result);
Now your $existingData is an array you can loop though;
Honestly I would recommend you take advantage of a framework with an ORM or just a standalone ORM. I suggest Laravel or CodeIgniter (if you are new to programming in general then CodeIgniter will be the easiest).
Next, why is your POST data JSON encoded? Why not just POST all the form variables? I would recommend that way instead to simplify it (even from JS).
Finally, you have to make sure you sanitize your inputs. You can use mysqli_real_escape_string(). I am assuming you will use the MySQLi DB interface. (Ref: http://php.net/manual/en/mysqlinfo.api.choosing.php)
Actually one last note: Laravel is, in my opinion, the future of PHP frameworks. It is beautiful, lightweight, and powerful. I HIGHLY recommend that you learn it. Ref: http://laravel.com/
I managed to get it working. Now I'm constructing my queries based on the difference between the existing data and the updates from the user. The foreach loop now looks like this:
foreach ($existingData as $key => $value) {
if ($existingData[$key] != $data[$key]) {
$statement .= $key . " = \"" . $data[$key] . "\" , ";
$flag = true;
}
}
This is the part that was interesting for me. The rest of the code should be updated according to the latest API.
To get an array like this array("123","456","789"); I use the code:
$Regids = mysql_query("SELECT regid FROM $tabel WHERE active = '1'");
while($row = mysql_fetch_array($Regids))
{
$result_array[] = "\"".$row['regid']."\"";
}
$regIDs = implode(',', $result_array);
$registrationIDs = array($regIDs); // array("123","456","789");
but I would expect PHP/mySQL has a simpler/faster solution for this?
I doubt that your code produces the result you want.
// assuming the this query produces 123,456,789
$Regids = mysql_query("SELECT regid FROM $tabel WHERE active = '1'");
// $row contains: array("123")
while($row = mysql_fetch_array($Regids))
{
$result_array[] = "\"".$row['regid']."\"";
}
// $result_array now contains: array("\"123\"", "\"456\"", "\"798\"");
$regIDs = implode(',', $result_array);
// $regIDS now contains a single string: "\"123\",\"456\",\"798\"";
$registrationIDs = array($regIDs);
// registrationIDs now is an array containing a single string: array("\"123\",\"456\",\"798\"");
If you really need an array that looks like this: array("123","456","789"); it is much simpler.
$Regids = mysql_query("SELECT regid FROM $tabel WHERE active = '1'");
while($row = mysql_fetch_array($Regids))
$registrationIDs[] = $row['regid'];
and that's all.
If your mysql result contains the number as an integer instead of an string you can convert it like this:
$Regids = mysql_query("SELECT regid FROM $tabel WHERE active = '1'");
while($row = mysql_fetch_array($Regids))
$registrationIDs[] = strval($row['regid']);
Also, keep in mind that the mysql_* functions are becoming deprecated. Don't start new code with it and make plans to port your existing code to mysqli_* or PDO.
You can use PDO implementation. At first sight, it may be more difficult to understand, but once you get used to it, it reveals to be really powerful and handy (IMHO! One year ago i switched to it and i love it)!
For your example, the PDO implementation would be like this:
/*CONNECT TO DB, FIRST. $dbh contains a handler to the current DB connection*/
$stmt = $dbh->prepare("SELECT regid FROM table WHERE active = '1'");
$stmt->execute();
$Regids = $stmt->fetchAll(PDO::FETCH_COLUMN,0);
There are many formatting options you can specify, like
PDO::FETCH_COLUMN
PDO::FETCH_ASSOC
and more...These options will allow you to get the array formatted as you prefer. As you can see i got the result in just 3 simple rows.
EDIT
Note: you are not escaping PHP variables before inserting them in your Query, and your code may suffer SQL INJECTION. Be careful!! Here is a simple guide to prevent it.
(In my code, just to be clear, i avoided the problem by just putting the table name instead of $table, just to show simply how to get the result you wanted.)
try this .. use Group concat in query ...
$Regids = mysql_fetch_array(mysql_query("SELECT GROUP_CONCAT(regid) as regids FROM $tabel WHERE active = '1'"));
echo $Regids[0]['regids']; // 123,456,789
for getting result "123","456","789" try this
$Regids = mysql_fetch_array(mysql_query("SELECT GROUP_CONCAT('\"',CONCAT(regid),'\"') as regids FROM $tabel WHERE active = '1'"));
echo $Regids[0]['regids']; // "123","456","789"
I'm trying to use DISTINCT to get a list of cities from a column in my DB.
function cityData() {
$db =& JFactory::getDBO();
$query = "SELECT DISTINCT MSTCITY FROM " . $db->nameQuote('#__mls') . " ORDER BY MSTCITY;";
$db->setQuery($query);
$tbl = $db->loadObjectList();
return $tbl;
}
Is there something akin to loadObjectList() that I can use ?
There are several options available to get data using database object.
You can check this link- http://docs.joomla.org/Accessing_the_database_using_JDatabase/1.5
In your case you can use loadResultArray() in place of loadObjectList.It'll return list of cities as values of an array.
Here's the revised joomla resource page for version 2.5 and 3.x
Selecting data using JDatabase. Also since you're already using the loadObjectList() function this question may be better asked as
How to use DISTINCT and JDatabase together
This post has a good solution by Janga_Jack but for your example here's a Joomla 3.x way to accomplish what you need, that allows you to use the convenience methods quote() or q(), quoteName() or qn(), and especially escape() or e().
function cityData() {
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$fieldlist = $db->qn(array('mls.MSTCITY')); // add the field names to an array
$fieldlist[0] = 'distinct ' . $fieldlist[0]; //prepend the distinct keyword to the first field name
$query->select($fieldlist);
->from($db->qn('#__mls', 'mls'))
->order($db->qn('mls.MSTCITY'));
$db->setQuery($query);
$tbl = $db->loadObjectList();
return $tbl;
}