Руководство по обновлению Magento 2.3.x
Введение
Когда вы управляете магазином электронной коммерции, важно оставаться в безопасности и быть в курсе событий. Вы всегда должны следить за последней версией Magento 2 и своевременно обновлять ее. Целью данной статьи является обзор возможных вариантов обновлений и ошибок, с которыми вы можете столкнуться.
Пример, описанный в данной статье подойдет для обновления версий Magento 2.3.x
Сейчас наиболее современными версиями Magento являются релизы Magento 2.3.x (Источник 1). Каждый такой выпуск сопровождается полным описанием дополнений, доработок и выгодных для вас улучшений. Пример, приложенный в данной статье, описывает обновление до последней доступной на момент написания статьи версии Magento 2.3.5-p1 (Источник 2).
Важно: всегда делайте резервную копию ваших файлов и базы данных, прежде чем пытаться выполнить обновление. Также рекомендуется делать обновление на отдельной копии магазина, а затем уже заливать обновленную и протестированную версию на рабочий сервер. С такой сложной платформой, как Magento 2, вы не можете предвидеть, что обновление пройдет успешно. Многое может пойти не так. У вас всегда должна быть возможность восстановить систему.
Обновление Magento 2
Существует 3 варианта обновления системы Magento 2:
- С использованием Composer и терминала
- С помощью мастера веб-установки
- С помощью загрузки версии вручную (не рекомендуется)
Поскольку наиболее предпочтителен вариант обновления через Composer, второй и третий варианты рассмотрим обзорно.
Обновление через Composer
Composer - менеджер зависимостей для PHP. Он может помочь обновить магазин с минимальными хлопотами. Инструкция по его установке представлена в источнике 3.
Рассмотрим применение Composer на примере. Текущая версия магазина: 2.3.2. Желаемая версия магазина: 2.3.5-p1.
Если вы используете git, убедитесь, что в текущей ветке нет незакоммиченных изменений. в противном случае, если вам придется откатить обновление, вы можете все потерять.
Весь процесс обновления можно рассмотреть в нескольких шагах:
1. Переключитесь в режим технического обслуживания, это можно сделать командой:
php bin/magento maintenance:enable
2. Запросите информацию о последних доступных версиях Magento:
composer show magento/product-community-edition 2.3.* --all | grep -m 1 versions
3. Заставьте Composer использовать последнюю версию (замените 2.3.5-p1 на самую новую):
composer require magento/product-community-edition=2.3.5-p1 --no-update
Если вы используете Magento 2 commerce, команда будет немного другой:
composer require magento/product-enterprise-edition=2.3.5-p1 --no-update
4. Обновите Composer, заставив его загрузить новую версию и обновить все файлы:
composer update
Применение первых четырех шагов выглядит следующим образом:
После завершения 4го шага можем убедиться, что обновилось много файлов системы:
В файле composer.json теперь отмечена новая версия:
5. На этом этапе нужно добавить все новые файлы в гит, закоммитить изменения и залить, чтобы дальнейшую донастройку можно было легко откатить.
6. После успешного обновления и коммита нужно запустить две команды, обновление базы данных и компиляция:
php bin/magento setup:upgrade
php bin/magento setup:di:compile
При выполнении этих команд могут возникать ошибки. Они рассмотрены ниже в пункте "Возможные проблемы". Не исключено, что вам придется изменять код своих модулей или обновлять сторонние модули до последних версий.
7. В случае успешного завершения команд, отключите режим обслуживания и запустите реиндекс:
php bin/magento maintenance:disable
php bin/magento indexer:reindex
После успешного завершения 7-го пункта, можно загружать магазин и тестировать его на возможные проблемы. Их обзор так же можно посмотреть в вышеупомянутом пункте статьи.
Номер текущей версии можно посмотреть на главной странице админки сайта:
Обновление с помощью мастера веб-настройки
В Magento 2 есть пункт меню в разделе System => Tools, называемый «Web Setup Wizard». Вы можете использовать его для установки расширений, купленных через Magento Marketplace, или для обновления Magento до новых версий.
Здесь нужно выбрать соответствующий пункт обновления и далее действовать по инструкции.
В начале обновления Magento попросит предоставить учетные данные. Их можно получить по ссылке https://marketplace.magento.com/customer/accessKeys/ (Источник 1). Следует помнить: имя пользователя - открытый ключ, а пароль - закрытый.
Далее система потребует выбрать версию обновления, возможно попросить установить дополнительные плагины. Нужно соглашаться с требованиями. Однако шаг создания резервной копии лучше пропустить и сделать вручную резервную копию ваших файлов и базы данных. Этот шаг может перегрузить систему, зависнуть, и вам нужно будет начать все сначала.
Обновление с помощью загрузки версии вручную
Данный способ наименее предпочтителен, поскольку имеет больше вероятности нанести вред текущей системе. Использовать его нужно, если предыдущие два не удались по какой-либо причине.
Для этого необходимо загрузить последнюю версию Magento 2 с официального сайта Magento, и разархивировать ее в основной папке magento. Это перезапишет основные файлы системы.
Затем запустите:
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento maintenance:disable
php bin/magento indexer:reindex
Обновление сделано.
Возможные проблемы
1. Обновление входных параметров в методах дочерних классов
Зачастую с обновлением версии Magento 2 необходимо обновлять сторонние модули.
Например, на шаге исполнения команды php bin/magento setup:upgrade может возникнуть такая проблема:
Текст ошибки: Warning: Declaration of Amasty\BannersLite\Model\BannerImageUpload::moveFileFromTmp($imageName) should be compatible with Magento\Catalog\Model\ImageUploader::moveFileFromTmp($imageName, $returnRelativePath = false) in /var/www/app/code/Amasty/BannersLite/Model/BannerImageUpload.php on line 76
Данная проблема возникает в стороннем модуле Amasty_BannersLite. Метод moveFileFromTmp класса Amasty\BannersLite\Model\BannerImageUpload принимает один аргумент, тогда когда его родительский метод теперь принимает два аргумента. Наличие одинаковых точных значений аргумента по умолчанию также важно.
Метод moveFileFromTmp класса Amasty\BannersLite\Model\BannerImageUpload:
<?php namespace Amasty\BannersLite\Model; class BannerImageUpload extends \Magento\Catalog\Model\ImageUploader { public function moveFileFromTmp($imageName) { ... } }
Метод moveFileFromTmp класса Magento\Catalog\Model\ImageUploader:
<?php namespace Magento\Catalog\Model; use Magento\Framework\File\Uploader; class ImageUploader { public function moveFileFromTmp($imageName, $returnRelativePath = false) { ... } }
Поскольку это сторонний модуль, есть 3 варианта решения ситуации:
- Обновить модуль, если вышло обновление для 2.3.5
- Отключить модуль, если он не используется и исправить ошибку вручную, чтобы при компиляции не появлялась ошибка вновь
- Написать разработчикам модуля с вопросом о совмещении версии с 2.3.5
Во время нашего обновления был выбран вариант 2. Модуль отключили, а его код поправили:
<?php namespace Amasty\BannersLite\Model; class BannerImageUpload extends \Magento\Catalog\Model\ImageUploader { public function moveFileFromTmp($imageName, $returnRelativePath = false) { ... } }
2. Can’t create directory
Данная ошибка может также возникнуть на шаге исполнения php bin/magento setup:upgrade.
Текст ошибки: Fatal error: Uncaught exception 'MagentoFrameworkExceptionLocalizedException' with message 'Can't create directory /var/www/html/site/var/generation/Magento/Framework/App/ResourceConnection/.' in /var/www/html/site/vendor/magento/framework/Code/Generator.php:103 Stack trace: #0 /var/www/html/site/vendor/magento/framework/Code/Generator/Autoloader.php(35): MagentoFrameworkCodeGenerator->generateClass('MagentoFramewo...') #1 [internal function]: MagentoFrameworkCodeGeneratorAutoloader->load('MagentoFramewo...') #2 [internal function]: spl_autoload_call('MagentoFramewo...') #3 /var/www/html/site/vendor/magento/framework/Code/Reader/ClassReader.php(19): ReflectionClass->__construct('MagentoFramewo...') #4 /var/www/html/site/vendor/magento/framework/ObjectManager/Definition/Runtime.php(44): MagentoFrameworkCodeReaderClassReader->getConstructor('MagentoFramewo...') #5 /var/www/html/site/vendor/magento/framework/ObjectMana in /var/www/html/site/vendor/magento/framework/Code/Generator.php on line 103`
В этом случае нужно убедиться, что у текущего пользователя есть права на запись в папках pub/static и var. Права на запись можно задать командой:
chmod 755 var pub/static
3. Обновление конструктора у дочерних классов
Не реже чем сторонние требуют обновления и свои модули.
Например, шаге компиляции (комада bin/magento setup:di:compile), мы столкнулись с такой ошибкой:
Текст ошибки: Astrio\CustomerPhone\Rewrite\Magento\Customer\Controller\Account\CreatePost Incompatible argument type: Required type: \Magento\Customer\Api\CustomerRepositoryInterface. Actual type: \Magento\Framework\Data\Form\FormKey\Validator; File: /var/www/app/code/Astrio/CustomerPhone/Rewrite/Magento/Customer/Controller/Account/CreatePost.php
Причина проблемы в том, что в одном из написанных к тому времени модулей есть класс CreatePost, наследуемый \Magento\Customer\Controller\Account\CreatePost. Он имеет конструктор. С обновлением magento обновился класс \Magento\Customer\Controller\Account\CreatePost и его конструктор. Соответственно система требует обновить конструктор и нашего класса.
Таким образом, решением данной проблемы стало добавление в конструктор класса еще одного параметра:
4. Устаревшие сторонние модули
После успешного обновления базы и компиляции, нужно быть готовым, что в любом месте сайта могут произойти сбои. Например, одной из проблем может стать устаревший сторонний модуль. Например, после обновления Magento на одной из страниц админки произошла такая ошибка:
Текст ошибки: main.ERROR: The URL «http://togas.local/default/dfe-yandex-kassa» is invalid, because the system expects an URL which starts with «https://». [] []
Решением данной проблемы стало выключение модуля dfe-yandex-kassa и обращение к его разработчикам для его обновления до последней версии.
5. Доработка темы
Не редкими являются проблемы с темой. Если вы используете стандартную тему Magento, то необходимо заранее удостовериться, что ее версия будет работать в обновленной Magento. Или что разработчики выпустили такой модуль и его можно обновить. В случае, если тему разрабатывали и правили вы сами, то будьте готовы к доработкам. Например в нашем случае при загрузке главной страницы сайта возникла такая ошибка:
Текст ошибки: Uncaught Error: Call to undefined method Astrio\Theme\Rewrite\Magento\Catalog\Plugin\Block\Topmenu::afterGetCacheKeyInfo() in /var/www/vendor/magento/framework/Interception/Interceptor.php:146
Дело в том, что в одном из наших модулей мы ранее переопределили класс Magento\Catalog\Plugin\Block\Topmenu.
C обновлением Magento добавился метод Magento\Catalog\Plugin\Block\Topmenu::afterGetCacheKeyInfo(), а класс Astrio\Theme\Rewrite\Magento\Catalog\Plugin\Block\Topmenu остался прежним.
Простым решением данной проблемы стало добавление нового метода в класс нашего модуля:
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_OrderDeliveryDate', __DIR__ );
<?php namespace Astrio\Theme\Rewrite\Magento\Catalog\Plugin\Block; use Magento\Catalog\Model\Category; use Magento\Framework\Data\Collection; use Magento\Framework\Data\Tree\Node; class Topmenu { public function afterGetCacheKeyInfo(\Magento\Theme\Block\Html\Topmenu $subject, array $result) { ... } }
6. Системные проблемы Nginx
Наконец, после обновления Magento можно не избежать даже системных ошибок. В нашем примере мы столкнулись с такой проблемой: после перезагрузки страницы некоторые из них начали падать в 502 страницу.
Веб-сервер, используемый для сайта - Nginx. Его системные логи показали такую ошибку:
Текст ошибки: upstream sent too big header while reading response header from upstream
В нашем случае решением проблемы стала правка конфигурационного файла nginx.conf. В раздел http мы вставили такие строки:
fastcgi_buffer_size 64k;
fastcgi_buffers 16 64k;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
Во время настроки необходимо перезагружать контейнер Nginx и каждый раз сверяться с его логами, зачастую они подсказывают какие параметры нужно поправить: увеличить или уменьшить.
7. Cannot allocate memory error
Если вы столкнулись с этой ошибкой во время обновления, это означает, что недостаточно памяти, выделенной для процессов PHP. Вы не можете безопасно запускать Magento 2 на сервере с менее чем 2 ГБ доступной оперативной памяти. Ваша система должна соответствовать минимальным требованиям к оборудованию. Увеличьте пределы памяти как минимум до 2Гб.
8. There are no commands defined in the "setup" namespace
Есть несколько способов исправить ошибку:
- Дайте права на запись папкам var и pub: chmod 755 var pub
- Проверьте ваши пользовательские модули, убедитесь, что в каждом модуле файл module.xml существует и содержит валидный xml.
- Проверьте ваш файл composer.json. Иногда ошибка может привести к тому, что команда обновления Magento2 выдает исключение «no commands defined».
Заключение
Обновление Magento до новой версии - процесс необходимый и вместе с тем достаточно трудоемкий не смотря на то, что зачастую требует небольшого количества команд. Основными трудностями могут стать возникающие в процессе обновления и проверки ошибки, связанные со своими и сторонними модулями и даже настройками веб-сервера.
Стоит еще раз отметить основные проблемы, с которыми можно столкнуться:
- Отсутствие необходимых разрешений на редактирование папок.
- Недостаток оперативной памяти, выделенной для процессов php.
- Устаревшие сторонние модули.
- Обновление переопределенных в собственном модуле функций.
- Обновление переопределенных в собственном модуле классов.
Тем неменее, сейчас достаточно справочного материала для своевременного решения данных проблем и успешного завершения обновления.
Источники