I have just started with Zend Framework, so I have lots of questions about the structure. I hope I can explain it properly, it's rather difficult.
Ok, I have done the Quickstart Tutorial and decided to use a similar structure for my first project.
So I have a Datamapper, a Model and the Database Table File.
I have created a Form where I can enter a some Information(Item) and upload Images with it.
I have 2 Datamapper (Item and Image) as well as 2 Models for them. I have an Item Controller, that one jumps into the ItemMapper. In the Datamapper I have a save Method. Please see below:
public function save(Application_Model_Item $item)
{
$data = array(
'item_title' => $item->getItemTitle(),
'item_description' => $item->getItemDescription(),
);
$this->getDbTable()->insert($data);
// Add Image Information ($imageData is Session Data)
$table = new Application_Model_DbTable_Image();
foreach ($imageData as $fileData)
{
$image = new Application_Model_Image($fileData);
$data = array(
'image_newname' => $image->getNewImageName(),
'image_thumbname' => $image->getImageThumbName(),
);
$table->insert($data);
}
Now the question I have.
I read something about "Fat Model Thin Controller". I had this all the time in my had, but I noticed that my Controller got pretty fat with just putting the Form together. I have about 5 Dropdown Fields which are depending Dropdowns. When I saw that I duplicating Code I decided to add this in a separate Function. So f.e. I have a Dropdown for counties. I wrote a Function which is also in my Controller so it looks like this:
public function getCounties ()
{
// List of Counties does not exist in Cache, read from DB
if(!$CountyList = $this->getFromCache('counties')){
$geolocationMapper = new Application_Model_GeolocationMapper();
$CountyDropdown = $geolocationMapper->createCountyDropdown();
// Save DB Result in Cache
$this->addToCache ('counties',$CountyDropdown);
return $CountyDropdown;
}
else{
// Return Country List from Cache
return $this->getFromCache('counties');
}
}
In my Add Function I use
// Assign Geo Info to Form
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList);
The Edit Function than
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList)->setValue($activeCounty)
all the Functions like getCounties () stay in the Controller or should it be moved to the GeolocationMapper? And if so, how would that be called up?
I know this are lots of questions, but I have the feeling it gets very messy, as a learner you are happy when it works, but I would also like to structure it in a proper way. I hope it all makes sense.
Maybe some of you have a few Tipps I could use. Thanks a lot for your help in advance.
There are quite a few questions here and most of the answers will be down largely to personal preference. With that caveat out of the way:
Should everything what is in the Item Database Table be in 1 Model?
I would say yes, although in general, try and think about it from the perspective of the models rather than the database structure. So all of the 'item' data goes in the Item model - the fact that this is all stored in one database table is irrelevant, since the mapper handles the translation from one to the other.
Is it correct that I save the Information about the Image in the Item Mapper?
It's not clear where $imageData comes from in your example, but I'd say the Item mapper should call the Image mapper if there is image data to save, e.g.:
public function save(Application_Model_Item $item)
{
$data = array(
'item_title' => $item->getItemTitle(),
'item_description' => $item->getItemDescription(),
);
$this->getDbTable()->insert($data);
// save image data if present
if (isset($item->image)) {
$imageMapper = new Yourapp_Mapper_Image();
$imageMapper->save($item->image);
}
return true;
}
[Should] all the Functions like getCounties () stay in the Controller or should it be moved to the GeolocationMapper? And if so, how would that be called up?
I don't see any reason for these functions to be in the controller. Depending on how comfortable you are with the Zend_Form component, one approach might be to write a custom Yourapp_Form_Element_Counties class that extends Zend_Form_Element_Select. You then move your logic from the getCounties function into the this class, so the form element itself is responsible for populating the options it presents. E.g.:
class Yourapp_Form_Element_Counties extends Zend_Form_Element_Select
{
public function getMultiOptions()
{
// load counties here and return an array in the format key -> value
}
}
Another approach, if you have a lot of location-related form elements, might be to create a GeoLocation Service class, which has a function for counties, cities etc. that returns the options.
Should the Form be created in some Function so I would only call up something like createForm()
It's not clear how much form stuff you are doing in the controller already apart from populating select options, so it's hard to answer this one. Here are the principles I generally follow when using Zend_Form:
Myapp_Form_Post_Base) which defines the elements, and then action-specific classes which extend it: Myapp_Form_Post_Add, Myapp_Form_Post_Edit and so on. These classes make any changes they need to the base form in their own init() method.My actions then look something like this:
public function editAction()
{
$form = new Myapp_Form_Post_Edit();
if ($this->_request->isPost()) {
if ($form->isValid($this->_request->getPost()) {
// save data, set flash messge and redirect
}
}
$this->view->form = $form;
}
My only other piece of advice is to try and follow the approach which seems most logical to you. You might find it difficult to find definitive 'best practices' for a lot of this stuff since there are many different ways to do it all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With