How to get the last generated value for a custom PRIMARY KEY column in ZF2? - zend-framework2

With Zend\Db\Adapter\Driver\ResultInterface#getGeneratedValue() Zend\Db provides a simple way to get the ID of the last INSERTed entry, e.g.:
$action = new Insert('my_table');
$action->values($data);
$sql = new Sql($this->dbAdapter);
$statement = $sql->prepareStatementForSqlObject($action);
$result = $statement->execute();
$newId = $result->getGeneratedValue();
But it seems only to work, if the PRIMARY KEY column calls "id". How to retrieve the generatedValue for a PRIMARY KEY defined on another column?

Preferably use Zend\Db\TableGateway\TableGateway offering the method getLastInsertValue().
use Zend\Db\TableGateway\TableGateway;
$myTable = new TableGateway('my_table', $this->dbAdapter);
$action = new Insert('my_table');
$action->values($data);
$myTable->insertWith($action);
$newId = $myTable->getLastInsertValue();

$this->dbAdapter->getDriver()->getLastGeneratedValue();

Related

How to use having() in tableGateway in ZF2

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);

zf2 select columns from joined tables - how?

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;

ZF2 - retrieving bottom row id from table

I am trying to retrieve the latest entered if from the 'order' table within my database.
I'm currently trying to use the following method:
public function getLatestOrderId()
{
$adapter = $this->adapter;
$sql = new Sql($adapter);
$select = $sql->select();
$select->columns(array('id' => 'orderId'));
$select->from('order');
$select->order('orderId DESC');
$select->limit(1);
$statement = $sql->prepareStatementForSqlObject($select);
$statement->execute();
}
I have a feeling that this should be working. I am then accessing this method in the controller like so:
$orderId = $this->getOrderTable()->getLatestOrderId();
I have realised that at present the getLatestOrderId method does not actually return anything e.g. return $statement->execute();. This is because I receive an error saying that the sql result could not be converted to a string.
I'm insure what is going wrong, so any help would be much appreciated.
Thank you.

how to execute MYSQL stored procedure in zend framework 2 with multiple result set

How to execute MYSQL stored procedure in zend framework 2 with multiple result set means if sp have multiple select query then how can i get all the result in array and how i pass dynamic value in sp for insert and update data in table.
thanks..
I recently wrote a small article about this. The solution I found is not a generic one and assumes that you are using PDO. I am not sure whether it works with other databases than MySQL. It is possible that there is a better and more generic way of doing this that I am not aware of.
$driver = $this->dbAdapter->getDriver();
$connection = $driver->getConnection();
$result = $connection->execute('CALL sp_get_profile_for_display (123)');
$statement = $result->getResource();
// Result set 1
$resultSet1 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet1 as $row) {
$something = $row->some_column;
}
// Result set 2
$statement->nextRowSet(); // Advance to the second result set
$resultSet2 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet2 as $row) {
/* Do something */
}
// Result set 3
$statement->nextRowSet(); // Advance to the third result set
$resultSet3 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet3 as $row) {
/* Do something */
}
Replace the 123 with the data you wish to pass to the stored procedure as a parameter. If using user supplied data, remember to escape it to prevent SQL injection!

How to create foreign key relationships with the Entity Framework?

I want to create a new row in my database on a table that has a couple of foreign key relationships and I haven't been able to get a handle on what order and what calls need to be made. This is what I have so far:
db.Models.Order order = DB.Models.Order.CreateOrder( apple );
order.CustomerReference.Attach( ( from c in db.Customer where c.Id == custId select c ).First() );
db.SaveChanges();
The code is failing on the second line there, saying:
Attach is not a valid operation when
the source object associated with this
related end is in an added, deleted,
or detached state. Objects loaded
using the NoTracking merge option are
always detached.
Any ideas?
(Thanks John for the grammar fixes)
So I figured it out. This is what you have to do:
db.Models.Order order = DB.Models.Order.CreateOrder( apple );
order.Customer = (from c in db.Customer where c.Id == custId select c).First();
db.SaveChanges();
I hope that helps people.
Why not use entity references? Your method will cause an extra SELECT statement.
A much nicer way is to use the CustomerReference class and an EntityKey.
order.CustomerReference = new System.Data.Objects.DataClasses.EntityReference<Customers>();
order.CustomerReference.EntityKey = new EntityKey("ModelsEntities.Customers", "Id", custId);
For update here is some sample code:
using (var ctx = new DataModelEntities())
{
var result = (from p in ctx.UserRole.Where(o => o.UserRoleId == userRole.UserRoleId)
select p).First();
result.RolesReference.EntityKey = new EntityKey("DataModelEntities.Roles",
"RoleId", userRole.RoleId);
result.UserRoleDescription = userRole.UserRoleDescription;
ctx.SaveChanges();
}

Resources