【问题标题】:Custom classes in CodeIgniterCodeIgniter 中的自定义类
【发布时间】:2012-03-19 16:15:51
【问题描述】:

对于 CodeIgniter 的初学者来说,这似乎是一个非常常见的问题,但到目前为止我找到的解决方案似乎都与我的问题无关。就像主题说的那样,我正在尝试在 CodeIgniter 中包含一个自定义类。

我正在尝试创建下面类的几个对象并将它们放在一个数组中,因此我需要该类可用于模型。

我尝试在 CodeIgniter 中使用 load (library->load('myclass') 函数,但它首先尝试在模型之外创建类的对象。这显然是一个问题,因为构造函数需要几个参数。

到目前为止我找到的解决方案是

  1. 一个简单的 php 包含似乎足够好,但因为我是新手 CodeIgniter 我想确保我坚持下去 可能。
  2. 按照here 的建议创建一个“包装器类”,但是我不确定如何实现它。

我想包括的课程, 用户.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
class User{
    public $ID = 0;
    public $username = 0;
    public $access_lvl = 0;
    public $staff_type = 0;
    public $name = 0;    

    public function __construct($ID, $username, $access_lvl, $staff_type, $name) 
    {
        $this->ID = $ID;
        $this->username = $username;
        $this->access_lvl = $access_lvl;
        $this->staff_type = $staff_type;
        $this->name = $name;
    }

    public function __toString() 
    {
        return $this->username;
    }
}
?>

需要User.php的方法(模型)

function get_all_users()
{
    $query = $this->db->get('tt_login');
    $arr = array();

    foreach ($query->result_array() as $row)
    {
        $arr[] = new User
        (
            $row['login_ID'],
            $row['login_user'],
            $row['login_super'],
            $row['crew_type'],
            $row['login_name']
        );
    }    

    return $arr;
}

最后是控制器,

function index()
{
        $this->load->library('user');
        $this->load->model('admin/usersmodel', '', true);            

        // Page title
        $data['title'] = "Some title";
        // Heading
        $data['heading'] = "Some heading";
        // Data (users)
        $data['users'] = $this->usersmodel->get_all_users();

【问题讨论】:

    标签: php codeigniter


    【解决方案1】:

    18 小时后,我设法在没有初始化的情况下在我的控件中包含了一个库(构造函数是问题所在,因此我无法使用标准的 codeiginiter $this-&gt;load-&gt;library() )。 关注https://stackoverflow.com/a/21858556/4701133。注意进一步的原生类初始化使用$date = new \DateTime()前面带有反斜杠,否则函数将产生错误!

    【讨论】:

      【解决方案2】:

      经过简短的谷歌搜索后,我受到启发,制作了自己的自动加载器类。这有点 hack,因为我使用自定义 Codeigniter 库来执行自动加载,但对我来说,这是我知道的加载所有类的最佳方式,我需要,而不会影响我的应用程序架构理念, 使其适合 Codeigniter 的做事方式。有些人可能会争辩说 Codeigniter 对我来说不是正确的框架,这可能是真的,但我正在尝试各种框架并玩弄各种框架,并且在从事 CI 工作时,我想出了这个解决方案。 1. 通过编辑 applicaion/config/autoload.php 来自动加载新的自定义库:

      $autoload['libraries'] = array('my_loader');
      

      以及您可能需要的任何其他库。 2.然后添加库类My_loader。此类将在每个请求上加载,并且当其构造函数运行时,它将递归搜索所有子文件夹并 require_once application/service 和 application/models/dto 文件夹中的所有 .php 文件。警告:文件夹名称中不应包含点,否则功能将失败

      <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
      
      class My_loader {
      
          protected static $_packages = array(
                  'service',
                  'models/dto'
                  );
      
          /**
           * Constructor loads service & dto classes
           * 
           * @return void
           */
          public function __construct($packages = array('service', 'models/dto'))
          {
              // files to be required
              $toBeRequired = array();
      
              // itrate through packages
              foreach ($packages as $package) {
                  $path = realpath(APPPATH . '/' . $package . '/');
                  $toBeRequired = array_merge($toBeRequired, $this->findAllPhpFiles($path));
              }
      
              /**
               * Require all files
               */
              foreach ($toBeRequired as $class) {
                  require_once $class;
              }
          }
      
          /**
           * Find all files in the folder
           * 
           * @param string $package
           * @return string[]
           */
          public function findAllPhpFiles($path)
          {
              $filesArray = array();
              // find everithing in the folder
              $all = scandir($path);
              // get all the folders
              $folders = array_filter($all, get_called_class() . '::_folderFilter');
              // get all the files
              $files = array_filter($all, get_called_class() . '::_limitationFilter');
      
              // assemble paths to the files
              foreach ($files as $file) {
                  $filesArray[] = $path . '/' . $file;
              }
              // recursively go through all the sub-folders
              foreach ($folders as $folder) {
                  $filesArray = array_merge($filesArray, $this->findAllPhpFiles($path . '/' . $folder));
              }
      
              return $filesArray;
          }
      
          /**
           * Callback function used to filter out array members containing unwanted text
           * 
           * @param string $string
           * @return boolean
           */
          protected static function _folderFilter($member) {
              $unwantedString = '.';
              return strpos($member, $unwantedString) === false;
          }
      
          /**
           * Callback function used to filter out array members not containing wanted text
           *
           * @param string $string
           * @return boolean
           */
          protected static function _limitationFilter($member) {
              $wantedString = '.php';
              return strpos($member, $wantedString) !== false;
          }
      }
      

      【讨论】:

        【解决方案3】:

        如果您的 PHP 版本 >= 5.3,则可以使用 namespacesautoloading 功能。

        库文件夹中的一个简单的自动加载器库。

        <?php
        class CustomAutoloader{
        
            public function __construct(){
                spl_autoload_register(array($this, 'loader'));
            }
        
            public function loader($className){
                if (substr($className, 0, 6) == 'models')
                    require  APPPATH .  str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php';
            }
        
        }
        ?>
        

        模型目录中的用户对象。 (模型/User.php)

        <?php 
        namespace models; // set namespace
        if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
        class User{
         ...
        }
        

        而不是 new User... new models\User ( ... )

        function get_all_users(){
            ....
            $arr[] = new models\User(
            $row['login_ID'],
            $row['login_user'],
            $row['login_super'],
            $row['crew_type'],
            $row['login_name']
            );
            ...
        }
        

        在控制器中,请确保像这样调用 customautoloader:

        function index()
        {
                $this->load->library('customautoloader');
                $this->load->model('admin/usersmodel', '', true);            
        
                // Page title
                $data['title'] = "Some title";
                // Heading
                $data['heading'] = "Some heading";
                // Data (users)
                $data['users'] = $this->usersmodel->get_all_users();
        

        【讨论】:

        • 在没有命名空间的情况下使用它会有什么后果?或者命名空间是否允许我们在我们定义了自定义类的服务器上的文件结构中工作?
        【解决方案4】:

        CodeIgniter 并不真正支持真实的对象。 所有的库、模型等都像单例。

        在不改变 CodeIgniter 结构的情况下有 2 种方法。

        1. 只需包含包含该类的文件,并生成它。

        2. 使用 load->library 或 load_class() 方法,然后创建新对象。这样做的缺点是,它总是会生成 1 个额外的对象,而您根本不需要。但最终加载方法也会包含该文件。

        另一种可能需要一些额外工作的方法是创建一个 User_Factory 库。 然后,您可以在文件底部添加对象,并从工厂创建它的新实例。

        我自己是工厂模式的忠实粉丝,但这是你必须自己做出的决定。

        我希望这对您有所帮助,如果您有任何与实施更相关的问题,请告诉我/我们。

        【讨论】:

        • 你能给我链接这种方法的任何例子吗?
        【解决方案5】:

        Codeigniter 有一个通用的函数来实例化各个类。

        它被称为 load_class(),在 /system/core/Common.php

        中找到

        函数;

        /**
        * Class registry
        *
        * This function acts as a singleton.  If the requested class does not
        * exist it is instantiated and set to a static variable.  If it has
        * previously been instantiated the variable is returned.
        *
        * @access   public
        * @param    string  the class name being requested
        * @param    string  the directory where the class should be found
        * @param    string  the class name prefix
        * @return   object
        */
        

        签名是

        load_class($class, $directory = 'libraries', $prefix = 'CI_')
        

        使用它的一个例子是调用 show_404() 函数时。

        【讨论】:

        • 据我所知,使用这种方法在模型之外还剩下一个额外的对象?除非有办法避免这种情况,否则我猜我将不得不使用标准包含。
        【解决方案6】:

        包含一个类文件不是一个坏方法。

        在我们的项目中,我们也是这样做的,在 MVC 中添加另一个层,这就是控制器调用和服务调用模型的服务层。我们引入了这一层来单独添加业务逻辑。

        到目前为止,我们一直在使用它,我们的产品也变得很大,但我们仍然没有发现包含我们过去制作的文件的决定。

        【讨论】:

        • @itachi :在你看来,没有必要,世界看到的都是一样的。我的回答是让用户确信直接包含文件不是一个错误的想法。 :)
        • 基本上这就是您在包括 Java 在内的任何其他语言中所做的。唯一的区别是你称他们为imports,在这里你称他们为includes
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-28
        • 1970-01-01
        相关资源
        最近更新 更多