How to select a calculated value including parameter using Zend FW? - zend-framework

I'm using Zend FW and have a select with specified columns to be selected, e.g.
$select = $this->_db->select();
$select->from( array("t" => 'table'), array( 'id', 'name', 'some_number'));
Now I want to get the some_number value multiplied by some given parameter, like :
select id, name, (some_number * $param) from table;
How to do that?

Got it, using Zend_Db_Expr. If someone else needs... That works for me:
$select->from( array("t" => 'table'),
array( 'id', 'name', 'new_number' => new Zend_Db_Expr('some_number * ' . $param ) )
);

Related

Cakephp table query

I have a members table. It has these columns:
ID
fname
lname
parent
spouse
I want 'parent' field to have select option in a form which uses 'fname' & 'lname' and store it in 'parent' field. I have tried to do this Members controller:
$results = $this->Members->find('list',
array('order'=>array('fname DESC')));
$parent = $results->toArray();
I am calling $parent variable as an input. However that method doesn't work. I don't know how to figure it out.
When calling list you can configure the fields used for the key and value with the keyField and valueField options respectively.
Doc: https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#finding-key-value-pairs
Like this
$query = $articles->find('list', [
'keyField' => 'slug',
'valueField' => 'title'
]);
In your case it will be like this
$results = $this->Members->find('list', array(
'keyField' => 'ID',
'valueField' => 'parent'
'order'=>array('fname DESC'),
));
$parent = $results->toArray();

Join two table in zend_Validate_Db_NoRecordExists

I need to join two tables in zend_validate_Db_NoRecordExists. I need to use exclude for each table. I am using postgresql as db.
The usual way of invoking zend_validate_Db_NoRecordExists is as follows:
$validator = new Zend_Validate_Db_NoRecordExists(
array (
'table' => 'table1',
'field' => 'flag',
'exclude' => 'delete=0',
)
);
I think you must me able to use
$validator->getSelect()->_joinUsing($type, $name, $cond);

Zend_Select select static value

How to make a request with the Zend_Select
SELECT "subdivision" as `type`, a.id as id FROM `some_table` a;
doing so
$ this-> select ()
-> from (
array ('a' => 'some_table'), array ('type' => "subdivision", 'id' => 'a.id')
)
result
SELECT `a`. `" Subdivision "` as `type`, a.id as id FROM `some_table` a;
You have to mark the static value so that Zend_Db_Select does not quote the value as an identifier using Zend_Db_Expr.
$this->select()
->from(array(
'a' => 'some_table'
), array(
'type' => new Zend_Db_Expr($db->quote('subdivision')),
'id' => 'a.id'
)
);
It's not always obvious but for Laminas it'll look like this
$select->from(['a' => 'some_table'])
->columns([
'id' => 'id',
'type' => new Laminas\Db\Sql\Expression('"subdivision"')
]);

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 = ?

How do I go around this Zend_Form_Element_Select db error?

When i use the Zend_Form_Element_Select elements with multioptions i get this error when i pass the selected value to Zend_DB_Table to insert into the db
Message: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'accounts_status ' in 'field list'
I have extracted some code snippets that i believe will go a long way into illustrating my problem.The accounts_status field DOES exist in my table
On my form construct have added the select element and options (I have left out the other elements)
$optionsstatus = array(
'active' => 'active',
'pending' => 'pending'
);
$optionsrole = array(
'guest' => 'guest',
'user' => 'user',
'writer' => 'writer',
'admin' => 'admin'
);
$status = new Zend_Form_Element_Select('accounts_status');
$status->setLabel('Status')
->setRequired(true)
->addMultiOptions($optionsstatus);
$role = new Zend_Form_Element_Select('accounts_role');
$role->setLabel('Role')
->setRequired(true)
->addMultiOptions($optionsrole);
I use the Zend_DB_table to insert the post values from my controller
public function addaccount($username, $fullname, $email,
$password,$status,$roles,$comments)
{
$data = array(
'accounts_username' => $username,
'accounts_fullname' => $fullname,
'accounts_email' => $email,
'accounts_password' => $password,
'accounts_status ' => $status,
'accounts_roles' => $roles,
'accounts_comments ' => $comments,
);
$this->insert($data);
}
In my controller i get the post values and send them to my model
$username = $form->getValue('accounts_username');
$fullname = $form->getValue('accounts_fullname');
$email = $form->getValue('accounts_email');
$password = $form->getValue('accounts_password');
$status = $form->getValue('accounts_status');
$roles = $form->getValue('accounts_roles');
$comments = $form->getValue('accounts_comments');
$accounts = new Model_DbTable_Account();
$accounts->addaccount($username, $fullname,$email,
$password,$status,$roles,$comments);
This approach works for me except when am dealing with the Zend_Form_Element_Select elements.Am just wondering if there is a specific way of dealing with this select elements when it comes to CRUD operations.
Message: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'accounts_status ' in 'field list'
Maybe I'm crazy, but looks to me like there's an extra space on that end of that 'accounts_status ' field name.