Advertisement
  1. Code
  2. OpenCart

Разбираем класс прокси в OpenCart

Scroll to top
Read Time: 8 min

Russian (Pусский) translation by Masha Kolesnikova (you can also view the original English article)

Чаще всего мы принимаем что-то как должное. Если что-то работает так, как ожидалось, мы не будем беспокоиться о его внутренней работе, чтобы понять лежащий в основе механизм. Или, говоря иначе, мы не копаемся в чем-то, пока не будем в беде!

Точно так же мне всегда было интересно узнать о нескольких концепциях OpenCart, которые использовались внутри фреймворка, и одним из них был класс Proxy. Мне потребовалось некоторое время, чтобы понять его, и я подумал, что с тобой приятно будет делиться, так как всегда интересно узнать что-то новое.

Что такое класс прокси?

Хотя вы найдете различные материалы в Интернете, которые определяют термин прокси, определение из Википедии  довольно легко понять.

Прокси-сервер в его самой общей форме - это класс, функционирующий как интерфейс к чему-то другому.

Таким образом, прокси делегирует элемент управления объекту, который он намеревается использовать, и таким образом действует от имени фактического класса, который был создан. Фактически, шаблон прокси-дизайна является очень популярным шаблоном, который используется популярными фреймворками по мере необходимости. Учитывая тот факт, что обсуждение прокси-метода само по себе является такой широкой темой и выходит за рамки этой статьи, я быстро подытожу, как он используется большую часть времени:

  • Действует как обертка, чтобы обеспечить дополнительную функциональность.
  • Задержка создания дорогостоящих объектов, также называемая ленивой загрузкой.

В контексте OpenCart можно сказать, что шаблон прокси используется для добавления функциональности в базовый прокси-класс. Сказав это, базовый прокси-класс сам по себе не предоставляет ничего, кроме нескольких волшебных методов! Как мы увидим в следующем разделе, прокси-класс обогащается во время выполнения, добавляя к нему свойства.

Прежде чем перейти к следующему разделу, давайте быстро взглянем на класс прокси. Он находится в system/engine/proxy.php.

Как вы можете видеть, он реализует три магических метода: __get(), __set() и __call(). Среди них реализация метода __call() является важной, и мы вернемся к ней довольно скоро.

Как работает прокси-класс с моделью

В этом разделе я объясню, как именно вызов типа $this->model_catalog_category->getCategory($category_id) работает из коробки.

Фактически, история начинается со следующего утверждения.

Во время начальной загрузки оболочка OpenCart хранит все общие объекты в объекте Registry, чтобы их можно было получить по желанию. В результате этого вызов $this->load возвращает объект Loader из реестра.

Класс Loader предоставляет различные методы для загрузки разных компонентов, но нас интересует метод model. Давайте быстро взглянем на фрагмент метода model из system/engine/ oader.php.

Учитывая вышеупомянутый пример, значением аргумента $route является catalog/category. Во-первых, значение переменной $route очищается и после этого запускает событие before, чтобы другие слушатели модуля могли изменить значение переменной $route.

Затем он проверяет наличие запрошенного объекта модели в реестре. Если реестр содержит запрошенный объект, дальнейшая обработка не требуется.

Если объект не найден, следует загрузить интересную процедуру, и это фрагмент, который мы ищем в контексте этой статьи.

Для начала он подготавливает путь к файлу запрашиваемой модели и загружает ее, если она существует.

После этого он создает объект Proxy.

Теперь обратите внимание на следующий цикл for: он намного больше, чем кажется.

В нашем случае значение $class должно быть ModelCatalogCategory. Фрагмент get_class_methods($class) загружает все методы класса ModelCatalogCategory и проходит через него. Что он делает в цикле? Давайте посмотрим внимательно.

В цикле он вызывает метод callback того же класса. Интересно отметить, что метод обратного вызова возвращает функцию, вызываемую для объекта $proxy с ключом в качестве имени метода. Конечно, прокси-объект не обладает такими свойствами; он будет создан на лету, используя магический метод __set()!

Затем объект $ proxy добавляется в реестр, чтобы его можно было получить позже, когда это необходимо. Посмотрите на ключевой компонент метода set. В нашем случае это должна быть model_catalog_category.

В конце он вызовет событие after, чтобы другие слушатели модуля могли изменить значение переменной $route.

Это одна часть истории.

Давайте рассмотрим, что происходит, когда вы используете следующее в своем контроллере.

Фрагмент $this->model_catalog_category пытается найти соответствие для ключа model_catalog_category в реестре. Если вам интересно, просто изучите определение класса Controller в файле system/engine/controller.php - он предоставляет магический метод __get(), который это делает.

Как мы только что обсуждали, это должно вернуть объект $proxy, назначенный этому конкретному ключу. Затем он пытается вызвать метод getCategory для этого объекта. Но класс Proxy не реализует такой метод, так как это будет работать?

Магический метод __call() приходит на помощь! Всякий раз, когда вы вызываете метод, который не существует в классе, элемент управления передается магическому методу __call().

Давайте рассмотрим его подробно, чтобы понять, что происходит. Откройте файл класса Proxy и обратите внимание на этот метод.

В $key содержится имя функции, которая называется-getCategory. С другой стороны, $args содержит аргументы, переданные методу, и он должен быть массивом из одного элемента, содержащего идентификатор категории, который передается.

Далее, существует массив $arg_data, который хранит ссылки на аргументы. Честно говоря, я не уверен, что код $arg instanceof Ref имеет смысл. Если кто-нибудь знает, почему он там, я был бы рад узнать.

Кроме того, он пытается проверить существование свойства $key в объекте $proxy, и это приводит к чему-то вроде этого.

Напомним, что ранее мы назначили все методы класса ModelCatalogCategory как свойства объекта $proxy с использованием цикла for. Для вашего удобства я снова вставлю этот код.

Таким образом, он должен быть там, и он также должен вернуть нам функцию, которая вызывается! И, наконец, он вызывает эту функцию, вызываемую с помощью функции call_user_func_array, передавая аргументы метода.

Теперь давайте обратим наше внимание на само вызываемое функцией определение. Я возьму фрагмент из метода callback, определенного в system/engine/ oader.php.

Поскольку это анонимная функция, она сохранила значения в виде переменных $register и $route, которые были переданы ранее методу callback. В этом случае значение переменной $route должно быть catalog/category/getCategory.

Кроме того, если мы посмотрим на важный фрагмент этой функции, он создает экземпляр объекта ModelCatalogCategory и сохраняет его в статическом массиве $model.

И вот фрагмент, который захватывает имя метода, которое нужно вызвать, используя переменную $route.

Таким образом, мы имеем ссылку на объект и имя метода, которое позволяет нам вызывать его с помощью функции call_user_func_array. Следующий фрагмент делает именно это!

В конце метода полученный результат возвращается через переменную $output. И да, это еще одна часть истории!

Я намеренно игнорировал код pre и post events, который позволяет вам переопределять методы основных классов OpenCart. Используя это, вы можете переопределить любой метод основного класса и настроить его в соответствии с вашими потребностями. Но давайте сделаем в другой раз, так как это уже будет слишком много всего, чтобы вписаться в одну статью!

Так вот как это работает. Я надеюсь, что вы должны быть более уверенны в этих коротких вызовах OpenCart и об их внутренней работе.

Заключение

То, что мы только что обсуждали, является одной из интересных и неоднозначных концепций в OpenCart: использование метода Proxy для поддержки сокращенных соглашений для вызова методов модели. Надеюсь, статья была достаточно интересна и обогатила ваши знания OpenCart.

Я хотел бы узнать ваши отзывы об этом, и если вы чувствуете, что я должен освещать такие темы в своих будущих статьях, не стесняйтесь написать об этом пару строк!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.