2

我正在从事用 CakePHP 编写的即将离任的专用项目,该项目变得相当大。该架构也使用了一堆插件。从项目一开始,这个应用程序只有一个实例。然而,客户发现该应用程序可以工作的另一个领域。它将使用相同的代码库但单独的数据库。问题是代码库实际上适用于大约 90%,这意味着在大多数情况下它会完成它的工作,但需要进行一些细微的更改。经过一些小的改进后,很明显这些修改将继续用于这个新实例。但同时会有适用于这两种情况的更改。对于在整个应用程序中创建一堆条件并检查哪个实例实际正在运行,这不是一个非常干净的解决方案。

所以我的想法是:

  • 将项目保存在一个存储库中,并在一个代码库中进行适用于所有实例的更改和修复
  • 制作某种“mod”,其中包含仅在需要时重载项目默认类的类,并且仅适用于特定实例
  • 为了更清楚,最好对包含这些新类的应用程序目录具有并行文件结构(当然只有那些需要的)
  • 很重要的一点是根本不碰蛋糕芯,我希望可以随时升级没有问题

例子:

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()标记为“实验性”即可。有什么建议或想法吗?

4

2 回答 2

2

那么有可能为 CakePHP 创建这样的模式,也许是在低级别的加载类上?我不想使用 runkit_method_redefine() 并替换例如 App::import() 方法,只要将 runkit_method_redefine() 标记为“实验性”。有什么建议或想法吗?

所有请求最初都通过app/webroot/index.php. 这个文件不是核心的一部分,可以自己修改。您可以做的是更改包含路径以列出您之前创建的文件夹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文件同时包含ConfigureApp类。)

简而言之,通过更改 中的一行app/webroot/index.php,您现在可以替换 CakePHP 核心的任何部分,而无需直接编辑它。

您现在可能能够进行所需的更改,App::import但是,由于这实际上并没有在任何地方记录,您的里程可能会有所不同。

于 2012-01-17T17:11:06.527 回答
1

所以我的想法是:

  • 将项目保存在一个存储库中,并在一个代码库中进行适用于所有实例的更改和修复
  • 制作某种“mod”,其中包含仅在需要时重载项目默认类的类,并且仅适用于特定实例
  • 为了更清楚,最好对包含这些新类(当然只有那些需要的类)的应用程序目录具有并行文件结构 - 非常重要的是根本不触及蛋糕核心,我想要可以随时升级而不会出现问题

我在之前的回答中谈到了这一点,但其他类路径听起来可能是您正在寻找的 CakePHP 功能。在你的“mod”应用程序中类似下面的内容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),
));

以上假设一个新的文件夹结构,而不是/appand /cake,看起来像这样:

- ROOT
|- app1 // look here first,
|- app2
|- core // then here,
|- cake // then lastly here.
于 2012-01-17T15:17:17.590 回答