I need last insert id after executing a insert statement. Now I am not using TableGateway so $this->lastInsertValue is not available to me. What other options are available if I need to use Insert statement through Sql Object not a Table Gateway Object.
$objInsert = new Insert('name_master');
$objInsert->values(array( 'username' => $name,
'price' => 0,
'is_approval_needed' => 'n'
));
$sql = new Sql($this->adapter);
$result = $sql->prepareStatementForSqlObject($objInsert)->execute()->getAffectedRows();
As I need to execute multiple insert statements in different tables using last insert id of previous insert, Now I want to do it in a single method of my Model.
The Zend\Db\Adapter\Driver\DriverInterface specifies a getLastGeneratedValue() method, so presumably this should work...
$lastId = $this->adapter->getDriver()->getLastGeneratedValue();
$dbAdapter = $this->tableGateway->adapter;
$lastId = $dbAdapter->getDriver()->getConnection()->getLastGeneratedValue();
Related
I was trying to search for information, but so far cannot see. Also checked in the documentation but did not see.
https://framework.zend.com/manual/2.2/en/modules/zend.db.table-gateway.html
So are my queries safe? For example
$rowset = $this->tableGateway->select(['email' => $email]);
Yes it does.
You can try the following code to check if the generated SQL statement is safe.
$sql = $this->tableGateway->getSql();
$select = $sql->select()->where(array("email" => $someDirtyInputHere));
// you can execute the query using $this->tableGateway->selectWith($select);
// output query
echo $sql->getSqlStringForSqlObject($select);
exit;
I have this, but it loads each and every ebay row individually, generating thousands of SQL statements:
$products = \app\models\Product::find()
->joinWith('ebay', false, 'inner join')
->indexBy(function($row){return $row->ebay->epid;})
->all();
I tried this, but it gave an error: 'Getting unknown property: app\models\Product::ebay.epid'
$products = \app\models\Product::find()
->joinWith('ebay', false, 'inner join')
->indexBy('ebay.epid')
->all();
Setting eager loading = true doesn't help either. It still loads each row individually then loads them again at the end.
How can I efficiently join a table in Yii and index by a value in the joined table?
You won't be able to do it with indexBy. However, ArrayHelper::index can index an array on a related model field. So here's how it can be done:
$products = \app\models\Product::find()
->with('ebay')
->all();
ArrayHelper::index($products, 'ebay.epid');
The code will run two queries, one to get all products, one to get all related ebay products. Then the array will be indexed with no DB queries at all.
I ended up doing it manually for a subset of the ids and it only uses 2 queries. I'd still be interested in the indexBy though.
$products = Product::find()->joinWith('ebay', true, 'inner join')->where(['ebay.epid' => $productIds])->all();
$ebayProducts = array();
foreach ($products as $p) {
$ebayProducts[$p->ebay->epid] = $p;
}
If you want index by relation recods via joinWith() or with() results you can use following:
->with(['relationName' => function($q) {
$q->indexBy('field_name');
}])
When adding $select->order(...) to a previously combined Select in Zend Framework 2 the "order by" will only be added to the first Select statement.
SELECT `user`.*
FROM `user` WHERE `user_id` = :where1
ORDER BY `starttime_dt` ASC )
UNION
( SELECT `user`.*
FROM `user`
WHERE `user_id` != :subselect1where1 )
What I need is that the sorting will be applied to the full Select. A solution is already described here
https://github.com/zendframework/zf2/issues/5162#issuecomment-36294281
But this solution works with an SQL-Adapter.
How can I do that with a Table Gateway?
My code looks currently like this (resulting to the above statement)
$select = $this->tableGateway->getSql()->select();
$select2 = clone $select;
$select->where->equalTo('user_id', $user_id);
$select2->where->notEqualTo('user_id', $user_id);
$select->combine($select2);
$select->order('starttime_dt');
$resultSet = $this->tableGateway->selectWith($select);
You would do it with table gateway the same way it was illustrated in the link you provided.
Your code would look like
$select = $this->tableGateway->getSql()->select();
$select2 = clone $select;
$select->where->equalTo('user_id', $user_id);
$select2->where->notEqualTo('user_id', $user_id);
$select->combine($select2);
$combinedSelect = (new Zend\Db\Sql\Select)->from(['sub' => $select])->order('starttime_dt');
$statement = $this->sql->prepareStatementForSqlObject($combinedSelect);
$result = $statement->execute();
$resultSet = clone $this->resultSetPrototype;
$resultSet->initialize($result);
You wouldn't be able to use the TableGateway's selectWith method because it's going to check that the provided Select's table matches the TableGateway's table.
I have two relation table "demande" and "reponse" which are linked and I'd like to retrieve all the lines of "demande" not in "reponse".
I try this with a join :
$select = new Select ();
$select->columns(array("id"));
$select->from ("demande" );
$select->where->lessThan("dateArretMarche",$stringDate );
$select->join(
array("rep" => 'reponse'), // table name,
'demande.id = rep.id_demande',array(),
$select::JOIN_RIGHT);
$select ->where->isNull("rep.id");//<== it doesn't work
But I can't select "null" lines".
I guess it's possible with "not in" but Zend Framework provide only "in" predicate.
Thank all.
What if you just include it in the query? Like this:
$select ->where('rep.id IS NULL');
If you want to use isNull condition.So do you need to use with Predicate.Try with following code.
$select->where(array(
new \Zend\Db\Sql\Predicate\IsNotNull("rep.id")
)
);
I am trying to make following query in Propel:
$criteria = new Criteria();
$criteria->clearSelectColumns();
$criteria->addSelectColumn(TableName::COLUMN1)
->addSelectColumn(TableName::COLUMN2)
->addAsColumn('alias1', 'DATE('.TableName::INIT_TIME.')')
->addAsColumn('alias2', 'COUNT('.TableName::DOWNLOAD_START_TIME.')')
->addGroupByColumn('DATE('.TableName::INIT_TIME.')')
->addGroupByColumn(TableName::DOWNLOAD_START_TIME);
$logs = TableName::doSelect($criteria);
It seems that everything OK and according to MySQL log file query generated and saved to server right. However I cannot get values of aggregated columns.
doSelect returns array of TableName objects which have no methods to fetch aggregated columns. So, how can I do it?
PS: I am talking about symfony 1.4 with Propel if it matters.
You should avoid the use of Criteria, use the ModelCriteria API instead (documentation available at: http://www.propelorm.org/reference/model-criteria.html)
The following query:
<?php
$criteria = new Criteria();
$criteria->clearSelectColumns();
$criteria->addSelectColumn(TableName::COLUMN1)
->addSelectColumn(TableName::COLUMN2)
->addAsColumn('alias1', 'DATE('.TableName::INIT_TIME.')')
->addAsColumn('alias2', 'COUNT('.TableName::DOWNLOAD_START_TIME.')')
->addGroupByColumn('DATE('.TableName::INIT_TIME.')')
->addGroupByColumn(TableName::DOWNLOAD_START_TIME);
$logs = TableName::doSelect($criteria);
Can be rewritten as below:
$query = TableNameQuery::create()
->select(array('Column1', 'Column2'))
->withColumn('DATE(InitTime)', 'alias1')
->withColumn('COUNT(DownloadStartTime)', 'alias2')
->groupBy('alias1')
->groupByDownloadStartTime()
;
$logs = $query->find();
Note you won't select both columns alias1 and alias2 as you didn't add them to the selected columns in your code. You can do that by adding the two alias to the select() clause:
->select(array('Column1', 'Column2', 'alias1', 'alias2'))
I used this snippet to retrieve and fetch data when I followed this same approach, but selecting only one column in my criteria through addSelectColumn:
$logs = TableName::doSelectStmt($criteria);
$data = $logs->fetchAll(PDO::FETCH_COLUMN, 0);
I hope this can help you.
My method is to make a query and iterate through a recordset. As suggested I use FETCH_BOTH to get array positions, but names as well. I take those values and hydrate my object, but also manually populate the properties of the object that are meant to hold the aggregate values. I pass those objects back to my application and use them as normal objects would be used in my view.
$stmt = self::doSelectStmt($c);
// empty array for now
$results = array();
// lets iterate through this
while($row = $stmt->fetch(PDO::FETCH_BOTH)) {
// we need to create a new object
$division = new Division();
// and we'll hydrate each row turning into an object so we can use it easily
$division->hydrate($row);
// now here's the magic, this object did not exist from our tables, we'll fix that
$division->setNumPlayers($row['num_players']);
$division->setNumTeams($row['teams']);
// set the output object
$results[] = $division;
}
return $results; // array of objects including aggregate values