我们熟悉CakePHP中的组件和助手。
我有一个ABC组件和XYZ助手,两者都有相同的功能(大约2000行总计4000行)。 有没有办法在Controller和.CTP文件中使用相同的功能。 2次使用相同的功能并不好。
任何方法,所以我可以在Helper / Component中使用Component / Helper函数而不重写?
与组件和帮助器相同的方法>>
组件
class DATAComponent扩展Component {
public $components = array('Session', 'THmail');
public function UsaStateList()
{ /********/}
帮助
class LabHelper extends AppHelper {
public function UsaStateList()
{ /********/}
}
答案 0 :(得分:8)
好吧,你必须重写某些东西,它不会自己解决。
CakePHP仍然是PHP,因此您可以轻松应用常用模式来保持DRY。最直接的方法可能是将共享功能移动到一个实用程序类中,组件和帮助程序可以在内部使用,同时保持公共API不变。
一些CakePHP帮助程序执行类似操作,例如检查时间帮助程序。
Traits也可能是一个选项,具体取决于共享的功能数量以及它与组件/帮助器中的使用量的关系。
答案 1 :(得分:2)
我想在帮助器中使用一个组件。所以我提出了以下解决方案。
<?php
App::uses('AppHelper', 'View/Helper');
App::import('Component', 'MyComponent');
class MyHelperHelper extends AppHelper {
private $MyComponent = null;
public function __construct(View $View, $settings = array()) {
$collection = new ComponentCollection();
$this->MyComponent = new MyComponentComponent($collection);
parent::__construct($View, $settings);
}
public function myCustomFunction() {
return $this->MyComponent->myCustomFunction();
}
}
答案 2 :(得分:2)
我会选择Lib文件夹中的一个类。很清楚如何处理只有静态方法的库类。所以,我省略了这个案子。用于实例化类的可行解决方案可以是在控制器中创建它并将其放入注册表中。如果您确实需要访问CakeRequest,CakeResponse和CakeSession(请注意CakeSession有许多静态方法,因此您通常不需要该类的实例),您可以从控制器中设置它:
$MyLib = new MyLib();
$MyLib->setRequest($this->request); // optional
ClassRegistry::addObject('MyLib', $MyLib);
然后从视图或任何其他地方,您只需从注册表中获取MyLib的实例:
ClassRegistry::getObject('MyLib');
或只是
$list = ClassRegistry::getObject('MyLib')->UsaStateList();
所以,你的课将是这样的:
// /Lib/MyLib.php
class MyLib {
public function setRequest(CakeRequest request) {...}
public function UsaStateList() {...}
}
答案 3 :(得分:1)
好的,你想在组件和助手中使用单个函数,我可以想到你可以做的3件事:
选项numbre 3: 在你的帮助器和组件中,你需要导入一个模型,假设你的函数在模型中#34; StateList&#34;:
如何调用模型的功能&#34; StateList&#34;在你的助手中,所以:
App::import("Model", "StateList");
$model = new StateList();
$model->UsaStateList();
如何调用模型的功能&#34; StateList&#34;在您的组件中,所以:
$model = ClassRegistry::init('StateList');
$model->UsaStateList();
如果你想在控制器中使用相同的功能:
$this->loadModel('StateList');
$this->StateList->UsaStateList();
答案 4 :(得分:1)
简单回答
对于整个应用程序中的常用功能,请添加Lib或Utility类。
应用程序/ LIB / MyClass.php
class MyClass {
public static function usaStateList() {
// ...
}
}
然后将此项添加到您要访问该功能的文件的顶部:
App::uses('MyClass', 'Lib');
并随时随地调用您的函数:
$myClass = new MyClass();
$states = $myClass::usaStateList();
更好的答案
在我看来,您的具体问题是您希望能够在控制器和视图中获得美国州的列表。执行此操作的最佳方法是拥有美国各州的数据库表。
在数据库中创建一个名为 us_states 的表。
示例SQL:
CREATE TABLE `us_states` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(20) NOT NULL,
`abbreviation` CHAR(2) NOT NULL
) ENGINE = MYISAM
将所有状态作为数据插入该表中。您可以在Internet上找到已经为您准备的SQL转储(例如Like this one)。
在CakePHP中创建一个UsState模型。
/**
* Model for US States
*
* @package app.Model
*/
class UsState extends AppModel {
/**
* Default sort order
*
* @var string|array
*/
public $order = 'UsState.name';
}
您可以做的就是使用模型从控制器访问状态。
/**
* Your Controller
*
* @package app.Controller
*/
class YourController extends AppController {
public function index() {
// Get a list of US states
$this->loadModel('UsState');
$states = $this->UsState->find('all');
}
}
如果您想在View中访问这些状态,那么您应该像通常的其他变量一样传递该数据。
我想你会想要这样做,所以你可以选择美国各州的选择菜单。
public function index() {
// Get a list of US states
$this->loadModel('UsState');
$states = $this->UsState->find('all');
// Make the states into an array we can use for a select menu
$stateOptions = array();
foreach ($states as $state) {
$stateOptions[$state['id']] = $state['name'];
}
// Send the options to the View
$this->set(compact('stateOptions'));
}
在您的视图中,您可以显示如下选择菜单:
echo $this->Form->select('us_state_id', $stateOptions);