Пользовательские классы в CodeIgniter
Похоже, это очень распространенная проблема для новичков с CodeIgniter, но ни одно из решений, которые я нашел до сих пор, не очень уместно для моей проблемы. Как и в этой теме, я пытаюсь включить пользовательский класс в CodeIgniter.
Я пытаюсь создать несколько объектов класса ниже и поместить их в массив, поэтому мне нужен класс, который будет доступен для модели.
Я попытался использовать функции load (library- > load ('myclass') в CodeIgniter, которые работают, за исключением того, что он пытается сначала создать объект класса за пределами модели. Это, очевидно, проблема, поскольку конструктор ожидает несколько параметров.
Решения, которые я нашел до сих пор,
- Простой php включает, который кажется достаточно хорошим, но поскольку я новичок в
CodeIgniter Я хочу, чтобы убедиться, что я придерживаюсь его столько, сколько
возможно.
- Создание "класса-оболочки", как предлагается здесь, однако я не уверен, как это реализовать.
Класс, который я хочу включить,
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;
}
}
?>
Метод (модель), которому требуется 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();
Ответы
Ответ 1
Если у вас есть версия PHP >= 5.3, вы можете использовать функции namespaces и для автозагрузки.
Простая библиотека автозагрузчика в папке библиотеки.
<?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 в каталоге модели. (модели/User.php)
<?php
namespace models; // set namespace
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class 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();
Ответ 2
CodeIgniter действительно не поддерживает реальные объекты.
Все библиотеки, модели и т.д. Похожи на синглтоны.
Есть два способа пойти, не меняя структуру CodeIgniter.
-
Просто включите файл, который содержит класс, и сгенерируйте его.
-
Используйте библиотеку load- > library или load_class() и просто создавайте новые объекты. Недостатком этого является то, что он всегда будет генерировать 1 дополнительный объект, который вам просто не нужен. Но в конечном итоге методы загрузки также будут содержать файл.
Другая возможность, которая потребует некоторой дополнительной работы, - создать библиотеку User_Factory.
Затем вы можете просто добавить объект в нижней части файла и создать новые экземпляры его из factory.
Я большой поклонник шаблона Factory, но это решение, которое вы должны сделать сами.
Надеюсь, это помогло вам, если у вас возникнут вопросы, связанные с реализацией, просто позвольте мне/нам знать.
Ответ 3
Включение файла класса не является плохим подходом.
В наших проектах мы делаем то же самое, добавляем еще один слой в MVC, и это уровень обслуживания, который вызываются контроллерами, а служба вызывает модель. Мы ввели этот слой, чтобы добавить Business Logic отдельно.
До сих пор мы использовали его, и наш продукт тоже стал большим, и все же мы не испытываем затруднений с решением включить файлы, которые мы делали в прошлом.
Ответ 4
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().
Ответ 5
После краткого поиска Google я был вдохновлен сделать свой собственный класс автозагрузчика. Это немного хак, поскольку я использую собственную библиотеку Codeigniter для предварительной автозагрузки, но для меня это лучший способ, который я знаю, загружать все классы, которые мне нужны, без ущерба для моей архитектуры архитектуры приложения, чтобы поместить его в Codeignign способ делать что-то. Некоторые могут утверждать, что Codeigniter не подходит для меня, и это может быть правдой, но я пытаюсь разобраться и разыгрывать различные рамки, а во время работы над CI я придумал это решение.
1. Автоматическая загрузка новой пользовательской библиотеки путем редактирования applicationica/config/autoload.php для включения:
$autoload['libraries'] = array('my_loader');
и любые другие библиотеки, которые могут вам понадобиться.
2. Затем добавьте класс библиотеки My_loader. Этот класс будет загружаться по каждому запросу и когда его конструктор будет запущен, он будет рекурсивно искать все подпапки и require_once все .php файлы внутри папок приложений/сервисов и приложений/моделей/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;
}
}
Ответ 6
Через 18 часов мне удалось включить библиотеку в мой элемент управления без инициализации (конструктор был проблемой, из-за этого и я не мог использовать стандартный codeiginiter $this->load->library()
).
Следуйте fooobar.com/info/324268/.... Имейте в виду, что для дальнейшей инициализации исходного класса используйте $date = new \DateTime()
с обратной косой чертой, иначе функция будет генерировать ошибку!