Zend relationship - get the parent row - zend-framework

I know there are some examples in the web, but doesn't work in my case.
I have a Category table with subcategories. One table 'category' that has id_father that's the id of the Parent Category.
My configuration is the following:
Application_Model_DbTable_Category:
protected $_referenceMap = array(
'Application_Model_DbTable_Category' => array(
'columns' => 'id_father',
'refColumns' => 'id',
'refTableClass' => 'Application_Model_DbTable_Category'
));
CategoryMapper (I don't write the top code, anyway I retrieve a Category that has a parent in the db)
$row = $result->current();
echo $row->name;
$father = 'Non trovato';
$father = $row->findParentRow('Application_Model_DbTable_Category');
print_r($father);
This doesn't print anything... Is something wrong on my code? Thank you

you need to create instance of class Application_Model_DbTable_Category
$row = $result->current();
echo $row->name;
$father = 'Non trovato';
$father = $row->findParentRow(new Application_Model_DbTable_Category());
print_r($father);

Related

populate id from database in select box option value in zend framework

hi I am new in zend framework Basically I want to populate company name list from the database. Actually I have doen it but i want to also populate its id in option box
example
select
option value='1'> tcs option
select
this is my code
Application_Form_Clientcompanyform extends Zend_Form
$company_list = new Application_Model_Clientcompany;
$showlist = $company_list->companyNameList();
$list=array();
$id=array();
foreach($showlist as $key => $value)
{
$list[]=$value['companyName'];
$id[]=$value['id'];
}
$this->addElement('select', 'companyName', array(
'required' => true,
'filters' => array('StringTrim'),
'style' => array('width:103px'),
'multiOptions' => $list,
'decorators'=>Array(
'ViewHelper','Errors'
but Now i want to set the value in option in select box width $id from database
$companyName = new Zend_Form_Element_Select('companyName');
$companyName->setRequired(true);
$companyName->addFilter('StringTrim');
$company_list = new Application_Model_Clientcompany;
$showlist = $company_list->companyNameList();
//add selections to multioption, assumes object...change notation if using array
foreach($showlist as $company) {
$name = ucfirst($company->name);
$companyName->addMultiOption($company->id, $name);
}
$this->addElement($companyName);
I know I changed the syntax style, I just find it easier to keep things straight this way.
Everything else you may need is in http://framework.zend.com/manual/1.12/en/zend.form.html, get used to using the reference and the the api for the framework, they really help.

Zend_Db_Table_Abstract Loading Joined Models

I have a tables named:
client (id, alias)
post (id, subject)
post_client (id, post_id, client_id)
Many clients can be joined to a post.
Using Zend DB Table abstract I have started to build a model, here are the classes:
ORM_Post
class ORM_Post extends Zend_Db_Table_Abstract {
protected $_name = 'Post';
protected $_dependentTables = array('ORM_Post_Client');
}
ORM_Client
class ORM_Client extends Zend_Db_Table_Abstract {
protected $_name = 'Client';
protected $_dependentTables = array(
'ORM_Post_Client'
);
}
ORM_Post_Client
class ORM_Post_Client extends Zend_Db_Table_Abstract {
protected $_name = 'Post_Client';
protected $_referenceMap = array(
'post' => array(
'columns' => 'post_id',
'refTableClass' => 'ORM_Post',
'refColumns' => 'id'
),
'client' => array(
'columns' => 'client_id',
'refTableClass' => 'ORM_Post_Client',
'refColumns' => 'id'
)
);
}
What I was hoping todo is call an instance of the Post and then load the clients associated aswell as loading an instance of the client and load all posts associated.
So I did this:
$post = new ORM_Post();
$results = $post->fetchAll();
foreach ($results as $key => $result){
$row = $results->current();
$client = $row->findDependentRowset('ORM_Post_Client','client');
}
and I get
Reference rule "client" does not reference table ORM_Post
I have battled with this for hours and cannot see where I'm going wrong. Am I to declare the Post_Client joins inside the client and post model also?
EDIT
Here is what I was after:
$post = new ORM_Post();
$results = $post->fetchAll();
$return = array();
foreach ($results as $result){
$row = $post->find($result->id)->current();
$return[$result->id] = $row->toArray();
$return[$result->id]['clients'] = $row->findManyToManyRowset('ORM_Client', 'ORM_Post_Client')->toArray();
}
return $return;
Thanks for the advice guys, you put me on the right track
in your ORM_Post_Client it should be
'client' => array(
'columns' => 'client_id',
'refTableClass' => 'ORM_Client', //instead of ORM_Post_Client
'refColumns' => 'id'
)
refTableClass => The class name of the parent table. Use the class
name, not the physical name of the SQL table (documentation)
also i think your loop should be :
foreach ($results as $result){
$row = $results->current();
$clients = $row->findDependentRowset('ORM_Post_Client','post');
}
because you are looking for clients of a post which means that post is your rule
($row->findDependentRowset($table, [$rule]); )
This as presented won't work, honestly it makes no sense.
$post = new ORM_Post();
$results = $post->fetchAll();
foreach ($results as $key => $result){
//$row is assigned to the whole fetchall result!
$row = $results->current();
//in this context $client cannot call a dependent rowset.
$client = $row->findDependentRowset('ORM_Post_Client','client');
}
MMc is correct in that you reference table definition was incorrect however your code has some issues as well. Maybe try something like:
$post = new ORM_Post();
$results = $post->fetchAll();
//unless your are going to use the 'key' for something you don't need it
foreach ($results as $result){
//you need each row object in order to call findDependentRowset in a one to many relationship.
$row = $post->find($result->id)->current();
//unless you have multiple rules set up for each table class pair you don't need to specify the rule.
$client = $row->findDependentRowset('ORM_Post_Client');
}

Ordering in find()

I have a model Org.
In a model Org I have $hasAndBelongsToMany = array('Patient','Project','Category');
In orgs controller action view I get data from database with
$this->set('org', $this->Org->find('first',array('condition'=> array('id'=>$id))));
Result is ok but I want change the order.
I want order result Patient by name, Project by name and Category by id.
How use ORDER BY for Patient,Project,Category in find() ?
Assuming this is Cake, the ordering of associated models should be done in the model when you declare the HABTM relationship:
<?php
class Org extends AppModel {
var $hasAndBelongsToMany = array(
'Patient' => array(
'order' => array(
'Patient.name ASC'
)
),
'Project' => array(
'order' => array(
'Project.name ASC'
)
),
'Category' => array(
'order' => array(
'Category.id ASC'
)
)
);
}
?>
If you're wanting to sort the actual result set by the associated models you can pass an order array to the find method:
<?php
$org = $this->Org->find('all', array(
'conditions' => array(
'Org.column_name' => $yourVar
),
'order' => array(
'Patient.name ASC',
'Project.name ASC',
'Category.id ASC'
)
));
?>
If you're doing a find first by a unique field (like an ID) you can use the built in findByFIELDNAME helper:
<?php
$org = $this->Org->findById($id);
$this->set(compact(array('org')));

Zend One To Many doesn't work

I was trying an example of one to many relationship in zend framework, but I can't get results.
Here are the tables:
UsersTable:
<?php
class Application_Model_DbTable_UsersTable extends Zend_Db_Table_Abstract
{
protected $_name = 'users';
protected $_dependentTables = array('Application_Model_DbTable_BugsTable');
}
BugsTable:
class Application_Model_DbTable_BugsTable extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
protected $_dependentTables = array('Application_Model_DbTable_BugsProductsTable');
protected $_referenceMap = array(
'Reporter' => array(
'columns' => 'reported_by',
'refTableClass' => 'Application_Model_DbTable_UsersTable',
'refColumns' => 'username'
),
'Engineer' => array(
'columns' => 'assigned_to',
'refTableClass' => 'Application_Model_DbTable_UsersTable',
'refColumns' => 'username'
),
'Verifier' => array(
'columns' => array('verified_by'),
'refTableClass' => 'Application_Model_DbTable_UsersTable',
'refColumns' => array('username')
)
);
}
As you can see, this is one to many relationship from db table 'users' to table 'bugs' , where we have three foreign reference keys in bugs talbe.
Now when I try to use Zend methods for one to many relationships I always get empty results:
$tableUser = new Application_Model_DbTable_UsersTable();
$tableBugs = new Application_Model_DbTable_BugsTable();
$result= $tableUser->find(1);
$user= $result->current();
$userBugs = $user->findDependentRowset('Application_Model_DbTable_BugsTable','Verifier');
echo count($userBugs); //returns 0
$bugresult = $tableBugs->find(1);
$thisbug= $bugresult->current();
$verifier= $thisbug->findParentRow('Application_Model_DbTable_UsersTable','Verifier');
return $verifier //returns nothing
The proper data is in the database, when I for example do a query:
select * from bugs b, users u where b.reported_by=u.id and u.id=1;
I get the expected results. But when I try in zend no results.
Do you have any suggestions? Thanks.
In your sql u get bugs by field
reported_id
but in this code:
$result= $tableUser->find(1);
$user= $result->current();
$userBugs = $user->findDependentRowset('Application_Model_DbTable_BugsTable','Verifier');
echo count($userBugs); //returns 0
$bugresult = $tableBugs->find(1);
$thisbug= $bugresult->current();
$verifier= $thisbug->findParentRow('Application_Model_DbTable_UsersTable','Verifier');
return $verifier //returns nothing
u try to get bug by
verified_by
field
try this:
$result= $tableUser->find(1);
$user= $result->current();
$userBugs = $user->findDependentRowset('Application_Model_DbTable_BugsTable','Reporter');
echo count($userBugs);

Zend_Validate_Db_RecordExists against 2 fields

I usualy use Zend_Validate_Db_RecordExists to update or insert a record. This works fine with one field to check against. How to do it if you have two fields to check?
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => $this->_name,
'field' => 'id_sector,day_of_week'
)
);
if ($validator->isValid($fields_values['id_sector'],$fields_values['day_of_week'])){
//true
}
I tried it with an array and comma separated list, nothing works... Any help is welcome.
Regards
Andrea
To do this you would have to extend the Zend_Validate_Db_RecordExists class.
It doesn't currently know how to check for the existence of more than one field.
You could just use two different validator instances to check the two fields separately. This is the only work around that I can see right now besides extending it.
If you choose to extend it then you'll have to find some way of passing in all the fields to the constructor ( array seems like a good choice ), and then you'll have to dig into the method that creates the sql query. In this method you'll have to loop over the array of fields that were passed in to the constructor.
You should look into using the exclude parameter. Something like this should do what you want:
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => $this->_name,
'field' => 'id_sector',
'exclude' => array(
'field' => 'day_of_week',
'value' => $fields_values['day_of_week']
)
);
The exclude field will effectively add to the automatically generated WHERE part to create something equivalent to this:
WHERE `id_sector` = $fields_values['id_sector'] AND `day_of_week` = $fields_values['day_of_week']
Its kind of a hack in that we're using it for the opposite of what it was intended, but its working for me similar to this (I'm using it with Db_NoRecordExists).
Source: Zend_Validate_Db_NoRecordExists example
Sorry for the late reply.
The best option that worked for me is this:
// create an instance of the Zend_Validate_Db_RecordExists class
// pass in the database table name and the first field (as usual)...
$validator = new Zend_Validate_Db_RecordExists(array(
'table' => 'tablename',
'field' => 'first_field'
));
// reset the where clause used by Zend_Validate_Db_RecordExists
$validator->getSelect()->reset('where');
// set again the first field and the second field.
// :value is a named parameter that will be substituted
// by the value passed to the isValid method
$validator->getSelect()->where('first_field = ?', $first_field);
$validator->getSelect()->where('second_field = :value', $second_field);
// add your new record exist based on 2 fields validator to your element.
$element = new Zend_Form_Element_Text('element');
$element->addValidator($validator);
// add the validated element to the form.
$form->addElement($element);
I hope that will help someone :)
Although, I would strongly recommend a neater solution which would be to extend the Zend_Validate_Db_RecordExists class with the above code.
Enjoy!!
Rosario
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
'validators' => array('EmailAddress', $obj= new Zend_Validate_Db_NoRecordExists(array('adapter'=>$dbAdapter,
'field'=>'email',
'table'=>'user',
'exclude'=>array('field'=>'email','value'=>$this->_options['email'], 'field'=>'is_deleted', 'value'=>'1')
))),
For those using Zend 2, If you want to check if user with given id and email exists in table users, It is possible this way.
First, you create the select object that will be use as parameter for the Zend\Validator\Db\RecordExists object
$select = new Zend\Db\Sql\Select();
$select->from('users')
->where->equalTo('id', $user_id)
->where->equalTo('email', $email);
Now, create RecordExists object and check the existence this way
$validator = new Zend\Validator\Db\RecordExists($select);
$validator->setAdapter($dbAdapter);
if ($validator->isValid($username)) {
echo 'This user is valid';
} else {
//get and display errors
$messages = $validator->getMessages();
foreach ($messages as $message) {
echo "$message\n";
}
}
This sample is from ZF2 official doc
You can use the 'exclude' in this parameter pass the second clause that you want to filter through.
$clause = 'table.field2 = value';
$validator = new Zend_Validate_Db_RecordExists(
array(
'table' => 'table',
'field' => 'field1',
'exclude' => $clause
)
);
if ($validator->isValid('value') {
true;
}
I am using zend framework v.3 and validation via InputFilter(), it uses same validation rules as zend framework 2.
In my case I need to check, if location exists in db (by 'id' field) and has needed company's id ('company_id' field).
I implemented it in next way:
$clause = new Operator('company_id', Operator::OP_EQ, $companyId);
$inputFilter->add([
'name' => 'location_id',
'required' => false,
'filters' => [
['name' => 'StringTrim'],
['name' => 'ToInt'],
],
'validators' => [
[
'name' => 'Int',
],
[
'name' => 'dbRecordExists',
'options' => [
'adapter' => $dbAdapterCore,
'table' => 'locations',
'field' => 'id',
'exclude' => $clause,
'messages' => [
'noRecordFound' => "Location does not exist.",
],
]
],
],
]);
In this case validation will pass, only if 'locations' table has item with columns id == $value and company_id == $companyId, like next:
select * from location where id = ? AND company_id = ?