ZF2 - bind array to single database query parameter - php

I'm trying to run a simple query against a Zend\Db\Adapter\Adapter instance. Some sample code:
$sql = "DELETE FROM Goals WHERE match_no = ? AND event_id NOT IN (?) ";
$res = $this->adapter->query($sql, array($matchNo, $goalIds));
return $res->getAffectedRows();
This won't work unfortunately, as the array $goalIds isn't quoted as a list for the IN () part of the SQL, but instead is placed in the SQL as 'Array'.
I've searched and search, and also played with the ZF2 ParameterContainer, but can't work out how to quote an array into a single parameter of comma separated values like this.
I'm pretty sure this could work if I used DB Select functionality, but I'd rather just keep to plain old SQL and parameter for these type of quick queries.
Any help much appreciated.
:wq

Assuming you are using MySQl Adapter, You can do things in the Zend way by writing this:-
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
use Zend\Debug\Debug;
$config = array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=database;host=localhost;charset=utf8',
'user' => 'root',
'pass' => 'password',
);
$adapter= new Adapter($config);
$sql = new Sql($adapter);
$select = $sql->select();
$select->from('Goals');
$select->where->notin('match_no', array($matchNo, $goalIds));
$select->where->notin('event_id', array($matchNo, $goalIds));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE);
Debug::dump($results);

Related

PHP "variable wrapper" as an array for SQL queries over multiple databases

I have 50 databases with the same design and structure. For benchmarking data analysis and evaluation of the several thousand of variables contained therein I need to build SQL queries. I have a SuperAdmin account who has the permission to view all these databases through an SSH access.
Now, I can write SQL queries combining data from one database after another using UNION ALL like this (simplified):
SELECT * FROM db1.table WHERE blah
UNION ALL
SELECT * FROM db2.table WHERE blah
UNION ALL
[...]
SELECT * FROM db50.table WHERE blah
These queries are within a PHP environment and work like a charm - I get all data analyses and evaluations I want.
But:
A single SQL query in my case, however, has about 1.000 lines of query statement and conditional code. Querying 50 databases this sequential way means that my query becomes quite large and I have to do a lot of error-prone copying the SQL query statement adjusting "db1" to "db50" every single time plus within a lot of JOINs additionally, so it becomes a pain in the youknowhere and becomes time-consuming.
My question:
Isn't there a way in which I can tell PHP to put all the "dbx" into an array and reiterate then only the one basic SQL query by exchanging the "dbx" from 1 to 50 using a foreach or while or similar statement?
Such as:
<?php
function getResultValuesFromDatabase() {
global $DATABASE;
$db1 = "database1";
$db2 = "database2";
[...]
$db50 = "database50";
$no_of_databases = array($db1, $db2, [...], $db50);
foreach ($no_of_databases as $value) {
$sql_query = "SELECT * FROM $value.table WHERE blah";
}
$rQuery = mysql_query($qQuery, $oDatabase);
$result = array("count" => mysql_num_rows($rQuery ), "result" => $rQuery);
return $result;
}
I receive an error which affects the reiteration process. Can anybody please tell me where my logical error is?
You don't need an array of the names. Since they are all similar a simple for loop should work for you. You also need to do the query in the loop and accumulate the results before you return them.
for ($db = 1;$db <= 50;$db++) {
$sql_query = 'SELECT * FROM database' . str_pad($db,2,'0',STR_PAD_LEFT) . '.table WHERE blah';
$rQuery = mysql_query($qQuery, $oDatabase);
$result[] = array("count" => mysql_num_rows($rQuery ), "result" => $rQuery);
}
return $result;
Of course, you can do it, but you must change the database before doing any request.
Also, please note that mysql_* functions are deprecated and you must consider changing them to mysqli or PDO.
Here is how you could do it:
function getResultValuesFromDatabase()
{
$result = [];
$con = mysqli_connect("localhost","my_user","my_password");
for ($i = 1; $i <= 50; $i++) {
$databaseName = 'database' . str_pad($i, 2, '0', STR_PAD_LEFT);
mysqli_select_db($con, $databaseName);
// Probably the database doesn't exist
if (mysqli_errno($con) !== 0) {
continue;
}
$queryResult = mysqli_query($con, "SELECT * FROM table WHERE blah");
$result[$databaseName] = [
'count' => mysqli_num_rows($queryResult),
'result' => mysqli_fetch_all($queryResult, MYSQLI_ASSOC)
];
mysqli_free_result($queryResult);
}
mysqli_close($con);
return $result;
}

Dynamically creating OR conditions by passing an array to a query in MySQL PHP

I am trying to create OR condition dynamically using an array. Given an array, of course names $courses = array('Eng, 'Deu', 'Bio', 'Chemi') I want to have a SQL query that uses the values of the array in its AND clause with OR conditions like:
SELECT *
FROM classe
/* The OR conditions should be created in AND clause using array */
WHERE class = 'EFG' AND (course = 'Eng' OR course = 'Deu' OR course = 'Bio')
I trying to do it in PHP MySQL.
Any help would be really appreciated.
Thanks in Advance.
Instead of so many OR clauses, you can simply use IN(..):
SELECT *
FROM classe
WHERE class = 'EFG' AND course IN ('Eng' ,'Deu', 'Bio')
In the PHP code, you can use implode() function to convert the array into a comma separated string, and use it in the query string generation.
The IN clause will be easier to use than ORs. If you are using PDO you can take advantage of its execute binding and build the placeholders dynamically then just pass your array to it.
$courses = array('Eng', 'Deu', 'Bio', 'Chemi');
$placeholders = rtrim(str_repeat('?, ', count($courses)), ', ');
$query = "select * from table WHERE class = 'EFG' AND course in ({$placeholders})";
$stmt = $pdo->prepare($query);
$stmt->execute($courses);
Demo: https://3v4l.org/jcFSv (PDO bit non functional)

update query with functions in typo3

I'm trying to use the typo3 update function with the mysql CONCAT function. Can you tell me how to manage that? What I tried:
$updateArray = array("field" => 'CONCAT( field'.','.$toAppend.')');
$GLOBALS['TYPO3_DB']->exec_UPDATEquery ('table','id = '.'"'.$some_id.'"',$updateArray);
That does not work, because that query is executed:
UPDATE table
SET
pagesEdited='CONCAT( field,'value')'
WHERE
id = "id"
As you see, the concat function is escaped.
The reference documentation isn't very clear about it, however, just appending TRUE to your parameters of the update function should disable quoting:
$GLOBALS['TYPO3_DB']->exec_UPDATEquery ('table','id = '.'"'.$some_id.'"',$updateArray, TRUE);
That also means that you will have to do your own input sanitization before lauching the query, if you haven't already:
$toAppend = $GLOBALS['TYPO3_DB']->fullQuoteString($toAppend, "");
Have a look at the noQuote parameter of the fullQuoteArray() method of TYPO3\CMS\Core\Database\DatabaseConnection that is used by exec_UPDATEquery():
#param boolean|array $noQuote List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
And when you take a kloser look ath this method, you will see that a simple true does not do the trick as expected. Simply use a list of fields (comma separated list) or an array to let TYPO3 know which fields should not be escaped.
In your case it would look like this:
$updateArray = array(
'field' => 'CONCAT(field,' . $GLOBALS['TYPO3_DB']->fullQuoteString($toAppend, 'table') . ')',
);
$where = 'id = ' . $GLOBALS['TYPO3_DB']->fullQuoteString($some_id, 'table');
$GLOBALS['TYPO3_DB']->exec_UPDATEquery ('table', $where, $updateArray, 'field');

Codeigniter mysql query AND_OR

Just trying to write custom string for $this->db->where(); function but I get syntax errors. Could you have a look on the code below to find the mistake
$where = "'phone' => $this->input->post('phone') AND '2g' = $data['2g'] OR '3g' = $data['3g'] OR '4g' = $data['4g']";
You're mixing two types of parameters for the $this->db->where() function.
From the docs
http://ellislab.com/codeigniter/user-guide/database/active_record.html
You either supply an associative array (like 'phone' => $this->input->post('phone'))
or you suppliy a custom string $where = "name='Joe' AND status='boss' OR status='active'";
You can't mix the two

Select ignores where clause using Zend_Db_Select

$table = new Zend_Db_Table(array('name'=>'rules'));
$select = $table->select();
$select->setTable($table);
$select->setIntegrityCheck(false);
$select = $select
->from(array('ru'=>'rules'),array('ru.*'))
->join(array('ro'=>'roles'),'ro.id=ru.role_id',array('role_id'=>'ro.id'))
->join(array('g'=>'groups'),'ro.group_id=g.id',array('group_id'=>'g.id'))
->join(array('ug'=>'user_groups'),"ug.group_id=g.id",array('user_group_id'=>'ug.id'))
->where("ug.user_id={$userId}")
->where("ru.resource='{$resource}'")
->where("ru.privilege='{$privilege}'");
echo "select: ".$select->__toString();
$row = $table->fetchAll();
I have the preceding code,but when I try fetchAll() it returns all rows in the table, ignoring the where clause, when I use fetchRow() it returns the first row it finds, ignoring the where clause, I printed the SQL statement and run it separately and it executes correctly
any clue ?
This is how you would create a db select object correctly
$db = Zend_Db::factory( ...options... );
$select = new Zend_Db_Select($db);
Or you use the database adapter's select() method
$db = Zend_Db::factory( ...options... );
$select = $db->select();
And you can add clauses
// Build this query:
// SELECT *
// FROM "table1"
// JOIN "table2"
// ON "table1".column1 = "table2".column1
// WHERE column2 = 'foo'
$select = $db->select()
->from('table1')
->joinUsing('table2', 'column1')
->where('column2 = ?', 'foo');
Have a look at the Zend_Db Reference Guide for more information
#ArtWorkAD is right in a certain way. But in your case you're not just using a Zend_Db_Select. You tried to extend a Zend_Db_Select obtained from a Zend_Db_Table (well, you should try to handle a Singleton pattern with Zend_Db_Table but this is another problem). Your current problem (if we except the fact you are certainly reading documentation too fast) is that this line was correct:
$select->setIntegrityCheck(false);
It make your 'select-from-a-zend-db-table' not anymore restricted to the Active Record Mode, and available for extra joins.
But just after that you make a:
$select = new Zend_Db_Select($table);
This is the complete creation of a new object, that you put into your variable. Nothing is kept from previous variable value. You could add a $select=null; just before it would be the same. So this is just canceling the 3 previous lines.
In quite the same confusion mode this line:
$select->setTable($table);
Is not necessary as you're already taking the select from a Zend_Db_Table so the table is already there.
EDIT
And your last and bigger error is:
$table->fetchAll()
You do not use your built $select but your $table, so effectively everything done in your $select is ignored :-) . Fecthing from the $select shoudl give you better results
This should work. Just tested it.
$table = new Zend_Db_Table('rules');
$select = $table->getAdapter()->select();
$select->from(array('ru' => 'rules'), array('ru.*'))
->join(array('ro'=>'roles'), 'ro.id = ru.role_id', array('role_id'=>'ro.id'))
->join(array('g'=>'groups'), 'ro.group_id = g.id', array('group_id'=>'g.id'))
->join(array('ug'=>'user_groups'),"ug.group_id=g.id",array('user_group_id'=>'ug.id'))
->where('ug.user_id = ?', $userId)
->where('ru.resource = ?', $resource)
->where("ru.privilege = ?", $privilege);
echo (string)$select;

Categories