Passing array with parameters to Model in Codeigniter 4 - sql

I tryng to pass an array of values from my controller to the model
My controller:
$arr_list = array('O','N','H');
$data['lista'] = $getmodel->query_list($arr_list1);
My model
public function query_list($list = '', $limit = 10, $lang = 'en')
{
$query = "SELECT tab1.id, name FROM tab_name";
$a = 0;
foreach( $list as $value)
{
if ($value != ''){
if ($a == 0){
$query .= " AND (field = '".$value."' ";
}
else
{
$query .= " OR field = '".$value."' ";
}
$a = $a + 1;
}
}
$query .= " ORDER BY RAND() ";
}
I receive the error: Array to string conversion
This code works perfectly in CI 2 but does not work on CI4.
Why?

Lots of bugs in yours the code, but I'll try to help.
Docs CI4: $builder->whereIn()
Generates a WHERE field IN (‘item’, ‘item’) SQL query joined with AND if appropriate
$names = ['Frank', 'Todd', 'James'];
$builder->whereIn('username', $names);
// Produces: WHERE username IN ('Frank', 'Todd', 'James')
Controller
$this->data['return'] = $HotelModel->test(['1', '2', '3', '4']);
Model
public function test($array)
{
return $this->db->table('tab_name')->whereIn('column',$array)->get()->getResultObject();
}
Result last_query
SELECT * FROM 'tab_name' WHERE 'column' IN ('1', '2', '3', '4')

Related

TYPO3 9.5 Extbase Query for UidArray

I´ve got the following SQL-Query
$uidArray = explode(",", $uids);
foreach ($uidArray as $uid) {
$dynamicUid[] = '`uid` LIKE \''.$uid.'\'';
}
$query = $this->createQuery();
$query->statement("SELECT * FROM `tx_myextension_domain_model_thi` WHERE ".implode($dynamicUid, " OR "));
return $query->execute();
This works fine but I want to have it like this:
$uidArray = explode(",", $uids);
$query = $this->createQuery();
foreach ($uidArray as $key => $value) {
$constraints[] = $query->equals('uid', $value);
}
return $query->matching(
$query->logicalAnd($constraints)
)->execute();
Here I get the following Output with the Query Parser :
'SELECT `tx_myextension_domain_model_thi`.* FROM `tx_myextension_domain_model_thi`
`tx_myextension_domain_model_thi`
WHERE ((`tx_myextension_domain_model_thi`.`uid` = :dcValue1) AND
(`tx_myextension_domain_model_thi`.`uid` = :dcValue2)) AND
(`tx_myextension_domain_model_thi`.`sys_language_uid` IN (0, -1)) AND
(`tx_myextension_domain_model_thi`.`pid` = 0) AND
((`tx_myextension_domain_model_thi`.`deleted` = 0) AND (
`tx_myextension_domain_model_thi`.`t3ver_state` <= 0) AND
(`tx_myextension_domain_model_thi`.`pid` <> -1) AND
(`tx_myextension_domain_model_thi`.`hidden` = 0) AND
(`tx_myextension_domain_model_thi`.`starttime` <= 1607084460) AND
((`tx_myextension_domain_model_thi`.`endtime` = 0)
OR (`tx_myextension_domain_model_thi`.`endtime` > 1607084460)))'
And the Uids as dcValue-Array.
dcValue1 => '1' (1 chars)
dcValue2 => '2' (1 chars)
Maybe someone can help me to rewrite this, because unfortunately I can't get any further!
Thanks :)
Did you try the in operator?
public function yourFunctionName($uid)
{
$query = $this->createQuery();
$query->in('uid', $uidArray);
return $query->execute();
}
Assuming that your array looks like this:
$uidArray = [
0 = '34',
1 = '15',
3 = '88'
]
EDIT
If you do not care about where your objects are stored then you can do the following.
public function yourFunctionName($uid)
{
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
$query->matching(
$query->in('uid', $uidArray)
);
return $query->execute()];
}
Which is going to ignore the pid in the query

ignore where statement if parameter is null in doctrine

Hi i have a problem in QueryByilder in Doctrine. i wrote a Query that has 2 parameter and they affect in where statement. i want to ignore where statement if the related parameter was null. for example if $play = 3 and $theater = null the query must return all tickets with play 3 and whatever theater
this is my code:
public function getAllSearchedTickets($play,$teater){
return $this->getEntityManager()->createQuery('
select s from mtadminBundle:ReserveLocation s
join s.reserve a
join a.sance b
where a.acceptCode != 0
and b.play = :play
and b.teater = :teater')
->setParameters(array('play'=>$play,'teater'=>$teater))->getResult();
}
thank you.
You should use the QueryBuilder for this, to do it more efficiently, I'll show you how you do yours and then the same with the QueryBuilder as example:
Yours:
public function getAllSearchedTickets($play,$teater){
$query = 'select s from mtadminBundle:ReserveLocation s'.
'join s.reserve a'.
'join a.sance b'.
'where a.acceptCode != 0');
$paramArray = array();
if( $play ) {
$query .= ' and b.play = :play';
$paramArray['play'] = $play;
}
if( $teater ) {
$query .= ' and b.teater = :teater';
$paramArray['teater '] = $teater;
}
return $this->getEntityManager()->createQuery($query)
->setParameters($paramArray)->getResult();
}
QueryBuilder:
public function getAllSearchedTickets($play,$teater){
$queryBuilder = $this->getEntityManager()->createQueryBuilder();
$queryBuilder->select('s')
->from('mtadminBundle:ReserveLocation', 's')
->join('s.reserve', 'a')
->join('a.sance', 'b')
->where('a.acceptCode != 0');
if( $play ) {
$queryBuilder->andWhere('b.play = :play');
$queryBuilder->setParameter('play', $play);
}
if( $teater ) {
$queryBuilder->andWhere('b.teater = :teater');
$queryBuilder->setParameter('teater', $teater);
}
return $queryBuilder->getResult();
}

Get raw sql from Phalcon query builder

Is it possible to extract raw sql query from the query builder instance in Phalcon? Something like this?
$queryBuilder = new Phalcon\Mvc\Model\Query\Builder();
$queryBuilder
->from(…)
->where(…);
$rawSql = $queryBuilder->hypotheticalGetRawQueryMethod();
By error and trial the below seems to working. Would be great if someone could confirm if there's a better way.
$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…);
$intermediate = $queryBuilder->getQuery()->parse();
$dialect = DI::getDefault()->get('db')->getDialect();
$sql = $dialect->select($intermediate);
Edit: As of 2.0.3 you can do it super simple, see comment for full details:
$modelsManager->createBuilder()
->from('Some\Robots')
->getQuery()
->getSql()
you can use getRealSqlStatement() (or similar function name) on the DbAdapter. See http://docs.phalconphp.com/en/latest/api/Phalcon_Db_Adapter.html
According to documentation you can get this way the resulting sql query.
Or wait, this might not work on querybuilder. Otherwise you can setup low level query logging: http://docs.phalconphp.com/en/latest/reference/models.html#logging-low-level-sql-statements
$db = Phalcon\DI::getDefault()->getDb();
$sql = $db->getSQLStatement();
$vars = $db->getSQLVariables();
if ($vars) {
$keys = array();
$values = array();
foreach ($vars as $placeHolder=>$var) {
// fill array of placeholders
if (is_string($placeHolder)) {
$keys[] = '/:'.ltrim($placeHolder, ':').'/';
} else {
$keys[] = '/[?]/';
}
// fill array of values
// It makes sense to use RawValue only in INSERT and UPDATE queries and only as values
// in all other cases it will be inserted as a quoted string
if ((strpos($sql, 'INSERT') === 0 || strpos($sql, 'UPDATE') === 0) && $var instanceof \Phalcon\Db\RawValue) {
$var = $var->getValue();
} elseif (is_null($var)) {
$var = 'NULL';
} elseif (is_numeric($var)) {
$var = $var;
} else {
$var = '"'.$var.'"';
}
$values[] = $var;
}
$sql = preg_replace($keys, $values, $sql, 1);
}
More you can read there
The following is the common solution:
$result = $modelsManager->createBuilder()
->from(Foo::class)
->where('slug = :bar:', ['bar' => "some-slug"])
->getQuery()
->getSql();
But you might not expect to see the query without its values, like in:
die(print_r($result, true));
Array
(
[sql] => SELECT `foo`.`id`, `foo`.`slug` FROM `foo` WHERE `foo`.`slug` = :bar
[bind] => Array
(
[bar] => some-slug
)
[bindTypes] =>
)
So, this simple code might be useful:
public static function toSql(\Phalcon\Mvc\Model\Query\BuilderInterface $builder) : string
{
$data = $builder->getQuery()->getSql();
['sql' => $sql, 'bind' => $binds, 'bindTypes' => $bindTypes] = $data;
$finalSql = $sql;
foreach ($binds as $name => $value) {
$formattedValue = $value;
if (\is_object($value)) {
$formattedValue = (string)$value;
}
if (\is_string($formattedValue)) {
$formattedValue = sprintf("'%s'", $formattedValue);
}
$finalSql = str_replace(":$name", $formattedValue, $finalSql);
}
return $finalSql;
}
If you're using query builder then like given below then getPhql function can serve the purpose as per phalcon 3.4.4 version.
$queryBuilder = new Builder();
$queryBuilder->from(…)->where(…)->getQuery();
$queryBuilder->getPhql();
if (!function_exists("getParsedBuilderQuery")) {
/**
* #param \Phalcon\Mvc\Model\Query\BuilderInterface $builder
*
* #return null|string|string[]
*/
function getParsedBuilderQuery (\Phalcon\Mvc\Model\Query\BuilderInterface $builder) {
$dialect = Phalcon\Di::getDefault()->get('db')->getDialect();
$sql = $dialect->select($builder->getQuery()->parse());
foreach ($builder->getQuery()->getBindParams() as $key => $value) {
// For strings work fine. You can add other types below
$sql = preg_replace("/:?\s?($key)\s?:?/","'$value'",$sql);
}
return $sql;
}
}
Simple function that im using for debugging.

ZF2 insert multiple rows

I'd like to know if there is a way to insert multiple row in ZF2 using only one $sql object (and not using the query(SQL COMMAND) method).
I tried something like this, but it doesn't work:
public function setAgentProjectLink( $IDProject , $IDsAgents )
{
$values = array () ;
foreach ( $IDsAgents as $IDAgent):
{
$values[] = array ( 'id_agent' => $IDAgent , 'id_projet' => $IDProject) ;
} endforeach ;
$sql = new Sql( $this->tableGateway->adapter ) ;
$insert = $sql->insert() ;
$insert -> into ( $this->tableGateway->getTable() )
-> values ( $values ) ;
$statement = $sql->prepareStatementForSqlObject($insert);
$result = $statement->execute();
}
Trying to insert values in a database with two columns (id_agent, id_projet)
there is no generic way for multyinsert in ZF2 BUT if you are using mysql and not planning to change to other databases, i have written a multiInsert function for myself:
$data is an array of arrays of key,value pairs.
protected function multiInsert($table, array $data)
{
if (count($data)) {
$columns = (array)current($data);
$columns = array_keys($columns);
$columnsCount = count($columns);
$platform = $this->db->platform;
array_filter($columns, function ($index, &$item) use ($platform) {
$item = $platform->quoteIdentifier($item);
});
$columns = "(" . implode(',', $columns) . ")";
$placeholder = array_fill(0, $columnsCount, '?');
$placeholder = "(" . implode(',', $placeholder) . ")";
$placeholder = implode(',', array_fill(0, count($data), $placeholder));
$values = array();
foreach ($data as $row) {
foreach ($row as $key => $value) {
$values[] = $value;
}
}
$table = $this->db->platform->quoteIdentifier($table);
$q = "INSERT INTO $table $columns VALUES $placeholder";
$this->db->query($q)->execute($values);
}
}

Applying a SQL function on Zend_Db_Table_Row::save()

Is it possible, when saving a Zend_Db_Table_Row, to make ZF apply a SQL function on one column?
For example, if $row->save() generates by default this SQL query:
UPDATE table SET field = ? WHERE id = ?;
I would like it to automatically apply the GeomFromText() function on this field:
UPDATE table SET field = GeomFromText(?) WHERE id = ?;
Thanks for any hint on how to do this with Zend_Db!
Define a custom update method in your class that inherits from Zend_Db_Table (not from the Zend_Db_Table_Row) and use a Zend_Db_Expr to set the column to the function return value.
See the docs here: http://framework.zend.com/manual/en/zend.db.table.html#zend.db.table.extending.insert-update.
I am just guessing but you could try this:
<?php
class MyTable extends Zend_Db_Table_Abstract
{
protected $_name = 'my_table';
public function update(array $data, $where) {
/**
* Build "col = ?" pairs for the statement,
* except for Zend_Db_Expr which is treated literally.
*/
$set = array();
$i = 0;
foreach ($data as $col => $val) {
if ($val instanceof Zend_Db_Expr) {
$val = $val->__toString();
unset($data[$col]);
} else {
if ($this->_db->supportsParameters('positional')) {
$val = ($col == 'field') ? 'GeomFromText(?)' : '?';
} else {
if ($this->_db->supportsParameters('named')) {
unset($data[$col]);
$data[':col'.$i] = $val;
$val = ($col == 'field') ? 'GeomFromText(:col'.$i.')' : ':col'.$i;
$i++;
} else {
/** #see Zend_Db_Adapter_Exception */
require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding");
}
}
}
$set[] = $this->_db->quoteIdentifier($col, true) . ' = ' . $val;
}
$where = $this->_whereExpr($where);
/**
* Build the UPDATE statement
*/
$sql = "UPDATE "
. $this->_db->quoteIdentifier($this->_name , true)
. ' SET ' . implode(', ', $set)
. (($where) ? " WHERE $where" : '');
/**
* Execute the statement and return the number of affected rows
*/
if ($this->_db->supportsParameters('positional')) {
$stmt = $this->_db->query($sql, array_values($data));
} else {
$stmt = $this->_db->query($sql, $data);
}
$result = $stmt->rowCount();
return $result;
}
protected function _whereExpr($where)
{
if (empty($where)) {
return $where;
}
if (!is_array($where)) {
$where = array($where);
}
foreach ($where as $cond => &$term) {
// is $cond an int? (i.e. Not a condition)
if (is_int($cond)) {
// $term is the full condition
if ($term instanceof Zend_Db_Expr) {
$term = $term->__toString();
}
} else {
// $cond is the condition with placeholder,
// and $term is quoted into the condition
$term = $this->quoteInto($cond, $term);
}
$term = '(' . $term . ')';
}
$where = implode(' AND ', $where);
return $where;
}
}
?>