Yii2 Write Custom Condition - yii2

I have something like this
$project = Project::find();
how can I write a custom
SELECT * FROM `Project` WHERE `personincharge` REGEXP "(^|,)2(,|$)"

you can do this easily by findBySql this way
$sql = 'SELECT * FROM `Project` WHERE `personincharge` REGEXP "(^|,)2(,|$)";';
$model = Project::findBySql($sql)->all();

You can execute any plain sql query using Yii2 createcommand method as shown below:
use yii\db\Query;
$connection = \Yii::$app->db;
$model = $connection->createCommand('SSELECT * FROM `Project` WHERE `personincharge` REGEXP "(^|,)2(,|$)"');
$projects = $model->queryAll();

Related

Fat free Framework Parameterized queries LIKE [duplicate]

I am running problems in implementing LIKE in PDO
I have this query:
$query = "SELECT * FROM tbl WHERE address LIKE '%?%' OR address LIKE '%?%'";
$params = array($var1, $var2);
$stmt = $handle->prepare($query);
$stmt->execute($params);
I checked the $var1 and $var2 they contain both the words I want to search, my PDO is working fine since some of my queries SELECT INSERT they work, it's just that I am not familiar in LIKE here in PDO.
The result is none returned. Do my $query is syntactically correct?
You have to include the % signs in the $params, not in the query:
$query = "SELECT * FROM tbl WHERE address LIKE ? OR address LIKE ?";
$params = array("%$var1%", "%$var2%");
$stmt = $handle->prepare($query);
$stmt->execute($params);
If you'd look at the generated query in your previous code, you'd see something like SELECT * FROM tbl WHERE address LIKE '%"foo"%' OR address LIKE '%"bar"%', because the prepared statement is quoting your values inside of an already quoted string.
Simply use the following:
$query = "SELECT * FROM tbl WHERE address LIKE CONCAT('%', :var1, '%')
OR address LIKE CONCAT('%', :var2, '%')";
$ar_val = array(':var1'=>$var1, ':var2'=>$var2);
if($sqlprep->execute($ar_val)) { ... }
No, you don't need to quote prepare placeholders. Also, include the % marks inside of your variables.
LIKE ?
And in the variable: %string%
$query = "SELECT * FROM tbl WHERE address LIKE ? OR address LIKE ?";
$params = array("%$var1%", "%$var2%");
$stmt = $handle->prepare($query);
$stmt->execute($params);
You can see below example
$title = 'PHP%';
$author = 'Bobi%';
// query
$sql = "SELECT * FROM books WHERE title like ? AND author like ? ";
$q = $conn->prepare($sql);
$q->execute(array($title,$author));
Hope it will work.

Query builder not display variable?

I running this code :
$id = 1;
$email = 'email#gmail.com';
$user = DB::table('users')->where([
['id', '=', $id],
['email', '=', $email]
])->toSql();
dd($user);
But query builder print is :
select * from `users` where (`id` = ? and `email` = ?)
Why not print is:
select * from `users` where (`id` = 1 and `email` = email#gmail.com)
the query builder inserts the characters in place of the values to protect you from the sql injections, then he himself will set the values to you as needed, and you will get the finished result, and the fact that you are displayed on the screen is simply viewing the query queries
That's how toSql() method works. It just shows you prepared query but doesn't execute it.
To execute the query, do use get(), find(), first() or similar method:
$user = DB::table('users')->where([
['id', '=', $id],
['email', '=', $email]
])->first();
Query Builder inserts the characters in place of the values to protect you from the SQL Injections.I believe #Дмитрий-Смирнов answered your query well.
Rather then using raw SQL use model directly you may cut-down your line of code using the below code:
$id = 1;
$email = 'email#gmail.com';
$user = User::where('id',$id)
->where('email',$email)
->get();
dd($user);

Left Join from Select Zend Framework

How can I do a Query like this using the Zend framework
SELECT * FROM `productos` AS `p`
LEFT JOIN (SELECT SUM(cantidad) AS transferencias FROM transferencias WHERE upc = p`.`upc` and sucursal = 10)
AS `trans` ON trans.upc = p.upc AND trans.sucursal_clave_destino = 10
Thank you in advance.
You need to try this one.
I can't try it but the way of resolve it you can use from my query
$this->getAdapter()
->select()
->from(array('p' => 'productos'))
->joinLeft(array('trans' => $this->getAdapter()
->select()
->from('transferencias', 'SUM(cantidad)')
->where('upc IN (?)', $this->getAdapter()
->select()
->from('productos', 'upc')
)->where('sucursal = ?', 10)
), 'trans.upc = p.upc')
->where('trans.sucursal_clave_destino = ?', 10)
->query()
->fetchAll();
First of all, I'm afraid it's impossible for your query to run because the syntax is wrong. The correct way to write it is:
SELECT *, SUM(trans.cantidad) as cantidad
FROM productos AS p
LEFT JOIN transferencias AS trans
ON p.upc = trans.upc
WHERE trans.sucursal_clave_destino = 10 AND trans.sucursal = 10
First approach
I assume you have created your model in this manner: http://framework.zend.com/manual/1.12/en/learning.quickstart.create-model.html
For example, in your Default_Model_ProductosMapper:
function getXXXX(){
$select = "[THE ABOVE QUERY]";
$result = $this->getDbTable()->getAdapter()->fetchAll($select);
return $result;
}
This is the most basic approach.
Second approach
By using Zend_Db functions, which is like prepare statement in database concept. Only use it to increase safety if you are passing parameters from user input (see SQL injection), otherwise it's safe to use the first approach.
Still, in your mapper:
function getXXXX(){
$query = $this->getDbTable()->getAdapter()->select();
$query->from('productos', array());
$query->joinLeft('transferencias', 'productos.upc = transferencias.upc', array('SUM(trans.cantidad) as cantidad));
$query->where("trans.sucursal_clave_destino = 10");
$query->where("trans.sucursal = 10");
// get result
$stmt = $this->getDbTable()->getAdapter()->query($query);
$result = $stmt->fetchAll();
return $result;
}
Third approach
If you are using Database ORM like Doctrine2, you can also write SQL or DQL (Doctrine Query Language) queries, which syntax is highly similar with SQL queries but absolutely NOT the same mechanism. The document is here. This document covers both approaches above for DQL and also will tell you where to put them.

How to set sql_mode in Zend Framework 2?

I'm currently having an issue with pagination in Zend Framework 2.
This code
public function findAllByCriteria(CourseSearchInput $input) {
$concatDelimiter = self::CONCAT_DELIMITER;
$select = new Select();
$where = new Where();
$having = new Having();
$select->columns(array(
'id', 'title', 'description'
));
$select->from($this->tableGateway->getTable());
$select
->join('coursedata', 'courses.id = coursedata.id', array(
'relevance' => $this->buildRelevanceExpressionFromCriteria($input)
))
;
$having
->greaterThanOrEqualTo('relevance', self::RELEVANCE_MIN);
;
$select->where($where, Predicate::OP_AND);
$select->having($having);
$select->group(array('courses.id'));
$dbAdapter = $this->tableGateway->getAdapter();
// $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');
$adapter = new \Zend\Paginator\Adapter\DbSelect($select, $dbAdapter);
$paginator = new \Zend\Paginator\Paginator($adapter);
return $paginator;
}
create this SQL:
SELECT
`courses`.`id` AS `id`,
`courses`.`title` AS `title`,
`courses`.`description` AS `description`,
MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
GROUP BY `courses`.`id`
HAVING `relevance` >= '3'
It ueses the MySQL Extensions to GROUP BY and cannot be executed, if the sql_mode is set to ONLY_FULL_GROUP_BY. So, I tried to reset the sql_mode before the statement is executed (see the commented out line above: $dbAdapter->getDriver()->getConnection()->execute('SET sql_mode = "";');). But it didn't worked. So, how can I set the sql_mode in order to execute my non-standard SQL?
This may not be the answer to the question you are asking, but I can see you are going to have an issue with your query regardless when using Paginator.
The DbSelect Adapter for the Paginator doesn't like the aggregate function in there (Group By)
The Paginator will try and use your query to build it's own query to calculate the "count" for items in the collection. This is broken due to you using an aggregate in your query, any groups etc will break the adapter.
if you check the default implementation you will see:
/**
* Returns the total number of rows in the result set.
*
* #return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
$select = clone $this->select;
$select->reset(Select::COLUMNS);
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
// This won't work if you've got a Group By in your query
$select->columns(array('c' => new Expression('COUNT(1)')));
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$row = $result->current();
$this->rowCount = $row['c'];
return $this->rowCount;
}
this doesn't like when you are using Group BY and will give back incorrect results.
You can create your own adataper, and extend the existing DbSelect and override the count method when you are planning to use Group BY;
Off the top of my head something like this should work, but may not be the most efficient way of doing it
/**
* Returns the total number of rows in the result set.
*
* #return integer
*/
public function count()
{
if ($this->rowCount !== null) {
return $this->rowCount;
}
/**
* If the query hasn't got 'GROUP BY' just try and use the old method
*/
$stateGroup = $this->select->getRawState('group');
if( ! isset($stateGroup) || empty($stateGroup)) {
return parent::count();
}
$select = clone $this->select;
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$this->rowCount = $result->count();
return $this->rowCount;
}

Zend DB Select : ORDER BY FIELD('id',some_array) - how?

How would you write the following query in Zend framework?
SELECT * FROM table_name ORDER BY FIELD(field_name, 'Small','Medium','Large');
I just need the "Order by" part :)
Thanks!
What about this:
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select();
$select->from('table_name')
->order(new Zend_Db_Expr("FIELD(field_name, 'Small','Medium','Large')"));
var_dump($select->assemble());
Results in:
string 'SELECT `table_name`.* FROM `table_name` ORDER BY FIELD(field_name, 'Small','Medium','Large')' (length=92)
$select->order(new Zend_Db_Expr('FIELD(field_name, 'Small','Medium','Large')'));
I think you should do:
$db = Zend_Db::factory( ...options... );
$select = $db->select()
->from(table_name)
->order(new Zend_Db_Expr("FIELD(field_name, 'Small','Medium','Large')")));