как использовать общую функцию в помощнике и компоненте в Cakephp

#cakephp #cakephp-2.0 #cakephp-2.3

#cakephp #cakephp-2.0 #cakephp-2.3

Вопрос:

Мы знакомы с компонентами и помощниками в CakePHP.

У меня есть компонент ABC и помощник XYZ, и оба имеют одинаковую функцию (всего около 2000 строк, всего 4000 строк). есть какой-либо способ использовать ту же функцию в контроллере и .Файлы CTP. нехорошо использовать одну и ту же функцию 2 раза.

любой метод, чтобы я мог использовать функцию компонента / помощника в помощнике / компоненте без перезаписи?

тот же метод в компоненте и помощнике >>

Компонент

класс DATAComponent расширяет компонент {

 public $components = array('Session', 'THmail');

public function UsaStateList()
{ /********/}
  

Помощник

 class LabHelper extends AppHelper {
    public function UsaStateList()
    { /********/}
}
  

Ответ №1:

Ну, вам придется что-то переписать, это не решит само по себе.

CakePHP по-прежнему является PHP, поэтому вы можете легко применять общие шаблоны, чтобы все оставалось СУХИМ. Вероятно, самым простым способом было бы переместить общую функциональность в служебный класс, который ваш компонент и помощник могут использовать внутри, оставив их общедоступный API неизменным.

Некоторые помощники CakePHPs делают что-то подобное, проверьте, например, time helper .

Черты также могут быть вариантом, в зависимости от объема совместно используемой функциональности и того, насколько она привязана к использованию в компоненте / помощнике.

Комментарии:

1. Я заметил, что на мой довольно старый ответ поступает больше голосов, и заметил награду. Это может быть неочевидно, но этот ответ был добавлен задолго до щедрости, т. Е. Это не тот подробный канонический ответ, который ищет @trante (хотя не уверен, что именно он / она ищет).

Ответ №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();
    }

}
  

Комментарии:

1. Если вы используете компоненты в помощниках, вы неправильно используете Cake MVC. Компоненты предназначены для контроллеров, а помощники — для представлений.

Ответ №3:

Простой ответ

Для общих функций в вашем приложении добавьте библиотеку или служебный класс.

app/Lib/MyClass.php

 class MyClass {

    public static function usaStateList() {
        // ...
    }
}
  

Затем добавьте это в начало любого файла, к которому вы хотите получить доступ к функции:

 App::uses('MyClass', 'Lib');
  

И вызывайте свою функцию везде, где вам нравится:

 $myClass = new MyClass();
$states = $myClass::usaStateList();
  

Лучший ответ

Мне кажется, что ваша конкретная проблема заключается в том, что вы хотите иметь возможность получать список состояний US как в вашем контроллере, так и в вашем представлении. Лучший способ сделать это — иметь таблицу базы данных состояний США.

  1. Создайте таблицу в своей базе данных с именем 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 
      
  2. Вставьте все состояния в виде данных в эту таблицу. Вы можете найти SQL-дампы в Интернете, в которых уже есть это для вас (например, как этот).

  3. Создайте модель UsState в CakePHP.

     /**
     * 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');
        }

    }
  

И если вы хотите получить доступ к этим состояниям в вашем представлении, тогда вы должны передать эти данные, как обычно, любым другим переменным.

Я полагаю, вы хотели бы сделать это, чтобы, возможно, у вас было меню выбора штатов США.

         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);
  

Ответ №4:

Я бы выбрал класс в папке 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() {...}
}
  

Ответ №5:

хорошо, вы хотите использовать одну функцию в компоненте и помощнике, я могу придумать 3 вещи, которые вы можете сделать:

  1. Вызов функции из компонента в вашем помощнике.
  2. Вызов функции из помощника в вашем компоненте.
  3. Создайте модель или используйте существующую модель, в которую вы помещаете функцию, и вы можете использовать эту функцию в своем компоненте или справке.

Вариант № 3: в вашем помощнике и компоненте вам необходимо импортировать модель, предполагая, что ваша функция находится в модели «StateList»:

как вы вызываете функцию модели «StateList» в вашем помощнике, так:

 App::import("Model", "StateList");  
$model = new StateList();  
$model->UsaStateList();
  

как вы вызываете функцию модели «StateList» в вашем компоненте, так:

 $model = ClassRegistry::init('StateList');
$model->UsaStateList();
  

и если вы хотите использовать ту же функцию в контроллере, просто:

 $this->loadModel('StateList');
$this->StateList->UsaStateList();
  

Комментарии:

1. $model = new StateList(); это плохо. $model = ClassRegistry::init('StateList'); подходит из любого места.