I've just started looking at Zend Framework 2 and Doctrine ORM, with a view to possibly using it in one of my future products. So far I have a very simple application which allows the user to select data from a 'configuration' table. This table has just one row and several columns with settings that the application will use at some point.
So far this is what I have come up with:
ConfigController.php (my Zend controller)
<?php
/**
* A restful controller that retrieves and updates configuration information
*/
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\View\Model\JsonModel;
class ConfigController extends AbstractRestfulController
{
/**
* Retrieves the configuration from the database
*/
public function getList(){
//locate the doctrine entity manager
$em = $this->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
//there should only ever be one row in the configuration table, so I use findAll
$config = $em->getRepository("\Application\Entity\Config")->findAll();
//return a JsonModel to the user. I use my toArray function to convert the doctrine
//entity into an array - the JsonModel can't handle a doctrine entity itself.
return new JsonModel(array(
'data' => $config[0]->toArray(),
));
}
/**
* Updates the configuration
*/
public function replaceList($data){
//locate the doctrine entity manager
$em = $this->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
//there should only ever be one row in the configuration table, so I use findAll
$config = $em->getRepository("\Application\Entity\Config")->findAll();
//loop through each submitted field
foreach($data as $column=>$value){
//work out the name of the setter function for each field
$func = "set".ucfirst($column);
$config[0]->$func($value);
}
//save the entity to the database
$em->persist($config[0]);
$em->flush();
//return a JsonModel to the user. I use my toArray function to convert the doctrine
//entity into an array - the JsonModel can't handle a doctrine entity itself.
return new JsonModel(array(
'data' => $config[0]->toArray(),
));
}
}
Config.php (my Doctrine entity)
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class Config {
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $minLengthUserId;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $minLengthUserName;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $minLengthUserPassword;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $daysPasswordReuse;
/**
* @ORM\Id
* @ORM\Column(type="boolean")
*/
protected $passwordLettersAndNumbers;
/**
* @ORM\Id
* @ORM\Column(type="boolean")
*/
protected $passwordUpperLower;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $maxFailedLogins;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $passwordValidity;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $passwordExpiryDays;
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
protected $timeout;
// getters/setters
/**
* Get the minimum length of the user ID
* @return int
*/
public function getMinLengthUserId(){
return $this->minLengthUserId;
}
/**
* Set the minmum length of the user ID
* @param int $minLengthUserId
* @return \Application\Entity\Config This object
*/
public function setMinLengthUserId($minLengthUserId){
$this->minLengthUserId = $minLengthUserId;
return $this;
}
/**
* Get the minimum length of the user name
* @return int
*/
public function getminLengthUserName(){
return $this->getminLengthUserName;
}
/**
* Set the minimum length of the user name
* @param int $minLengthUserName
* @return \Application\Entity\Config
*/
public function setMinLengthUserName($minLengthUserName){
$this->minLengthUserName = $minLengthUserName;
return $this;
}
/**
* Get the minimum length of the user password
* @return int
*/
public function getMinLengthUserPassword(){
return $this->minLengthUserPassword;
}
/**
* Set the minimum length of the user password
* @param int $minLengthUserPassword
* @return \Application\Entity\Config
*/
public function setMinLengthUserPassword($minLengthUserPassword){
$this->minLengthUserPassword = $minLengthUserPassword;
return $this;
}
/**
* Get the number of days before passwords can be reused
* @return int
*/
public function getDaysPasswordReuse(){
return $this->daysPasswordReuse;
}
/**
* Set the number of days before passwords can be reused
* @param int $daysPasswordReuse
* @return \Application\Entity\Config
*/
public function setDaysPasswordReuse($daysPasswordReuse){
$this->daysPasswordReuse = $daysPasswordReuse;
return $this;
}
/**
* Get whether the passwords must contain letters and numbers
* @return boolean
*/
public function getPasswordLettersAndNumbers(){
return $this->passwordLettersAndNumbers;
}
/**
* Set whether passwords must contain letters and numbers
* @param int $passwordLettersAndNumbers
* @return \Application\Entity\Config
*/
public function setPasswordLettersAndNumbers($passwordLettersAndNumbers){
$this->passwordLettersAndNumbers = $passwordLettersAndNumbers;
return $this;
}
/**
* Get whether password must contain upper and lower case characters
* @return type
*/
public function getPasswordUpperLower(){
return $this->passwordUpperLower;
}
/**
* Set whether password must contain upper and lower case characters
* @param type $passwordUpperLower
* @return \Application\Entity\Config
*/
public function setPasswordUpperLower($passwordUpperLower){
$this->passwordUpperLower = $passwordUpperLower;
return $this;
}
/**
* Get the number of failed logins before user is locked out
* @return int
*/
public function getMaxFailedLogins(){
return $this->maxFailedLogins;
}
/**
* Set the number of failed logins before user is locked out
* @param int $maxFailedLogins
* @return \Application\Entity\Config
*/
public function setMaxFailedLogins($maxFailedLogins){
$this->maxFailedLogins = $maxFailedLogins;
return $this;
}
/**
* Get the password validity period in days
* @return int
*/
public function getPasswordValidity(){
return $this->passwordValidity;
}
/**
* Set the password validity in days
* @param int $passwordValidity
* @return \Application\Entity\Config
*/
public function setPasswordValidity($passwordValidity){
$this->passwordValidity = $passwordValidity;
return $this;
}
/**
* Get the number of days prior to expiry that the user starts getting
* warning messages
* @return int
*/
public function getPasswordExpiryDays(){
return $this->passwordExpiryDays;
}
/**
* Get the number of days prior to expiry that the user starts getting
* warning messages
* @param int $passwordExpiryDays
* @return \Application\Entity\Config
*/
public function setPasswordExpiryDays($passwordExpiryDays){
$this->passwordExpiryDays = $passwordExpiryDays;
return $this;
}
/**
* Get the timeout period of the application
* @return int
*/
public function getTimeout(){
return $this->timeout;
}
/**
* Get the timeout period of the application
* @param int $timeout
* @return \Application\Entity\Config
*/
public function setTimeout($timeout){
$this->timeout = $timeout;
return $this;
}
/**
* Returns the properties of this object as an array for ease of use
* @return array
*/
public function toArray(){
return get_object_vars($this);
}
/**
* Before persisting this entity, check that the minimum
* length of the user ID is not less than 1
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function assertMinLengthUserIdNotLessThan1(){
if($this->minLengthUserId < 1){
throw new \Exception('Minimum length of user ID cannot be less than 1.');
}
}
}
One of my goals is to make the application 'testable'. The applications we have written so far do not include any automated testing whatsoever, which has proved to be very time consuming.
I have several questions regarding what I've done so far:
- Is this easily testable at the moment? How could I improve it in this regard?
- Do I really need all the getters and setters or could I use a generic 'magic methods' __get and __set to do this job?
- Should I be validating input in the setter functions or is it fine to validate before persisting (like in my assertMinLengthUserIdNotLessThan1 function)?
- Is there any better way of getting the Doctrine entity into an array? I have a simple toArray() function so far but I there may be better ways of doing it for more complicated objects.
Any general comments/advice would be much appreciated also!
Thanks in advance!