Экземпляр данного класса создается первым, еще на этапе загрузки приложения, перед созданием остальных служебных объектов, в файле system\framework.php
$registry = new Registry();
Далее, все создаваемые объекты библиотек регистрируют свой экземпляр класса в регистраторе. Например объект класса Event (для работы с событиями):
$event = new Event($registry); $registry->set('event', $event);
Таким образом, позже, обратившись к регистратору из другого класса, можно получить любой объект, который был зарегистрирован. Для этого, только, нужно не терять связь с самим регистратором. Для этого, при создании служебных объектов, в метод конструктора передается объект класса регистратора:
class Event { protected $registry; public function __construct($registry) { $this->registry = $registry; } …
Только на словах понять новичку будет трудно, поэтому я написал УПРОЩЕННЫЙ пример. Доступ к другим служебным объектам в OpenCart часто используется в работе контроллеров. Поэтому в примере я использовал принцип работы модели MVC, примерно как это делается в данном фреймворке.
Можно скачать небольшой архив с файлами для тестирования, чтобы не набирать указанный ниже код вручную.
Файл index.php
/* * Класс-регистратор, который сохраняет в свойстве $data * экземпляры других служебных классов для доступа к любому из них * из любой точки приложения. * * Для доступа к регистру, такие классы, при создании объекта, * получают аргументом для метода-конструктора экземпляр данного класса: * protected $registry; function __construct($registry) { $this->registry = $registry; } */ class Registry{ private $data = array(); function set($key,$obj){ if (!$this->has($key)){ $this->data[$key] = $obj; } } function get($key){ return $this->data[$key]; } public function has($key) { return isset($this->data[$key]); } } $registry = new Registry(); /* * Тестовый класс для демонстрации доступа к его свойствам/методам */ class Request{ public $language = 'ru'; function get(){ return $this->language; } } $request = new Request(); /* * Все объекты, к которым нужен доступ из других классов, передаем в регистратор * в формате ключ/экземпляр класса */ $registry->set('request', $request); /* * Класс для удобного доступа к элементам MVC (модель/вид/контроллер) */ class Loader{ protected $registry; function __construct($registry) { $this->registry = $registry; } function controller($name, $action='index'){ $file = './controllers/' . $name . '.php'; if (is_file($file)){ require_once $file; $controller = new $name($this->registry); return $controller->$action(); } } function model($name){ $file = './models/' . $name . '.php'; if (is_file($file)){ require_once $file; return new $name($this->registry); } } function view($name, $date){ $file = './views/' . $name . '.php'; if (is_file($file)){ ob_start(); require_once $file; return ob_get_clean(); } } /* * Метод, подключающий языковой файл в зависимости от текущего языка * Для примера, текущий язык берем из объекта Request */ function language($name){ /* * Таким образом можем получить данные из любого объекта, который внесен * в регистратор. Просто передаем ключ нужного объекта. */ $request = $this->registry->get('request'); $default = $request->get(); $file = './language/' . $default . '/' . $name . '.php'; if (is_file($file)){ require_once $file; return isset($_) ? $_: null; } } } $loader = new Loader($registry); $registry->set('loader',$loader); //так же передаем в регистратор /* * В реальном приложении вызов определенного контроллера происходит после * разбора текущего URL. Для упрощения - вызовем сразу FunController. */ $output = $loader->controller('FunController'); echo $output;
В данном файле у нас упрощенная реализация того, что происходит в файле framework.php OpenCart.
Классы (для простоты примера) я не стал разбивать на отдельные файлы. То есть – первым создаем экземпляр класса регистратора, а далее передаем ему каждый из служебных классов, доступ к которому нам понадобится в дальнейшем. Соответственно, чтобы из других объектов была возможность обратиться к одному и тому же объекту класса регистратора, при создании этих объектов – передаем методу конструктору этих классов, объект- регистратор.
Так же, тут приведена работа загрузчика реализованная в OpenCart (класс Loader), который активно применяется в контроллерах для получения доступа к основным компонентам MVC – моделям, видам ну и языковым файлам.
Загрузчик позволяет динамически создавать экземпляры классов, которые нужно вызвать, одновременно передавая в их метод-конструктор объект-регистратор. С помощью загрузчика, так же, легче/нагляднее получить доступ к другому служебному объекту, с которыми он работает (методы загрузчика соответствуют классам, объекты которых создаются в этих методах).
Например получаем класс нужной модели:
$model = $this->loader->model('FunModel');
Без использования загрузчика, из контроллера или модели, обратиться к другому объекту можно так, как продемонстрировано в методе language() класса Loader:
- получаем объект нужного класса (например 'request')
$request = $this->registry->get('request');- далее вызываем нужный метод или свойство
$default = $request->get();
В конце, для тестирования, вызван контроллер 'FunController' который, в своих методах, использует работу с объектом-регистратором.
Результат работы выводим на экран, должно отобразиться:
Fun русский
Первое значение получено с использованием модели, второе – языкового файла.
Далее привожу код остальных файлов с комментариями. Разместить их следует в указанных папках. Будут вопросы – задавайте.
Файл controllers\FunController.php
<?php class Controller{ protected $registry; function __construct($registry) { $this->registry = $registry; } /* * Используем "магический" метод __get для перенаправления к методу get() * класса регистратора (Registry) */ function __get($name) { return $this->registry->get($name); } } class FunController extends Controller { function index(){ /* * Формируем общий массив для данных, которые будут передаваться в * файл-представление для использования */ $date = []; /* * Т.к. у класса FunController нет свойства loader, будет вызван * метод __get() родительского класса Controller, который строкой * $this->registry получает объект регистратор, сохраненный в свойстве * $registry при создании объекта FunController. А уже регистратор, используя * метод get() возвращает объект класса Loader, у которого вызывается * запрашиваемый метод model('FunModel'). */ $model = $this->loader->model('FunModel'); $date['text'] = $model->index(); $language = $this->loader->language('lang'); $date['lang'] = $language['title']; $view = $this->loader->view('FunView',$date); return $view; } }
Файл models\FunModel.php
<?php class Model{ protected $registry; function __construct($registry) { $this->registry = $registry; } function __get($name) { return $this->registry->get($name); } } class FunModel extends Model{ function index(){ //Допустим модель обработала данные и должна вернуть в качестве рез-та "Fun" return "Fun"; } }
Файл language\ru\lang.php
<?php $_['title'] = 'русский';
Файл language\en\lang.php
<?php $_['title'] = 'english';
Файл views\FunView.php
<h2><?=$date['text']?></h2> <h3><?=$date['lang']?></h3>