Understanding issue get one row from database with 2 parameters - zend-framework

I thought it would work find, but it doesn't.
I have a method in my modelclass like this:
public function getUnitbyName2($unitname, $ProjectID)
{
//$id = (int) $id;
$rowset = $this->tableGateway->select(['Unitname' => $unitname], ['ProjectID' => $ProjectID]);
$row = $rowset->current();
if (! $row) {
// throw new RuntimeException(sprintf(
// 'Could not find row with identifier %d',
// $unitname
// ));
$row=0;
}
return $row;
}
If I give an existing unitname and a non existent project_ID I expect to get some 0 value. But I always get the number of the unit in the first project with the given unitname. It is common that the unitname exists in several different projects.
The function is supposed to get the right record if exist using both parameters.
My question is, what's wrong with using 2 parameters connected by AND?

AbstractTableGateway::select() accepts one argument, you are passing 2:
You need to pass 1, combine the 2 arrays.
Change your code to:
$rowset = $this->tableGateway->select(['Unitname' => $unitname, 'ProjectID' => $ProjectID]);
Zend table Gateways

Related

Zend Tutorial: Difficult to find row 1

I am trying to follow the tutorial https://framework.zend.com/manual/2.4/en/user-guide/database-and-models.html
I have the problem, that i can't use the getAlbum(1) function.
It is possible to fetchAll() -> All rows returned
If I want to use getAlbum($personalnummer) -> Could not find row 1
Yes, there is an entry with Personalnummer 1 in the database and it is type int. The only difference is that, I use a Microsoft SQL Server, but the Configuration is right because all rows could be returned.
Any ideas?
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function getAlbum($personalnummer)
{
$personalnummer = (int) $personalnummer;
$rowset = $this->tableGateway->select(array('Personalnummer' => $personalnummer));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $personalnummer");
}
return $row;
}
try this if it helps replace
$rowset = $this->tableGateway->select(array('Personalnummer' => $personalnummer));
with this
$where = new \Zend\Db\Sql\Where();
$where->equalTo('Personalnummer', $personalnummer);
$rowset = $this->tableGateway->select($where)

association where clause with array cakephp 3

Basically what i want to do is write this query with cakephp 3 query builder :
SELECT * FROM question as q innerjoin answers as a where q.question = $question AND a.id NOT IN = $avoidedIDs
codes for table class
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use App\Model\Entity\Comlib;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Validator;
use Cake\ORM\TableRegistry;
class ComlibsTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('questions');
// join the tables
$this->hasMany('Answers' , [
'foreignKey' => 'question_id'
]);
}
public function LFA( $live_req) {
$query = $this->find()->where(['question' => $live_req])->contain(['Answers'])->LIMIT(6);
$query = $query->toArray();
//include 5 answer
return $query;
}
public function LFM($theid , $avoidedIDs, $question )
{
$query = $this->find()->where(['question' => $question])->contain(['Answers' => function($q){
return $q
->where(['Answers.id NOT IN' => $avoidedIDs] );
}
]);
$query = $query->toArray();
debug($query);
return $query;
}
}
the error that i get is : Impossible to generate condition with empty list of values for field (Answers.id).
but when i print_r($avoidedIDs) i get the values that i passed so im sure that $avoidedIDs is not empty , at least not out of contain function and thats what makes it more complicated for me, but when i put ONE number instead of my variable it will execute , if i put 1,2,3,4 still it will execute only the first one!
what am i doing WRONG for the past 2 days ?????
tnx for any help
It is because you are trying to use $avoidedIDs in an anonymous function (Closure) call, which is not available there.
You should make it available for the function.
->contain(['Answers' => function($q) use ($avoidedIDs){..}
Closures may also inherit variables from the parent scope. Any such
variables must be passed to the use language construct.
http://www.php.net/manual/en/functions.anonymous.php

Symfony 2.4.1 and Doctrine 2 dates interval query

I have two tables: Empleado and Fichaje in a (1..*) relationship.
I created a query builder for getting fichajes corresponding to IdEmpleado (key) property in Fichaje.
I attempt to filter those Fichajes, but it never works. So I've searched for any clear example of dates in Doctrine for this basic case in vane.
The query result is empty always. No error is thrown.
If I check for IdEmpleado parameter only it gives me all the available records.
The dates interval is the problematic one.
Note: I checked this similar post
Here is the table data, I'm quite convinced of the dates availability.
This is my function:
public function empleadoAction(Request $request){
...
$repository = $em->getRepository('ZkTimeBundle:Fichaje');
$fichajes = $repository->FindByEmpleadoAndDateInterval(
array(
'IdEmpleado' => $workerId,
'FechaInicial' => (new \DateTime('2014-01-10'))->format('Y-m-d'),
'FechaFinal' => (new \DateTime('today'))->format('Y-m-d')
));
...
This is my repository function:
public function FindByEmpleadoAndDateInterval($parameters = array(), $limit = null){
...
$qb = $this->createQueryBuilder('q');
$qb
->where('q.IdEmpleado = :IdEmpleado')
->andWhere('q.Fecha > :FechaInicial')
->andWhere('q.Fecha < :FechaFinal')
->setParameter('IdEmpleado', $parameters['IdEmpleado'])
->setParameter('FechaInicial', $parameters['FechaInicial'])
->setParameter('FechaFinal', $parameters['FechaFinal'])
;
return $qb->getQuery()->execute();
}
Folks, careful with this, have a nice look to the format of dates when you're working with Doctrine 2. The problem was this:
-I've set dates format as: 'Y-M-d', but: 'Ymd' was the correct one (in my particular case).
So, have faith in Doctrine 2 and try every known format (Y-m-d), (Y/m/d), etc. So, you could use dates intervals in these simple ways:
public function findByEmpleadoAndDateInterval($parameters = array(), $limit = null)
{
$qb = $this->createQueryBuilder('q');
$qb->where('q.IdEmpleado = :IdEmpleado')
->andWhere('q.Fecha between :FechaInicial and :FechaFinal')
->setParameters($parameters);
return $qb->getQuery()->execute();
}
OR
public function findByEmpleadoAndDateInterval($parameters = array(), $limit = null)
{
$qb = $this->createQueryBuilder('q');
$qb->where('q.IdEmpleado = :IdEmpleado')
->andWhere('q.Fecha >= :FechaInicial and q.Fecha <= :FechaFinal')
->setParameters($parameters);
return $qb->getQuery()->execute();
}
Maybe, out there, there are more elaborated examples, but this case took me a while to figure it out. Specially because isn't directly accesible online.

ZF last inserted id

does this code gives me the last inserted id of the record, even on a heavy load page?
db = Zend_Db_Table::getDefaultAdapter();
$db->insert($this->_name, $fields_values);
$idAddress = $db->lastInsertId($this->_name);
Regards
Andrea
i am using this...
db = Zend_Db_Table::getDefaultAdapter();
$lastInsertId = $db->insert($this->_name, $fields_values);
The Zend_Db_Adapter_Abstract::lastInsertId() method is a proxy to PDO::lastInsertId(). According to the documentation:
PDO::lastInsertId — Returns the ID of the last inserted row or sequence value
Note:
This method may not return a meaningful or consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.
Now you know. Use it as your own risk!
public function saveData(array $data) {
$this->_setName('user');
// this will return all field name for user table in $field variable
$fields = $this->info($this->getConstCol());
// By this foreach loop we will set data in $data array
foreach ($data as $field => $value)
{
if (!in_array($field, $fields))
{
unset($data[$field]);
}
}
// It will call insert function of (Zend_Db_Table_Abstract Parent of Zend_Db_Table)
// It will return $pkData which is primary key for user table
return $this->insert($data); // It will return last insert ID
}

Zend Dojo FilteringSelect from joined tables How can this be done with Doctrine

I have a number of FilteringSelect elements within my Zend Framework application that are working fine but they are based on simple queries.
I now need to create a FilteringSelect that will allow me to select the id of one table while displaying the text of field in a related table, i.e. I have two tables groomservices and groomprocedures which are related (i.e. groomprocedures.groomProceduresID has many groomservices.procedure).
The form I'm trying to create is for an appointments table which has many groomservices.groomServicesID values. I want the user to be able to see the name of the procedure while saving the value of the groomservices.groomServicesID using the FilteringSelect.
So far I've not been able to do this in that my FilteringSelect displays nothing, I'm sure this can be done just that the fault is with my inexperience with Zend,Doctrine and Dojo
I'm not sure if my problem is with my autocomplete action(including the query) or with the FilteringSelect element.
Can anyone spot where I've gone wrong in the code sections below, I need to get this working.
My autocomplete action within my controller
public function gserviceAction()
{
// disable layout and view rendering
$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender(true);
// get a list of all grooming services IDs and related procedures
$qry= Doctrine_Query::create()
->select('g.groomServicesID,p.groomProcedure')
->from('PetManager_Model_Groomservices g')
->leftJoin('g.PetManager_Model_Groomprocedures p');
$result=$qry->fetchArray();
//generate and return JSON string
$data = new Zend_Dojo_Data('g.groomServicesID',$result);
echo $data->toJson();
}
My FilteringSelect element code
// Create a autocomplete select input for the service
$gservice = new Zend_Dojo_Form_Element_FilteringSelect('gapmtService');
$gservice->setLabel('Proceedure');
$gservice->setOptions(array(
'autocomplete' => true,
'storeID' => 'gserviceStore',
'storeType' => 'dojo.data.ItemFileReadStore',
'storeParams' => array('url' => "/groomappointments/appointment/gservice"),
'dijitParams' => array('searchAttr' => 'groomProcedure')))
->setRequired(true)
->addValidator('NotEmpty', true)
->addFilter('HTMLEntities')
->addFilter('StringToLower')
->addFilter('StringTrim');
Many thanks in advance,
Graham
P.S. orgot to mention I tried the following query in mysql and I gave me what I'm looking for I believe the Doctine query evaluates to the same.
select groomservices.groomservicesID,groomprocedures.groomprocedure from groomprocedures left join groomservices on groomprocedures.groomproceduresID =groomservices.groomProcedure
But I'm not sure if I formatted the query correctly in Doctrine.
EDIT in relation to the flammon's comments
Ok I've set the code to the following but I'm still not getting anything to display.
public function gserviceAction()
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContexts(array(
'gservice' => 'json'
));
// get a list of all grooming services IDs and related procedures
$qry= Doctrine_Query::create()
->select('g.groomServicesID AS id,p.groomprocedure AS name')
->from('PetManager_Model_Groomservices g')
->leftJoin('g.PetManager_Model_Groomprocedures p');
$this->view->model = (object) array();
$this->view->model->identifier = 'id';
$this->view->model->label = 'name';
$this->view->model->items = array();
$tableRows = $this->dbTable->fetchAll($qry);
foreach ($tableRows as $row) {
$this->view->model->items[] = $row->toArray();
}
}
I'm sure the fault lies with me.
It looks like there's a problem with the data that you're putting in the ItemFileReadStore.
Here are a few pointers.
Consider extending Zend_Rest_Controller for your services. It'll be easier to manage your contexts and your views. You'll be able to do something like this:
public function init()
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContexts(array(
'gservice' => 'json'
));
}
And it will eliminate the need for the following in each of you service actions.
// disable layout and view rendering
$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender(true);
You'll need to either pass the format parameter or use the following plugin to help with the context switch. Passing the format parameter is simpler but it pollutes the url with ?format=json. Here's the Zend documentation on AjaxContext.
Here's a plugin that you can use if you don't want to pass the format parameter.
class Application_Plugin_AcceptHandler extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
if (!$request instanceof Zend_Controller_Request_Http) {
return;
}
$header = $request->getHeader('Accept');
switch (true) {
case (strstr($header, 'application/json')):
Zend_Registry::get('logger')->log('Setting format to json', Zend_Log::INFO);
$request->setParam('format', 'json');
break;
case (strstr($header, 'application/xml')
&& (!strstr($header, 'html'))):
Zend_Registry::get('logger')->log('Setting format to xml', Zend_Log::INFO);
$request->setParam('format', 'xml');
break;
default:
Zend_Registry::get('logger')->log('Setting format to html', Zend_Log::INFO);
break;
}
}
}
In your controller, instead of echoing the data, create view variables that dojo expects. See this document for the format.
$this->view->model = (object) array();
$this->view->model->identifier = 'id';
$this->view->model->label = 'name';
$this->view->model->items = array();
In your controller, fetch your table rows:
$tableRows = $this->dbTable->fetchAll($select);
or, if you've put model code in a function, it might look more like:
$tableRows = $this->dbTable->fetchGroomProcedures();
Put your row data in the model->items[] array:
foreach ($tableRows as $row) {
$this->view->model->items[] = $row->toArray();
}
Create a view, view/scripts/appointment/gservice.json.phtml and in it put
Zend_Json::encode($this->model)
Use Firebug to see what is returned from your service.