Zend Framework: How to check an additional column while using DbTable Auth Adapter? - zend-framework

Currently, I'm getting a regular DbTable Auth Adapter:
protected function _getAuthAdapter($formData)
{
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users')
->setIdentityColumn('username')
->setCredentialColumn('password');
$authAdapter->setIdentity($formData['username']);
$authAdapter->setCredential(md5($formData['password']));
return $authAdapter;
}
But I want to check an additional column in the database (IsActive for example). I don't know if this can be done with the adapter. How can this be done?

I have a similar situation, and I extended the Zend_Auth_Adapter_DbTable to satisfy my needs:
class My_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable
{
protected $_customerIdColumn = 'customer_id';
protected $_customerId = false;
public function setCustomerId($id) {
$this->_customerId = $id;
return $this;
}
public function getCustomerId() {
return ($this->_customerId !== false) ? $this->_customerId : '';
}
public function _authenticateCreateSelect() {
$dbSelect = parent::_authenticateCreateSelect();
$dbSelect->where($this->_zendDb->quoteIdentifier($this->_customerIdColumn, true) . ' = ?',
$this->getCustomerId());
return $dbSelect;
}
}
I then use it like this:
public function getAuthAdapter(array $params)
{
$authAdapter = new My_Auth_Adapter_DbTable(
$params['db_adapter'],
'users',
'username',
'password',
'? AND active = 1'
);
$authAdapter->setIdentity($params['username'])
->setCustomerId($params['customer_id'])
->setCredential($params['password']);
return $authAdapter;
}

I use two columns for my Zend_Auth_Adapter_DbTable, and it looks like this:
$authAdapter = new Zend_Auth_Adapter_DbTable(
Zend_Registry::get('database'),
"user",
"username",
"password_hash", // column 1
"MD5( CONCAT(?,password_salt) )" // column 2
);
When authenticating, the SQL ends up looking like this:
SELECT `user`.*,
(CASE WHEN `password_hash` = MD5( CONCAT('password entered',password_salt) )
THEN 1 ELSE 0 END) AS `zend_auth_credential_match`
FROM `user` WHERE (`username` = 'username entered')
So, that checks an additional column, password_salt, and for me it works well. I don't know if that helps you, as I don't know what you're trying to do.

The included Auth Adapater Zend_Auth_Adapter_DbTable does not allow you to check an additional column. You could extend the Zend_Auth_Adapter_DbTable class and add another column. You will have to add a member variable for the value of new field $_otherFieldValue and a public function setMemberField($value). Finally, you would have to override:
protected function _authenticateCreateSelect()
Hope that helps.

I know this question may be already solved but you can also solve this without needing to extend the class, use the getDbSelect() method and add the where clause to it:
$authAdapter = new Zend_Auth_Adapter_DbTable(Model_Users::getDefaultAdapter());
$authAdapter->setTableName('users');
$authAdapter->setIdentityColumn('email');
$authAdapter->setCredentialColumn('password')->setCredentialTreatment('md5(?)');
$authAdapter->setIdentity($email);
$authAdapter->setCredential($password);
$authAdapter->getDbSelect()->where('active = 1');

Related

Is it possible to declare a form object inside a block of if condition in zend framework?

I am very new to zend framework. I want to declare a form object inside an if condition. but I don't know is it possible or not ?. I write the below code:
public function editAction()
{
$modelUsers = new Model_Users();
$userId = $this->_getParam('userId');
if ($userId) {
$populateData = array();
$user = $modelUsers->fetch($userId);
// print_r($user); exit();
if ($user instanceof Model_User) {
$populateData = $user->toArray();
$form = $this->_geteditForm($user->email);
}
$form->populate($populateData);
}
$request = $this->getRequest();
if ($request->isPost()) {
Please let me know I am going to the write path or not.
Thanks in advance
It's OK, but (assuming that it's some kind of a crud) it's better to redirect back to list or throw exception if the ID is missing. Than you don't need to close the whole form in condition. i.e:
if (!$userId = $this->_getParam('userId')) {
throw new Exception('Missing userId');
//or
$this->_helper->redirector('index');
}

Call to undefined method Application_Model_DbTable_Projects::lastInsertId()

I want to retrieve the id of the last inserted row. This is the code I use in the mapper:
public function save(Application_Model_Projects $project)
{
$data = array(
'id_user' => $project->getIdUser(),
'project_name' => $project->getProjectName(),
'project_description' => $project->getProjectDescription(),
'due_date' => $project->getDueDate(),
'id_customer' => $project->getIdCustomer()
);
if(($id = $project->getId()) === null) {
unset($data['id']);
$this->getDbTable()->insert($data);
return $this->getDbTable()->lastInsertId();
}else {
$this->getDbTable()->update($data, array('id = ?', (int) $id));
return $id;
}
}
According to the code above, it should return the id of the object. It is either the id after insertion or the current id.
The code where I use this function:
$currentUser = new Application_Model_UserAuth();
$project = new Application_Model_Projects();
$project->setProjectName($formValues['projectName'])
->setProjectDescription($formValues['projectDescription'])
->setDueDate(date("Y-m-d",strtotime($formValues['dueDate'])))
->setIdCustomer($formValues['assignCustomer'])
->setIdUser($currentUser->id);
$projectMapper = new Application_Model_ProjectsMapper();
$idProject = $projectMapper->save($project);
The error I get is:
Fatal error: Call to undefined method Application_Model_DbTable_Projects::lastInsertId()
What is wrong with this? Shouldn't that return the last id? Because it is triggered upon insertion. In another sequence of code I call the lastInsertId: $Zend_Db_Table::getDefaultAdapter()->lastInsertId(). The only difference is that now I call lastInsertIt on a dbTable, that extends Zend_Db_Table_Abstract.
The answer to my question above is that I should call getAdapter() before lastInsertId().
Updated code:
if(($id = $project->getId()) === null) {
unset($data['id']);
$this->getDbTable()->insert($data);
return $this->getDbTable()->getAdapter()->lastInsertId();
}
If it is an single-column Primary Key the return value is lastInsertId by default, so you also can use this:
return $this->getDbTable()->insert($data);

Zend Db query to select all IDs

How would I write an Zend DB query to select all from the column ID?
So far I have tried:
public function getLatestUserID()
{
$ids = $this->select()
->where('id = ?');
return $ids;
}
But to no avail.
You just want the id column,
You failed to call an execute command.
try:
//assuming you are using a DbTable model
public function getLatestUserID()
{
$ids = $this->fetchAll('id');
return $ids;
}
I would do it like this, because I use the select() object for everything:
public function getLatestUserID()
{
$select = $this->select();
//I'm not sure if $this will work in this contex but you can out the table name
$select->from(array($this), array('id'));
$ids = $this->fetchAll($select);
return $ids;
}
The first two examples should return just the id column of the table, now if you actually want to query for a specific id:
public function getLatestUserID($id)
{
$select = $this->select();
$select->where('id = ?', $id);
//fetchAll() would still work here if we wanted multiple rows returned
//but fetchRow() for one row and fetchRowset() for multiple rows are probably
//more specific for this purpose.
$ids = $this->fetchRow($select);
return $ids;
}
make sure your class containing getLatestUserID does extend Zend_Db_Table_Abstract also :
$ids = $this->select()->where('id = ?'); can't work because where('id = ?'); expects an id value like where('id = ?', $id);
if what you want is the latest inserted row's Id use :
$lastInsertId = $this->getAdapter()->lastInsertId();
(however if you are using an oracle database this will not work and you should use $lastInsertId = $this->getAdapter()->lastSequenceId('USER_TABLE_SEQUENCE'); )

Symfony: exclude empty values from form save

I have a many to many relation between Product and Properties. I'm using embedRelation() in my Product form to edit a Product and it's Properties. Properties includes images which causes my issue. Every time I save the form the updated_at column is updated for file properties even when no file is uploaded.
Therefore, I want to exclude empty properties when saving my form.
I'm using Symfony 1.4 and Doctrine 1.2.
I'm thinking something like this in my ProductForm.class.php, but I need some input on how to make this work.
Thanks
class ProductForm extends BaseProductForm
{
public function configure()
{
unset($this['created_at'], $this['updated_at'], $this['id'], $this['slug']);
$this->embedRelation('ProductProperties');
}
public function saveEmbeddedForms($con = null, $forms = null)
{
if (null === $forms)
{
$properties = $this->getValue('ProductProperties');
$forms = $this->embeddedForms;
foreach($properties as $p)
{
// If property value is empty, unset from $forms['ProductProperties']
}
}
}
}
I ended up avoiding Symfony's forms and saving models instead of saving forms. It can be easier when playing with embedded forms. http://arialdomartini.wordpress.com/2011/04/01/how-to-kill-symfony%E2%80%99s-forms-and-live-well/
Solved it by checking if posted value is a file, and if both filename and value_delete is null I unset from the array. It might not be best practice, but it works for now.
Solution based on http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms
class ProductPropertyValidatorSchema extends sfValidatorSchema
{
protected function configure($options = array(), $messages = array())
{
// N0thing to configure
}
protected function doClean($values)
{
$errorSchema = new sfValidatorErrorSchema($this);
foreach($values as $key => $value)
{
$errorSchemaLocal = new sfValidatorErrorSchema($this);
if(array_key_exists('value_delete', $values))
{
if(!$value && !$values['value_delete'])
{
unset($values[$key]);
}
}
// Some error for this embedded-form
if (count($errorSchemaLocal))
{
$errorSchema->addError($errorSchemaLocal, (string) $key);
}
}
// Throws the error for the main form
if (count($errorSchema))
{
throw new sfValidatorErrorSchema($this, $errorSchema);
}
return $values;
}
}

Symfony form with doctrine table other than getTable()->find() is not working

I get a really anoying error when I try to edit an entry from a table, in tutorial they always use getTable()->find(), but I need to verify that the person logged in is the owner of that entry here what I did:
In the action:
public function executeEdit(sfWebRequest $request)
{
$id = $request->getParameter('id');
$userid = $this->getUser()->getGuardUser()->getId();
$ad = Doctrine_Core::getTable('BambinbazarArticles')->getMyAd($id, $userid);
$this->forward404Unless($ad, sprintf('Object bambinbazar_articles does not exist (%s).', $request->getParameter('id')));
$this->form = new BambinbazarArticlesForm($ad);
}
In the model:
public function getMyAd($id, $userid)
{
$q = $this->createQuery('c')
->where('c.id = ? ', $id)
->addWhere('c.userid = ? ', $userid);
return $q->execute();
}
I tried it with and without the ->execute(), did doctrine clean, cleared cache, rebuilded model,
Always get the same error 'The "%s" form only accepts a "%s" object.
If I use the Doctrine_Core::getTable('BambinbazarArticles')->find() it work, but of course, i need more than that..
I am becoming crazy over this.
execute() can return multiple rows; effectively you're getting a recordset back, rather than the individual object that your form is expecting. Try fetching a single object, using, e.g.:
return $q->execute()->getFirst();
or
return $q->fetchOne();
Its probably because your query is returning a Doctrine_Collection, not the actual Doctrine_Record youre expecting. Instead of execute use fetchOne.
public function getMyAd($id, $userid)
{
$q = $this->createQuery('c')
->where('c.id = ? ', $id)
->addWhere('c.userid = ? ', $userid)
->limit(1);
return $q->fetchOne();
}