我刚开始使用Zend Framework,所以我对结构有很多疑问。 我希望我能正确解释,这很难。
好的,我已经完成了快速入门教程,并决定在我的第一个项目中使用类似的结构。
所以我有一个Datamapper,一个Model和一个数据库表文件。
我创建了一个表单,我可以在其中输入一些信息(项目)并用它上传图像。
我有2个Datamapper(项目和图像)以及2个模型。我有一个Item Controller,跳转到ItemMapper。在Datamapper中,我有一个save方法。请参阅以下内容:
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);
}
现在我有问题了。
我读了一些关于“Fat Model Thin Controller”的内容。我一直都有这个,但是我注意到我的控制器非常胖,只需将Form放在一起。我有大约5个下拉字段,这取决于下拉列表。当我看到我复制Code时,我决定将它添加到一个单独的Function中。所以f.e.我有一个县的下拉菜单。我写了一个函数,它也在我的控制器中,所以它看起来像这样:
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');
}
}
在我的添加功能中,我使用
//将地理信息分配给表单
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList);
编辑功能
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList)->setValue($activeCounty)
getCounties()等所有函数都保留在Controller中,还是应该移动到GeolocationMapper?如果是这样,那怎么会被召唤出来?
我知道这是很多问题,但我觉得它变得非常混乱,作为一个学习者,当它工作时你很开心,但我也希望以适当的方式构建它。我希望这一切都有道理。
也许有些人有一些我可以使用的Tipps。非常感谢您的帮助。
答案 0 :(得分:1)
这里有很多问题,大多数答案主要取决于个人偏好。有了这个警告:
项目数据库表中的所有内容是否应该在1个模型中?
我会说是的,尽管一般来说,从模型的角度而不是数据库结构中尝试思考它。因此,所有'item'数据都在Item模型中 - 事实上,这一切都存储在一个数据库表中是无关紧要的,因为映射器处理从一个到另一个的转换。
在项目映射器中保存有关图像的信息是否正确?
不清楚你的示例中$ imageData来自哪里,但是如果有要保存的图像数据,我会说Item映射器应该调用Image映射器,例如:
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;
}
[应该]像getCounties()这样的所有函数都保留在Controller中,还是应该移动到GeolocationMapper?如果是这样,那怎么会被召唤出来?
我认为这些功能没有任何理由在控制器中。根据您对Zend_Form
组件的满意程度,一种方法可能是编写扩展Yourapp_Form_Element_Counties
的自定义Zend_Form_Element_Select
类。然后,将逻辑从getCounties函数移动到此类中,因此表单元素本身负责填充它所呈现的选项。 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
}
}
另一种方法,如果你有很多与位置相关的表单元素,可能是创建一个GeoLocation Service类,它具有返回选项的县,城市等功能。
如果在某个函数中创建表单,那么我只会调用类似createForm()
的内容
目前还不清楚你在控制器中做了多少表单,除了填充选择选项之外,所以很难回答这个问题。以下是我在使用Zend_Form时通常遵循的原则:
Myapp_Form_Post_Base
)创建一个抽象基类来定义元素,并且然后是特定于行动的类,它们扩展了它:Myapp_Form_Post_Add
,Myapp_Form_Post_Edit
等等。这些类在他们自己的init()方法中对基本表单进行所需的任何更改。我的行为看起来像这样:
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;
}
我唯一的另一条建议是尝试遵循对您来说最合乎逻辑的方法。您可能会发现很难找到确定的“最佳实践”,因为有很多不同的方法可以做到这一切。
答案 1 :(得分:0)
我试图尽可能地遵循你的想法,所以所有对县,镇和邮政编码的调用都在GeolocationMapper中,图像数据的保存在ImageMapper中。
你问我现在如何创建我的表格,这是一个来自县表格的init()等的例子......
// Create Dropdown for Counties
$county = new Zend_Form_Element_Select('county');
$county->setLabel('Select a County')
->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description',
array('tag' => 'p', 'class'=>'description')),
'Label',
array('HtmlTag',
array('tag'=>'li','class'=>'county'))
))
->setRequired(false);
// Create Dropdown for Town
$town = new Zend_Form_Element_Select('town');
$town->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
'Label',
array('HtmlTag',array('tag'=>'li','class'=>'town'))
));
// Create Dropdown for Postcode
$postcode = new Zend_Form_Element_Select('postcode');
$postcode->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
'Label',
array('HtmlTag',array('tag'=>'li','class'=>'postcode'))
))
->setRegisterInArrayValidator(false);
在我的控制器中我获取元素并填充它们:
$geolocationMapper = new Application_Model_GeolocationMapper();
$CountyOptions = $geolocationMapper->createCountyDropdown();
$form->getElement('county')->setMultiOptions($CountyOptions);
在我的GeolocationMapper中,我有构建我的县数组的方法:
/** ===========================================================================
* Get Counties
* @param
* @return Object? of Counties
* ========================================================================= */
public function getCountyList()
{
$table = $this->getDbTable();
$select = $table->select()->distinct()
->from(array('p' => 'geolocation'),'county')
->order('county');
$resultSet = $this->getDbTable()->fetchAll($select);
$entries = array();
foreach ($resultSet as $row)
{
$entry = new Application_Model_Geolocation();
$entry->setId($row->county)
->setCounty($row->county);
$entries[] = $entry;
}
return $entries;
}
/** ===========================================================================
* Create Array which will be used for Dropdown
* @param
* @return Array of Counties
* ========================================================================= */
public function createCountyDropdown()
{
// List of Counties does not exist in Cache, read from DB
if(!$CountyList = $this->getFromCache('counties'))
{
$CountyList = $this->getCountyList();
$Counties[''] = "Please choose";
foreach($CountyList as $value)
{
$Counties[str_replace(' ','_',$value->getCounty())] = $value->getCounty();
}
$CountyDropdown = $Counties;
// Save DB Result in Cache
$this->addToCache ('counties',$CountyDropdown);
return $CountyDropdown;
}else{
return $this->getFromCache('counties');
}
}
我在GeolocationMapper中读到的县。当您选择一个郡时,Towns和Postcodes会被读取,而不是通过Ajax调用地理位置映射器而不是createTownDropdown($ county),当一个城镇选择相同的过程但是调用loadPostcodes()的Ajax时,还有createPostcodeDropdown($ town) )。
这一切听起来是否正确或有任何建议我如何改善这一点?
我很抱歉,但我真的想添加另一个问题,因为我无法在任何地方找到答案...我还有一个图像上传,可以通过Ajax和jQuery工作。选择要上载的图像时,图像会直接显示。为此我动态创建一个带有图像src的输入元素。我没有找到其他方式将图像添加到Zend Form。是否有可能添加图像以正常显示图像?拥有一个img会更容易,因为我想使用jQuery Drag and Drop。非常感谢你们的帮助!