php CodeIgniter 中的自定义类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9511636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 06:58:58  来源:igfitidea点击:

Custom classes in CodeIgniter

phpcodeigniter

提问by Index

Seems like this is a very common problem for beginners with CodeIgniter, but none of the solutions I've found so far seems very relevant to my problem. Like the topic says I'm trying to include a custom class in CodeIgniter.

对于使用 CodeIgniter 的初学者来说,这似乎是一个非常常见的问题,但到目前为止我发现的所有解决方案似乎都与我的问题无关。就像这个话题说我试图在 CodeIgniter 中包含一个自定义类。

I'm trying to create several objects of the class below and place them in an array, thus I need the class to be available to the model.

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

I've tried using the load (library->load('myclass') functions within CodeIgniter which sort of works, except it tries to create an object of the class outside the model first. This is obviously a problem since the constructor expects several parameters.

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

The solutions I've found so far is

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

  1. A simple php include which seems fine enough, but since I'm new to CodeIgniter I want to make sure I'm sticking to it as much as possible.
  2. Creating a "wrapper class" as suggested here, however I'm uncertain how I would implement this.
  1. 一个简单的 php 包含看起来足够好,但由于我是 CodeIgniter 的新手,我想确保我尽可能地坚持使用它。
  2. 按照此处的建议创建“包装器类” ,但是我不确定如何实现它。

The class I want to include, User.php

我想包含的类 User.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;
    }
}
?>

Method (Model) which needs the User.php

需要 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;
}

And finally the controller,

最后是控制器,

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();

采纳答案by Petter Kjelkenes

If you have PHP version >= 5.3 you could take use of namespacesand autoloadingfeatures.

如果您的 PHP 版本 >= 5.3,您可以使用命名空间自动加载功能。

A simple autoloader library in the library folder.

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

<?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';
    }

}
?>

The User object in the model dir. ( models/User.php )

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

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

And instead of new User... new models\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']
    );
    ...
}

And in controller just make sure to call the customautoloader like this:

在控制器中只需确保像这样调用 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();

回答by Nico Kaag

CodeIgniter doesn't really support real Objects. All the libraries, models and such, are like Singletons.

CodeIgniter 并不真正支持真正的对象。所有的库、模型等等,都像单身人士。

There are 2 ways to go, without changing the CodeIgniter structure.

有两种方法可以走,而无需更改 CodeIgniter 结构。

  1. Just include the file which contains the class, and generate it.

  2. Use the load->library or load_class() method, and just create new objects. The downside of this, is that it will always generate 1 extra object, that you just don't need. But eventually the load methods will also include the file.

  1. 只需包含包含类的文件,然后生成它。

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

Another possibility, which will require some extra work, is to make a User_Factory library. You can then just add the object on the bottom of the file, and create new instances of it from the factory.

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

I'm a big fan of the Factory pattern myself, but it's a decision you have to make yourself.

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

I hope this helped you, if you have any questions that are more related to the implementation, just let me/us know.

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

回答by linuxeasy

Including a class file is not a bad approach.

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

In our projects, we do the same, add an another layer to MVC, and thats a Service Layer which the Controllers calls and Service calls the Model. We introduced this layer to add Business Logic seperate.

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

So far, we have been using it, and our product has gone large too, and still we find no difficulty with the decision of including files that we had made in the past.

到目前为止,我们一直在使用它,我们的产品也变大了,我们仍然没有发现我们过去所做的包含文件的决定有什么困难。

回答by Rooneyl

Codeigniter has a common function to instantiate individual classes.

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

It is called load_class(), found in /system/core/Common.php

它称为load_class(),位于/system/core/Common.php

The function;

功能;

/**
* 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
*/

The signature is

签名是

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

An example of it being used is when you call the show_404()function.

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

回答by Ajant

After a brief google search, I was inspired to make my own autoloader class. It's a bit of a hack, since I use custom Codeigniter library to preform auto-loading, but for me this is the best way, that I'm aware of, of loading all the classes, I require, without compromising my application architecture philosophy, to fit it into Codeigniter way of doing things. Some might argue that Codeigniter is not the right framework for me and that might be true, but I'm trying things out and playing around with various frameworks and while working on CI, I came up with this solution. 1. Auto-load new custom library by editing applicaion/config/autoload.php to include:

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

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

and any other libraries you might need. 2. Then add library class My_loader. This class will be loaded on every request and when its constructor is run, it will recursively search through all sub-folders and require_once all .php files inside application/service & application/models/dto folders. Warning: folders should not have dot in the name, otherwise function will fail

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

<?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;
    }
}

回答by Elias Debs

After 18 hours I managed to include a library in my control without initialisation (the constructor was the problem, because of that and i could't use the standard codeiginiter $this->load->library()). Follow the https://stackoverflow.com/a/21858556/4701133. Be aware for further native class initialization use $date = new \DateTime()with back-slash in front otherwise the function will generate an error !

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