[英]Codeigniter 3 - Third_party and controllers / loading ressources
我想使用/third_party/myapp/controllers
文件夹中的/third_party/myapp/controllers
而不必将它们移至/application/controllers
似乎不可能(至少没有破解内核)。 尽管该问题与加载模型有关,但这里提到了局限性
我不喜欢使用HMVC-如此处提出的解决方案所述,因为除了避免在CI基础文件夹中增加文件传输之外,我不需要任何其他功能(我真的不需要它的“分层”部分) )
但是我真的不明白。。。如果有人声明了third_party应用程序,CI将从那些文件夹中加载资源(如doc所述 )
配置/
助手/
语言/
图书馆/
楷模/
[形而上]为什么也不能简单地加载控制器?
[实用性]尝试破解核心系统还是个好主意,还是应该继续选择“ HMVC或复制文件”?
[乐观]有人解决方案吗?
在进一步寻找CI的另一个安装中的trajchevska技巧时,我尝试实现spl_register的DFriend示例。 我读了几次手册和这个答案 :到目前为止,我了解到在调用类时会触发spl_autoload_register,从而可以跳过其手动加载
因此,我尝试仅在application/config/config.php
中的配置文件末尾添加spl_autoload_register
,期望在调用第一个类时它会打印自动加载ClassName-天真,我知道。
但是据我了解(感谢DFriend),此spl_autoload_register不适用于控制器,因为CI会在尝试声明控制器之前始终检查文件是否存在(在其自己的路径中)。
另一方面,它似乎可以与其他类一起使用(核心,模型……请参见下面的DFriend答案)
因此,从我的头上拔了几根头发之后,我决定尝试使用WireDesign的 CI- MX HMVC扩展。 它解决了我从不同文件夹加载任何资源的问题,并带来了共享类的全新范围及其附带的问题(哪里有可用?)。
作为项目的开始,我有机会切换到“分层”方面,否则我听从了Dfriend的建议
顺其自然,并将控制器放置在CI希望第三方软件包使用的地方
我认为是因为路由过程-CI路由器检查应用程序文件夹中是否存在相应的控制器,或者在配置中定义了相应的路由。 如果未找到它们,则返回404。
您可以覆盖路由器文件以启用从其他位置加载控制器。 在核心文件夹中,创建一个MY_Router文件,该文件将扩展CI_Router。 然后扩展_validate_request函数,以允许从不同于默认路径的路径加载控制器文件。
更新:因此,我花了一些时间,没有设法扩展路由器以从第三方文件夹中获取控制器文件。 涉及默认控制器目录的子文件夹很容易,但是设置一个自定义目录来读取控制器并不是那么简单,不幸的是,我找不到关于它的任何文档。
您可以使用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
或其他文件,可以使用挂钩。 这是一种方法。
application / config / config.php
$config['enable_hooks'] = TRUE;
application / config / hooks.php
$hook['pre_system'][] = array(
'class' => '',
'function' => 'register_autoloader',
'filename' => 'Auto_load.php',
'filepath' => 'hooks'
);
application / 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坚持认为Controllers在application/controllers
目录或其子目录中。
当您尝试使用尚未定义的类/接口时,PHP将运行一个已注册的自动加载器。 控制器是php类,因此您可能希望有一个自动加载器来解救。 但是CI对于在哪里查找控制器文件非常明确。 如果找不到该文件,则它将从不尝试对该类进行任何调用。 相反,它放弃了所有希望,并立即发出404错误。 自动装带器永远没有机会查找文件。
形而上学问题的答案是CI的路由和URL解析与文件存储结构紧密耦合,因此无法实现所需的功能。 (没有一些严重的核心黑客攻击)
务实问题的答案是非常主观的。 我不喜欢HMVC方法,因此我个人会选择顺其自然,并在CI希望的地方将第三方程序包的控制器放到这里。
开始:从眼前的问题严重转移
那么,在CI环境中注册自动加载器有什么好处?
像这样定义控制器。
class Home extends CI_Controller{ ...
扩展的类CI_Controller
是核心类。 如果要扩展此核心类以供其他多个控制器使用,则可以使用CI约定,在类名前加上“ MY_”。 例如
class MY_Controller extends CI_Controller
(
//class implementation
}
然后使用它通过扩展核心类定义实际的控制器
class Home extends MY_Controller{ ...
问题在于,使用此约定只能扩展一次核心CI_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;
}
}
}
请注意,以上内容还允许您从其他模型扩展模型。
结束:严重地转移了手头的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.