I'm new to ZF2.
How can I write a query like this?
SELECT * FROM users WHERE id = 1 AND status != 2
My code Model:
public function getUser($where = array())
{
$select = $this->sql->select();
$select->from(self::TABLE);
$select->where($where);
$select->order('name ASC');
return $statement->execute();
}
I am using: Zend\Db\Sql
Thanks.
Look at the docs here.
So $where can be a string or Closure, too.
Call it in your case like:
$user = $object->getUser('status != 2');
Oh, I missed the first condition:
$user = $object->getUser(array('id = 1', 'status != 2'));
EDIT:
You can for sure leave the = array() default value. I don't know why but I confused it with type hinting. (array $where)
public function getUser( where = array() ) {
$select = $this->sql->select();
$select->from(self::TABLE);
$select
->where->nest()
->equalTo( 'id' => where['id'] )
->or
->notEqualTo( 'status' => where['status'] )
->unnest();
$select->order('name ASC');
return $statement->execute();
}
use like this:
getUser( array(
'id' => 1,
'where' => 2,
) );
Related
Is there an elegant way to squash these two statements into one, similar to a plain SQL INSERT INTO t1 SELECT 'something', t2.x FROM t2 WHERE ...?:
const commentIds: Array<Pick<SectionComment, 'id'>> =
await this.articleRepository
.createQueryBuilder('article')
.select('sectionComment.id', 'id')
.innerJoin('article.sectionComments', 'sectionComment')
.where(
'article.vaultId = :vaultId and article.valueId = :valueId and sectionComment.userId = :userId',
{
valueId,
vaultId,
userId,
}
)
.getRawMany();
if (commentIds.length) {
await this.userSectionReadRepository
.createQueryBuilder()
.insert()
.into(UserSectionRead)
.values(
commentIds.map((sectionComment) => ({
userId,
commentId: sectionComment.id,
}))
)
.orIgnore()
.execute();
}
The problem is the values() method in InsertQueryBuilder does not accept a subquery function (qb: this) => string like the where() method does.
i am unable to fit my query into zf2 query, i can fit simple join query but i can not write for more complex sub queries.
please help me to do this.
SELECT `created_date` FROM `salesmodule_discussed_topic` dt WHERE dt.`meeting_id` IN(
SELECT ma.`meeting_id` FROM `salesmodule_meeting_agent` ma WHERE ma.`agent_id`=30547
)
public function getLastmeetingdate() {
$select = new Select();
$select->from(array('dt' => 'salesmodule_discussed_topic'));
$select->columns(array('created_date'));
$select->where(array('ma.`agent_id` => 30547));
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet->buffer();
}
The previous example is bad because has an sql injections. You need make a subquery using Select.
public function getLastmeetingdate() {
$subQuery = new Select();
$subQuery->from(array('ma' => 'salesmodule_meeting_agent'));
$subQuery->columns(array('meeting_id'));
$subQuery->where(array('ma.agent_id' => 30547));
$select = new Select();
$select->from(array('dt' => 'salesmodule_discussed_topic'));
$select->columns(array('created_date'));
$select->where->in('dt.meeting_id', $subQuery);
return $this->tableGateway->selectWith($select);
}
public function fetchAllSubQuery($id = '') {
$columns = array("*");
$where = "main_booking_id IN (SELECT
b1.`main_booking_id`
FROM
`booking_sector` b1
WHERE b1.`connected_booking_id` = '$id' OR b1.`main_booking_id` = '$id') ";
$resultSet = $this->tableGateway->select(function (Select $select) use ($where,$columns) {
$select->where($where);
$select->columns($columns);
});
$resultSet->buffer();
// $resultSet->next();
return $resultSet;
}
I just want to return one column (per.cd_acao), so I tried something like:
$select->from(array('act' => 'tb_acao'))
->join(array('per' => 'tb_perfil_acao'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
$select::JOIN_INNER
);
but this is producing a query string like:
SELECT "act".*, "per"."cd_acao" AS "cd_acao" FROM "tb_acao" AS "act" INNER JOIN "tb_perfil_acao" AS "per" ON "per"."cd_acao" = "act"."cd_acao" WHERE "per"."sq_perfil" = '89'
it is bringing all columns from the first table, when I want none. What am I missing here?
Update
summarizing: When I don't inform 'columns' in a select object, it defaults to return all columns to me. But when I'm joining, I don't want any columns to be returned by the first table.
An empty array will suffice
$select->from(array('act' => 'tb_acao'))
->columns(array())
->join(array('per' => 'tb_perfil_acao'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
$select::JOIN_INNER
);
Try with this query
use Zend\Db\Sql\Sql;
protected $tableGateway;
public $adapter;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
publice function getData(){
$adapter = $this->tableGateway->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select();
$select->from('tb_acao')
->join('per'),
'per.cd_acao = act.cd_acao',
array('cd_acao'),
);
$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();
return $results;
}
I feel like I must me missing something very simple. It's a very simple task, all I want to do is get something like:
SELECT * FROM lookup_items
JOIN lookup ON lookup_items.lookup_id = lookup.id
This returns all the columns for all the joined tables, in regular SQL. Here's my attempt in zf2:
$select = new Select();
$select->from('lookup_items');
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
The result set only includes the columns in 'lookup_items'. I've tried various ways to get the 'lookup' columns, including:
$select->columns(array('lookup_items.*', 'lookup.*'));
But they all just blow up. Surely there's a way to do this, and it's just so simple I'm missing it completely.
I thought a simple example would be avoid confusion, but here's more code:
class LookupItemsTable extends AbstractTableGateway
{
public function getList($resource)
{
$system_name = str_replace('*', '%', strtoupper($resource));
$joinTable = 'lookup';
$select = new Select();
$select->from($this->table);
$select->join($joinTable, "{$this->table}.lookup_id = {$joinTable}.id");
$where = array();
$where[] = "{$this->table}.enabled is true";
$where[] = "{$joinTable}.enabled is true";
$where[] = "UPPER({$joinTable}.system_name) ilike '{$system_name}'";
$select->where($where);
$sort[] = 'sort_order ASC';
$sort[] = 'value ASC';
$select->order($sort);
$rowset = $this->selectWith($select);
return $rowset;
}
}
Where:
$resource = $this->params()->fromRoute('resource', 'BUSINESS');
And $this->table is 'lookup_items'. Really all I want to do is get columns from both joined tables. I guess there's a zf2 way to just make a straight SQL statement without all the OO falderal, so I could just force it that way. But I'd rather work within the framework as much as possible.
Just change this line
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
to
$select->join('lookup', 'lookup_items.lookup_id = lookup.id', array('lookupcol1', 'lookupcol2');
Raj answer is the best one but it only works if you don't forget to add these fiels in your LookupItems model.
class LookupItems
{
// Your lookup_items fields here...
...
// And the added lookup fields here, the ones you add in the array
public $lookupcol1;
public $lookupcol2;
And in the exchangeArray method :
public function exchangeArray($data)
{
// .... your fields, and the new ones
$this->lookupcol1 = (! empty($data['lookupcol1'])) ? $data['lookupcol1'] : null;
$this->lookupcol2 = (! empty($data['lookupcol2'])) ? $data['lookupcol2'] : null;
}
I figured it out.
Added this:
$select->columns(array('*'));
And then this near the end:
$sql = new Sql($this->adapter);
$statement = $sql->prepareStatementForSqlObject($select);
$rowset = $statement->execute();
This returns the expected result, with the caveat that now my rows are returned as associative arrays instead of objects.
This is how you can create queries with join in zf2.
$resultSet = $this->select(function (Select $select) {
// omit the table name
//$select->from('foo');
$select->join('users', "users.id foo.createdby", 'firstname', '');
$select->order('id ASC');
// echo $select->getSqlString();// to print your query
});
$entities = array();
foreach ($resultSet as $row) {
$entity = new Entity\Foo();
$entity->setId($row->id)
->setFullname($row->fullname)
->setCaseid($row->caseid)
->setTestimonial($row->testimonial)
->setSortorder($row->sortorder)
->setActive($row->active)
->setCreated($row->created)
->setModified($row->modified)
->setFirstname($row->firstname)
->setCreatedby($row->createdby);
$entities[] = $entity;
}
return $entities;
I need to make a "not like" operation in a where. I know that i can do this:
$predicate->like($a,$b);
But i can't find a way to perform a "not like" and other negated like "not in". Is there any way or i will have to make string where?
Thanks.
As you mention there is no notLike method on where object. But there is literal method where you can pass anything you want:
$sql = new Sql($adapter);
$select = $sql->select();
$select->from('foo')
->where->literal('NOT LIKE ?', array('bar'));
echo $select->getSqlString();
The output wille be:
SELECT "foo".* FROM "foo" WHERE NOT LIKE 'bar'
For reference to those who want to add the Object method of notLike() instead of using literal()
$predicate->notLike( $a, $b );
Create ZF2/Db/Sql/Predicate/NotLike.php
namespace Zend\Db\Sql\Predicate;
class NotLike extends Like {
protected $specification = '%1$s NOT LIKE %2$s',
}
In ZF2/Db/Sql/Predicate/Predicate.php add
public function notLike( $identifier, $like ) {
$this->addPredicate( new NotLike( $identifier, $like ), ($this->nextPredicateCombineOperator) ? : $this->defaultCombination );
$this->nextPredicateCombineOperator = null;
return $this;
}
Test
$select = new Select;
$select->from( 'dbTable' )
->columns( array() )
->where->notLike( 'column', '%test%' );
echo $select->getSqlString();