Cake PHP - создание своего рода мода для приложения - PullRequest
2 голосов
/ 17 января 2012

Я работаю над исходящим специализированным проектом, написанным на CakePHP, который стал довольно большим Архитектура также использует множество плагинов. С самого начала проекта был только один экземпляр этого приложения. Однако Клиент обнаружил еще одну область, в которой приложение может работать. Он будет использовать ту же кодовую базу, но отдельную базу данных. Дело в том, что кодовая база фактически применима примерно на 90%, что означает, что в большинстве случаев она будет выполнять свою работу, но есть некоторые небольшие изменения, которые необходимы. После некоторых небольших улучшений становится ясно, что эти изменения будут продолжены для этого нового экземпляра. Но в то же время будут изменения, применимые для обоих случаев. Это не было бы очень чистым решением для создания множества условий во всем приложении и проверки того, какой экземпляр действительно работает.

Итак, моя идея:

  • хранить проект в одном репозитории и вносить изменения и исправления, применимые ко всем экземплярам в одной кодовой базе
  • создайте своего рода "мод", который будет содержать классы, которые будут перегружать классы по умолчанию проекта только при необходимости и только для конкретного экземпляра
  • Для большей ясности было бы лучше иметь параллельную файловую структуру с каталогом приложения, который будет содержать эти новые классы (конечно, только те, которые необходимы)
  • очень важно вообще не трогать ядро ​​пирога, я хочу иметь возможность обновить его в любое время без проблем

Пример:

app/controllers/invoices_controller.php:
InvoicesController extends AppController {
  public function generateInvoice() {}
}

newbusinness/controllers/invoices_controller.php:
NewbusinessInvoicesController extends InvoicesController {
  public function generateInvoice() {}
}

Что важно, когда мы перейдем к:

www.mynewbusinnes.com/Invoices/generateInvoice

система автоматически вызовет NewbusinessInvoicesController->generateInvoice(), поскольку такой дочерний контроллер и метод существуют. В противном случае он вызовет контроллеры и методы по умолчанию.

Так можно ли создать такой режим для CakePHP, может быть, при низком уровне загрузки классов? Я не хотел бы использовать runkit_method_redefine() и заменить, например, метод App::import(), если runkit_method_redefine() помечен как «экспериментальный». Есть предложения или идеи?

Ответы [ 2 ]

2 голосов
/ 17 января 2012

Так можно ли создать такой режим для CakePHP, может быть, при низком уровне загрузки классов?Я не хотел бы использовать runkit_method_redefine () и заменить, например, метод App :: import (), если runkit_method_redefine () помечен как «экспериментальный».Любые предложения или идеи?

Все запросы изначально проходят через app/webroot/index.php.Этот файл не является частью ядра и может быть изменен вами.Что вы можете сделать, это изменить include paths , чтобы получить список папок вашего собственного создания до CAKE_CORE_INCLUDE_PATH.Здесь я задаю /absolute/path/to/custom в качестве пути включения:

if (function_exists('ini_set') && ini_set('include_path', ROOT . DS . 'custom' . PATH_SEPARATOR . CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ROOT . DS . APP_DIR . DS . PATH_SEPARATOR . ini_get('include_path'))) {

После этого раздела загружается файл начальной загрузки CakePHP (/cake/bootstrap.php) и начинается загрузка многих классов ядра:

require CORE_PATH . 'cake' . DS . 'basics.php';
$TIME_START = getMicrotime();
require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php';
require LIBS . 'object.php';
require LIBS . 'inflector.php';
require LIBS . 'configure.php';
require LIBS . 'set.php';
require LIBS . 'cache.php';
Configure::getInstance();
require CAKE . 'dispatcher.php';

Вставив свой собственный путь включения, вы можете заменить их, скопировав их в этот путь:

ROOT
|- app/
|- cake/
  |- libs/
    |- configure.php // this would usually be loaded
|- custom/
  |- cake/
    |- libs/
      |- configure.php // now this is loaded

(Примечание: файл configure.php содержит классы Configure и App.)

Короче говоря, изменив одну строку в app/webroot/index.php, теперь вы можете заменить любую часть ядра CakePHP, не редактируя ее напрямую.

Теперь вы можете вносить необходимые изменения вApp::import но, поскольку это нигде не задокументировано, ваш пробег может отличаться.

1 голос
/ 17 января 2012

Итак, моя идея такова:

  • хранить проект в одном репозитории и вносить изменения и исправления, применимые ко всем экземплярам в одной кодовой базе
  • сделать что-то вроде "мода"«который будет содержать классы, которые будут перегружать классы по умолчанию проекта только тогда, когда это необходимо, и только для конкретного экземпляра
  • , чтобы сделать его более понятным, лучше всего иметь параллельную структуру файла с каталогом приложения, который будет содержатьэти новые классы (конечно, только те, которые нужны) - очень важно, чтобы вообще не трогать ядро ​​пирога, я хочу иметь возможность обновить его в любое время без проблем

Я коснулсяоб этом в предыдущем ответе , но дополнительных путей к классам звучит так, как будто это может быть функция CakePHP, которую вы ищете.Что-то вроде следующего в bootstap.php вашего приложения-мода должно указывать CakePHP также загружать файлы из каталога core:

App::build(array(
    'plugins'     => array(ROOT . DS . 'core' . DS . 'plugins' . DS),
    'models'      => array(ROOT . DS . 'core' . DS . 'models' . DS),
    'views'       => array(ROOT . DS . 'core' . DS . 'views' . DS),
    'controllers' => array(ROOT . DS . 'core' . DS . 'controllers' . DS),
    'datasources' => array(ROOT . DS . 'core' . DS . 'models' . DS . 'datasources' . DS),
    'behaviors'   => array(ROOT . DS . 'core' . DS . 'models' . DS . 'behaviors' . DS),
    'components'  => array(ROOT . DS . 'core' . DS . 'controllers' . DS . 'components' . DS),
    'helpers'     => array(ROOT . DS . 'core' . DS . 'views' . DS . 'helpers' . DS),
    'vendors'     => array(ROOT . DS . 'core' . DS . 'vendors' . DS),
    'shells'      => array(ROOT . DS . 'core' . DS . 'vendors' . DS . 'shells' . DS),
    'locales'     => array(ROOT . DS . 'core' . DS . 'locale' . DS),
));

Выше предполагается, что новая структура папок вместо /app и /cake, выглядит так:

- ROOT
|- app1 // look here first,
|- app2
|- core // then here,
|- cake // then lastly here.
...