Codeigniter 3 - Third_party和控制器/加载资源

时间:2016-06-09 13:21:59

标签: php codeigniter path

我想使用/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期望他们

2 个答案:

答案 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;
    }
  }
}

请注意,上述内容还允许您从其他模型扩展模型。

  

结束:手头的问题严重转移