我想使用/third_party/myapp/controllers
文件夹中的控制器,而不必将它们移到/application/controllers
似乎不可能(至少没有黑客攻击核心)。虽然问题涉及加载模型,但提到了限制here
我不想使用HMVC - 正如在那里提出的解决方案中所述,因为我不需要任何其他功能而不是避免在CI基本文件夹中繁殖文件传输(我真的不需要'层次'部分内容)
但我真的不明白......如果一个人声明了它的third_party应用程序,CI将从这些文件夹中加载资源(如the doc所述)
配置/
助手/
语言/
库/
模型/
[形而上学] 为什么不能简单地加载控制器呢?
[实用] 尝试破解核心系统是一个好主意,还是应该留在“HMVC或复制文件”中?
[乐观] 有人有解决方案吗?
在另一个CI安装中进一步查看trajchevska提示时,我尝试实现了splriregister的DFriend示例。我多次阅读手册和answer: 到目前为止,我知道在调用类时会触发spl_autoload_register,这允许跳过他们的手动加载
所以我尝试在spl_autoload_register
的配置文件末尾添加application/config/config.php
,希望在调用第一个类时打印自动加载ClassName - 我知道,有点天真。
但是根据我的理解(感谢DFriend),这个spl_autoload_register不能与控制器一起使用,因为CI会在尝试声明控制器之前检查文件是否存在(在自己的路径中)。
另一方面,它可能适用于其他类(核心,模型......请参阅下面的DFriend答案)
所以,在我的脑袋里拔出几根头发后,我决定尝试使用HMVC扩展CI - MX from WireDesign。它解决了我从不同文件夹加载任何资源的问题,同时带来了一个全新的共享类及其附加问题(可用的地方?)。
由于这是项目的开始,我有机会切换到“等级”方面,否则我会遵循Dfriend的建议
使用流程并为第三方软件包安装控制器 CI期望他们
答案 0 :(得分:1)
我认为是因为路由过程 - CI路由器检查应用程序文件夹中是否存在相应的控制器,或者在配置中定义了相应的路由。如果未找到它们,则返回404。
您可以覆盖路由器文件以启用从其他位置加载控制器。在核心文件夹中,创建一个将扩展CI_Router的MY_Router文件。然后扩展_validate_request函数,以允许从不同于默认路径的路径加载控制器文件。
更新:所以,我花了一些时间在这上面,并没有设法扩展路由器从第三方文件夹获取控制器文件。当涉及到默认控制器目录的子文件夹时,它很容易做到,但设置一个用于读取控制器的自定义目录并不是那么简单,不幸的是,我无法找到任何文档。
答案 1 :(得分:1)
您可以使用PHP spl_autoload_register
来实现自动加载器。谷歌搜索将揭示在CI框架内使用一种方法的多种方法。
一个有效且经常被描述的是在config.php中注册自动加载器,或者可能是特定于站点的常量文件。这样的解决方案是将这样的东西放在上面提到的文件中。
spl_autoload_register(function($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.`/third_party/myapp/controllers/`.$class.'.php'))
{
require_once $file;
}
}
});
如果您想避免攻击config.php
或其他文件,可以使用挂钩。这是实现这一目标的一种方法。
应用/配置/ config.php中
$config['enable_hooks'] = TRUE;
应用/配置/ hooks.php
$hook['pre_system'][] = array(
'class' => '',
'function' => 'register_autoloader',
'filename' => 'Auto_load.php',
'filepath' => 'hooks'
);
应用/钩/ Auto_load.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
function register_autoloader()
{
spl_autoload_register('my_autoloader');
}
function my_autoloader($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.`/third_party/myapp/controllers/`.$class.'.php'))
{
require_once $file;
}
}
}
<强>附录强>
在进一步挖掘和考虑时,上述操作无效,因为CI坚持控制器位于application/controllers
目录或其子目录中。
当您尝试使用尚未定义的类/接口时,PHP将运行已注册的自动加载器。控制器是php类,所以你可能希望自动加载器能够解决问题。但CI非常明确地查找控制器文件的位置。如果找不到该文件,则它永远不会尝试对该类进行任何调用。相反,它放弃了所有希望并立即发出404错误。自动加载器永远不会有机会查找文件。
形而上学问题的答案是CI的路由和URL解析与文件存储结构紧密耦合,使得所需的功能变得不可能。 (没有一些严重的核心黑客攻击)
实用问题的答案是非常主观的。我不喜欢HMVC方法,并且个人会选择使用流程并将控制器放在CI期望的第三方软件包中。
开始:手头的问题严重转移
那么,在CI环境中注册自动加载器有什么用呢?
控制器的定义如下。
class Home extends CI_Controller{ ...
正在扩展的类CI_Controller
是一个核心类。如果要扩展此核心类以供多个其他控制器使用,可以使用CI约定,在类名前加上&#34; MY _&#34;。 e.g。
class MY_Controller extends CI_Controller
(
//class implementation
}
然后使用它来定义使用扩展核心类的实际控制器
class Home extends MY_Controller{ ...
问题是您只能使用此约定扩展核心CI_Controller
。如果您需要对CI_Controller
核心类进行多次扩展,该怎么办?一种解决方案是注册自动加载器。 (关于克服MY_Controller垄断的这个和其他方法的一个很好的讨论是HERE。)
用于这些目的的自动加载器可以看这个。
spl_autoload_register(function($class)
{
if(strpos($class, 'CI_') !== 0)
{
if(file_exists($file = APPPATH.'libraries/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'models/'.$class.'.php'))
{
require_once $file;
}
elseif(file_exists($file = APPPATH.'core/'.$class.'.php'))
{
require_once $file;
}
}
}
请注意,上述内容还允许您从其他模型扩展模型。
结束:手头的问题严重转移