I would like mapping a sql-view with Doctrine2.
This view is a TempTable containing some statistics that would show without rewriting the sql that generates the view
I try to map like a table, but updating schema drop the view and create a table
I try also with NativeSQL...
public function getMessages(\Project\Bundle\MyBundle\Entity\User $user) {
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addEntityResult('MessageCenter', 'v');
$rsm->addFieldResult('v', 'user_id', 'user_id');
$rsm->addFieldResult('v', 'tot', 'tot');
$rsm->addFieldResult('v', 'read', 'read');
$rsm->addFieldResult('v', 'to_read', 'to_read');
$rsm->addFieldResult('v', 'stored', 'stored');
$rsm->addFieldResult('v', 'spam', 'spam');
$q = "SELECT * FROM message_stats_view WHERE user_id = ?";
$rsm = new \Doctrine\ORM\Query\ResultSetMapping;
$query = $this->getEntityManager()->createNativeQuery($q, $rsm);
$query->setParameter(1, $user->getId());
echo $query->getSQL();
var_dump($query->execute());
exit;
}
I create the entity MessageCenter with getter and setter, but my output is:
SELECT * FROM message_stats_view WHERE user_id = ?
array
empty
(Answered by the OP in aq question edit. Transcribed to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
I SOLVED!!!!
public function getCentroMessaggi(\Project\Bundle\MyBundle\Entity\User $user) {
$connection = $this->getEntityManager()->getConnection();
$q = "SELECT * FROM message_stats_view WHERE user_id = :id";
$stmt = $connection->executeQuery($q, array('id' => $user->getId()));
return $stmt->fetch();
}
This return an array. PERFECT!
Related
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;
}
How to use having() clause in ZF2?
There is almost no examples on the web how to prepare correct select object with having.
I have query like:
SELECT root_schema_id as `schema_id`
FROM `standard_specific_root_schemas`
WHERE `vehicle_id` IN (".implode(",",$vehiclesIds).")
GROUP BY `schema_id`, rootSubGroup_id HAVING count(*)=".$noOfVehicles
And I'm trying to run it in ZF2:
public function getVehicleWithinCommonRootSubgroupInSpecific($vehiclesIds)
{
$where = new Where();
$where->in('vehicle_id', $vehiclesIds);
$having = new Having('count(*) = '.count($vehiclesIds));
$rowset = $this->tableGateway->select(function (Select $select) use ($where, $having) {
$select
->where($where)
->having($having);
});
if (!$rowset) {
throw new \Exception("Could not find schemas for group $groupId");
}
return $rowset;
}
Of course that part in ZF2 is not finished yet as I wanted to check if it's working first.
I've tried few ways of providing params to having method but everything generates errors.
Help please, I'm desperate...
I cannot test your query, but can try and reproduce the query you need.
I adjusted the having to use ->expression() instead of a variable via the construct.
I also added the group statement.
To view the query I added a var_dump:
$where = new \Zend\Db\Sql\Where();
$where->in('vehicle_id', $vehiclesIds);
$having = new \Zend\Db\Sql\Having();
$having->expression('count(*) = ?', count($vehiclesIds));
$rowset = $this->tableGateway->select(function (\Zend\Db\Sql\Select $select) use ($where, $having) {
$select
->where($where)
->group(array('schema_id', 'rootSubGroup_id'))
->having($having);
var_dump( $select->getSqlString() );
});
Let me know if this helps.
To circumvent the error mentioned in the comments you would have to do something like below:
$sql = $this->tableGateway->getSql();
$select = $sql->select();
$where = new \Zend\Db\Sql\Where();
$where->in('vehicle_id', $vehiclesIds);
$having = new \Zend\Db\Sql\Having();
$having->expression('count(*) = ?', count($vehiclesIds));
$select
->where($where)
->group(array('schema_id', 'rootSubGroup_id'))
->having($having);
$preparedQuery = $sql->prepareStatementForSqlObject($select);
var_dump( $preparedQuery->getSql() );
However, if I'm right, the tableGateway does this for you so the error should go away once you start using the select to query the database.
Also, you can use the above to do that too, just replace this:
$preparedQuery = $sql->prepareStatementForSqlObject($select);
var_dump( $preparedQuery->getSql() );
With:
$this->tableGateway->selectWith($select);
I have trouble creating a CdbCriteria with nested join. Here's the code in model (sorry it's in Indonesian. Hopefully anyone can understand the query):
public function report() {
$criteria=new CDbCriteria;
$criteria->alias = "p";
$criteria->select = "p.tanggal_transaksi,
MONTH( p.tanggal_transaksi ) AS bulan,
p.kode,
p.kode_supplier,
s.nama,
d.kode_bahan_baku,
b.nama_barang,
d.jumlah_kg,
d.jumlah_cones,
d.harga_satuan,
d.harga_satuan * d.jumlah_cones AS total,
FLOOR(d.harga_satuan * d.jumlah_cones * p.ppn / 100) AS ppn,
(d.harga_satuan * d.jumlah_cones) + FLOOR(d.harga_satuan * d.jumlah_cones * p.ppn / 100) AS total_akhir
";
$criteria->join = "JOIN m_supplier s ON s.kode = p.kode_supplier
RIGHT JOIN t_pembelian_detail d ON d.kode_pembelian = p.kode
JOIN m_bahan_baku b ON b.kode = d.kode_bahan_baku
";
$criteria->together = TRUE;
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
The name of the model is TPembelian and here is the relation:
public function relations()
{
return array(
'supplier' => array(self::BELONGS_TO, 'MSupplier', 'kode_supplier'),
'tPembelianDetails' => array(self::HAS_MANY, 'TPembelianDetail', 'kode_pembelian'),
);
}
In a controller, I wrote these lines of codes to just simply print out each attributes of CActiveDataProvider:
$model = new TPembelian('search');
$dataProvider = $model->report();
foreach ($dataProvider->getData() as $data) {
echo "<pre>".print_r($data->attributes, 1)."</pre>";
}
the problem is, it only prints out the attributes from TPembelian model (which use alias "p"). Why are other attributes (with other alias beside "p") not printed?
I have searched for a while and it appears that CActiveDataProvider not returning one long query, but instead it returns many query with HAS_MANY relation. Someone said to use "together" and set it to TRUE (I wrote it already in the code above) to make it returns one long query, but it's still not working. Can anybody please help me?
Note:
in the first code, m_supplier, t_pembelian_detail, and m_bahan_baku are tables, not models
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've an existing project in Symfony 1.4/Propel 1.4
For database optimization purpose, I created a view of few tables. The function/ view query are as follow:
create function getPlayer() returns INTEGER DETERMINISTIC NO SQL return #getPlayer;
create view getPlay as
SELECT
CASE WHEN play.hiderid = getPlayer() THEN play.seekerid ELSE play.hiderid END AS opponent, play . *
FROM odd_play play, odd_match mat
WHERE (seekerid = getPlayer() OR hiderid = getPlayer())
AND play.id = mat.latestplay;
After creating above view, I can write following simple SQL query to get required data effectively.
select play.*
from (select #getPlayer:=1 p) p, getPlay play;
Now the problem is that, how to write this query in Symfony/Propel 1.4. Can someone please suggest how to write that query in propel 1.4?
Edit after J0K comments
I'm trying following
class GetplayPeer extends BaseGetplayPeer {
static public function getOpponents($player){
$con = Propel::getConnection();
$sql = "select play.* from (select #getPlayer:=:player p) ply, getPlay play;";
$stmt = $con->prepare($sql);
$stmt->bindParam(":player",&$player,PDO::PARAM_INT);
$rs = $stmt->execute();
//$opponents = GetplayPeer::populateObjects($rs);
echo "opponents=<pre>";print_r($rs);exit;
}
} // GetplayPeer
I'm getting 1 as output, which is not expected output.