繁体   English   中英

Codeigniter 3-第三方和控制器/加载资源

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM