How to write native query in Doctrine / Postgres equivalent to a normal PDO_PGSQL - postgresql

I have the following query in php with (pdo_pgsql) adapter:
$dsn = "pgsql:host=$host;port=5432;dbname=$db;user=$username;password=$password";
$conn = new PDO($dsn);
$query = 'SET search_path TO xyz_de;';
$result = $conn->query($query);
$query = 'Select * FROM "Orders" WHERE vendor_id=189 ';
$statement = $conn->query($query);
while($row = $statement->fetch(PDO::FETCH_ASSOC)) {
var_dump($row); // --> working perfectly fine, I see results here
}
I want to reproduce it using doctrine so I'm doing the following:
// given: 1) $this->em = EntityManager
// 2) the conenction is established successfull (I debugged it and sure about it)
$rsm = new ResultSetMapping();
$query = $this->em->createNativeQuery("SET search_path TO xyz_de ", $rsm);
$query->execute();
$query = $this->em->createNativeQuery('SELECT * FROM "Orders" WHERE vendor_id=?', $rsm);
$query->setParameter(1, 189);
$orders = $query->getArrayResult();
var_dump($orders); // Gives empty array (no errors)
as per my comment in the last line, the problem is that I get no results and no errors when using doctrine for this

Many things:
You can use addScalarResult
A simple example:
$rsm->addScalarResult('my_real_column', 'my_alias_column');
$query = $this->em->createNativeQuery('SELECT my_real_column FROM "Orders"');
var_dump($query->getScalarResult());
But I think, the best you can do is to use the queryBuilder.

Related

Joomla: get all users in a usergroup

I am working on a component where I want to show all users of a specific usergroup. Right now I found two solutions for this but I'm not feeling comfortable with both of them.
Solution 1
$usersID = JAccess::getUsersByGroup(3);
$users = array();
foreach($usersID as $cUserID)
{
$users[] = JFactory::getUser($cUserID);
}
This one seems to produce two database queries every time JFactory::getUser($cUserID) is called. I really don't want this.
Solution 2
function inside model
function getUsers()
{
if(!isset($this->users))
{
$groupID = 3;
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$select = array( 'users.id', 'users.name');
$where = $db->quoteName('map.group_id') . ' = ' . $groupID;
$query
->select($select)
->from( $db->quoteName('#__user_usergroup_map', 'map') )
->leftJoin( $db->quoteName('#__users', 'users') . ' ON (map.user_id = users.id)' )
->where($where);
$db->setQuery($query);
$this->users = $db->loadObjectList();
}
return $this->users;
}
This one works like a charm but I feel there should be a "more Joomla! way" of doing this. I don't like working on their tables.
Right now I'm going with solution 2 but i really wonder if there is some better way to do it.

Converting mysql_query to mysqli_query

I just moved to xampp version 7.0.13, which now has PHP 7.x, and the following query no longer works. I was Hoping someone can help me convert the following to mysqli query. I don't write code, so any help you could give me would be great.
// Count the number of rows in the member table
$rows = "SELECT * FROM $db_name.$tbl_name";
$count_rows = mysql_query( $rows );
here is your example with PDO:
$pdo = new PDO('mysql:host=localhost;dbname=databasename', 'username', 'password');
$sql = 'SELECT * FROM :table';
$statement = $pdo->prepare($sql);
$count = $statement->execute(array('table' => 'your-table-name'))->rowCount();

How to migrate mysqli to pdo

Hi I was wondering how I would migrate a mysqli php file to use PDO. Would anyone be able to take a look at my code and see if I'm on the right track?
This is my original (mysqli) code:
<?php
// connecting to database
$conn = new mysqli('xxxxxx', 'xxxxxx', 'password', 'xxxxxx');
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = '$match_email' AND passhash = '$match_passhash'
AND userlevel='user' AND confirmed='true' AND blocked='false';";
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
And this is my attempt to migrate it to PDO:
<?php
// connecting to database
$dbh = new PDO("mysql:host=xxxxxx; dbname=xxxxxx", "xxxxxx", "password");
$match_email = 'email';
$match_passhash = 'passhash';
if (isset($_POST['email'])) {
$clean_email = mysqli_real_escape_string($conn, $_POST['email']);
$match_email = $clean_email;
}
if (isset($_POST['passhash'])) {
$clean_passhash = mysqli_real_escape_string($conn, $_POST['passhash']);
$match_passhash = sha1($clean_passhash);
}
$userquery = "SELECT email, passhash, userlevel, confirmed, blocked FROM useraccounts
WHERE email = ':match_email' AND passhash = ':match_passhash' AND
userlevel='user' AND confirmed='true' AND blocked='false';";
$stmt = $dbh->prepare($query);
$stmt->bindParam(":match_email", $match_email);
$stmt->bindParam(":match_passhash", $match_passhash);
$stmt->execute();
$userresult = $conn->query($userquery);
if ($userresult->num_rows == 1) {
$_SESSION['authorisation'] = 'knownuser';
header("Location: userhome.php");
exit;
} else {
$_SESSION['authorisation'] = 'unknownuser';
header("Location: userlogin.php");
exit;
}
?>
I'm also not sure how to count the number of rows returned in PDO.
If anyone would be able to help me out that wold be very great.
A million thanks in advance!
When using prepared statements and $stmt->bindValue() or $stmt->bindParam() you do not need to escape values with mysqli_real_escape_string(), PDO will do that for you.
Just remember to set a correct data type for the value. That is the third argument in the bind functions and it is a string by default so your code here is fine. I would only use bindValue() instead of bindParam() as you do not need references.
$stmt->execute() will run your prepared statement as a query. The other $conn->query() does not work with prepared statements. It is for raw queries, like you used to have with MySQLi.
When $stmt->execute() runs your response is saved in the $stmt object. For row count use $stmt->rowCount().

How can i find the sql query statement of insert() in Zend Framework?

How can i find the sql query statement in Zend Framework for insert(), like its done for db table select's. $select->__toString().
Try this which work for me:
$db = Zend_Db_Table_Abstract::getDefaultAdapter();
$db->getProfiler()->setEnabled(true);
$profiler = $db->getProfiler();
$lastID = ($this->insert($data));
$query = $profiler->getLastQueryProfile();
$params = $query->getQueryParams();
$sqlQuery= $query->getQuery();
foreach ($params as $par) {
$sqlQuery = preg_replace('/\\?/', "'" . $par . "'", $sqlQuery, 1);
}
echo $sqlQuery;
You can't extract it since it's executed right away, but the code exists in Zend_Db_Adapter_Abstract::insert() and possibly overwritten in some of the adapters.

Zend DB Framework examine query for an update

So you can use something like this:
$query = $db->select();
$query->from('pages', array('url'));
echo $query->__toString();
to examine the sql that the Zend Db Framework is going to use for that SELECT query. Is there an equivilent way to view the SQL for an update?
$data = array(
'content' => stripslashes(htmlspecialchars_decode($content))
);
$n = $db->update('pages', $data, "url = '".$content."'");
??
Use Zend_Db_Profiler to capture and report SQL statements:
$db->getProfiler()->setEnabled(true);
$db->update( ... );
print $db->getProfiler()->getLastQueryProfile()->getQuery();
print_r($db->getProfiler()->getLastQueryProfile()->getQueryParams());
$db->getProfiler()->setEnabled(false);
Remember to turn the profiler off if you don't need it! I talked to one fellow who thought he had a memory leak, but it was the profiler instantiating a few PHP objects for each of the millions of SQL queries he was running.
PS: You should use quoteInto() in that query:
$n = $db->update('pages', $data, $db->quoteInto("url = ?", $content));
No, not directly, since Zend Framework builds and executes the SQL inside the adapter method Zend_Db_Adapter_Abstract::update:
/**
* Updates table rows with specified data based on a WHERE clause.
*
* #param mixed $table The table to update.
* #param array $bind Column-value pairs.
* #param mixed $where UPDATE WHERE clause(s).
* #return int The number of affected rows.
*/
public function update($table, array $bind, $where = '')
{
/**
* Build "col = ?" pairs for the statement,
* except for Zend_Db_Expr which is treated literally.
*/
$set = array();
foreach ($bind as $col => $val) {
if ($val instanceof Zend_Db_Expr) {
$val = $val->__toString();
unset($bind[$col]);
} else {
$val = '?';
}
$set[] = $this->quoteIdentifier($col, true) . ' = ' . $val;
}
$where = $this->_whereExpr($where);
/**
* Build the UPDATE statement
*/
$sql = "UPDATE "
. $this->quoteIdentifier($table, true)
. ' SET ' . implode(', ', $set)
. (($where) ? " WHERE $where" : '');
/**
* Execute the statement and return the number of affected rows
*/
$stmt = $this->query($sql, array_values($bind));
$result = $stmt->rowCount();
return $result;
}
You can, temporarily, insert a var_dump and exit inside this method to inspect the sql to ensure that it is correct:
/**
* Build the UPDATE statement
*/
$sql = "UPDATE "
. $this->quoteIdentifier($table, true)
. ' SET ' . implode(', ', $set)
. (($where) ? " WHERE $where" : '');
var_dump($sql); exit;
I quess another way is to log the actual SQL query, rather than changing the ZF library code, by combining the profiler data.
$db->getProfiler()->setEnabled(true);
$db->update( ... );
$query = $db->getProfiler()->getLastQueryProfile()->getQuery();
$queryParams = $db->getProfiler()->getLastQueryProfile()->getQueryParams();
$logger->log('SQL: ' . $db->quoteInto($query, $queryParams), Zend_Log::DEBUG);
$db->getProfiler()->setEnabled(false);
Recently came across this looking for a way to debug a zend_db_statement. If anyone else comes across this with the same search, you can use the following function.
Just replace "self::getDefaultAdapter()" with your method of getting a DB connection or adapter.
/**
* replace any named parameters with placeholders
* #param string $sql sql string with placeholders, e.g. :theKey
* #param array $bind array keyed on placeholders, e.g. array('theKey', 'THEVALUE')
*
* #return String sql statement with the placeholders replaced
*/
public static function debugNamedParamsSql($sql, array $bind) {
$sqlDebug = $sql;
foreach($bind as $needle => $replace) {
$sqlDebug = str_replace(
':' . $needle,
self::getDefaultAdapter()->quote($replace),
$sqlDebug
);
}
return $sqlDebug;
}