php - Zend Action Controller——重构攻略

标签 php model-view-controller zend-framework refactoring

我已经在 Zend Framework (1.10) 上构建了一个首次运行的 Web 服务,现在我正在寻找重构我的 Action Controllers 中的一些逻辑的方法,这样对我和其他人来说会更容易我的团队负责扩展和维护服务。

我可以看到哪里有重构的机会,但我不清楚关于如何重构的最佳策略。最好的 Controller 文档和教程只讨论小规模应用程序,并没有真正讨论如何抽象更大规模的重复代码。

我们的 Action Controller 的基本结构是:

  1. 从请求正文中提取 XML 消息 - 这包括针对特定于操作的 relaxNG 模式进行验证
  2. 准备 XML 响应
  3. 验证请求消息中的数据(无效数据会引发异常 - 一条消息会添加到立即发送的响应中)
  4. 执行数据库操作(选择/插入/更新/删除)
  5. 返回操作成功或失败,以及所需信息

一个简单的示例是此操作,它根据一组灵活的标准返回供应商列表:

class Api_VendorController extends Lib_Controller_Action
{  
    public function getDetailsAction()
    {
        try {
            $request = new Lib_XML_Request('1.0');
            $request->load($this->getRequest()->getRawBody(), dirname(__FILE__) . '/../resources/xml/relaxng/vendor/getDetails.xml');
        } catch (Lib_XML_Request_Exception $e) {
            // Log exception, if logger available
            if ($log = $this->getLog()) {
                $log->warn('API/Vendor/getDetails: Error validating incoming request message', $e);
            }

            // Elevate as general error
            throw new Zend_Controller_Action_Exception($e->getMessage(), 400);
        }

        $response = new Lib_XML_Response('API/vendor/getDetails');

        try {
            $criteria = array();
            $fields = $request->getElementsByTagName('field');
            for ($i = 0; $i < $fields->length; $i++) {
                $name = trim($fields->item($i)->attributes->getNamedItem('name')->nodeValue);
                if (!isset($criteria[$name])) {
                    $criteria[$name] = array();
                }
                $criteria[$name][] = trim($fields->item($i)->childNodes->item(0)->nodeValue);
            }

            $vendors = $this->_mappers['vendor']->find($criteria);
            if (count($vendors) < 1) {
                throw new Api_VendorController_Exception('Could not find any vendors matching your criteria');
            }

            $response->append('success');
            foreach ($vendors as $vendor) {
                $v = $vendor->toArray();
                $response->append('vendor', $v);
            }

        } catch (Api_VendorController_Exception $e) {
            // Send failure message
            $error = $response->append('error');
            $response->appendChild($error, 'message', $e->getMessage());

            // Log exception, if logger available
            if ($log = $this->getLog()) {
                $log->warn('API/Account/GetDetails: ' . $e->getMessage(), $e);
            }
        }

        echo $response->save();
    }
}

那么 - 知道我的 Controller 中的共性在哪里,重构的最佳策略是什么,同时保持它类似于 Zend 并且还可以使用 PHPUnit 进行测试?

我确实考虑过将更多的 Controller 逻辑抽象到父类 (Lib_Controller_Action) 中,但这使单元测试变得更加复杂,在我看来这是错误的。

最佳答案

两个想法(只是根据上面的评论创建一个答案):

  1. 将通用性下推到服务/存储库类中?这样的类是可测试的,可以跨 Controller 使用,并且可以使 Controller 代码更紧凑。

  2. 将通用性收集到 action helpers 中。

关于php - Zend Action Controller——重构攻略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8829613/

相关文章:

php - PHP 中的 use 和 require_once

php - MySQL 查询从 WordPress 数据库中获取最近的位置 WHERE 经度和纬度保存为后元

java - Spring MVC - 如何在下载开始前显示消息

email - Zend Framework 2 的原始字符串电子邮件

php - 如何在WordPress的同一页面中提交表单数据而不重新加载页面?

php - MYSQL 语法错误 : Where

model-view-controller - MVC-在哪里实现表单验证(服务器端)?

java - 找不到媒体类型 = 文本/html 的 MessageBodyWriter 但适用于 JSON

php - Zend_Form 单选元素

php - 如何通过 iframe 调用验证第三方网站