Исторически сложилось, что jeka.by был написан на фреймворке kohana 3.2 и использовал как и все на то время php 5 (то ли php 5.2 то ли 5.3).
На дворе 2017 год, а, значит, давно пора переходить на php 7.
Тут я напишу, какие изменения пришлось внести в код проекта.
1. Я обновил Kohana до последней стабильной 3.3.0 версии.
a) Заменил все модули на новые. А также заменил папку system. Переименовал часть своих папок и обращение в index.php, bootstap.php, чтобы каталоги и имена классов начинались с прописной буквы вместо строчной, пример:
require SYSPATH.'classes/kohana/core'.EXT;
на
require SYSPATH.'classes/Kohana/Core'.EXT;
b) В kohana 3.3 удалён метод:
Request::current()->redirect()
вместо него нужно везде прописать редирект в виде:
HTTP::redirect(url);
2. В php 7 наконец таки удалена поддержка mysql extension (нужно использовать mysqli или pdo). В то же время в kohana mysqli driver ещё официально не появился!
Поэтому нам нужно найти и подключить модуль mysqli для kohana. Я взял модуль на github https://github.com/tomlankhorst/kohana-3.3-mysqli.
Подключил модуль как обычно в application/bootstrap.php в массиве Kohana::modules:
'mysqli' => MODPATH.'mysqli
А так же нужно изменить тип адаптера в application/config/database.php с MySQL на MySQLi.
3. Одну строку номер 121 в файле modules/pagination/classes/Kohana/Pagination.php нужно обновить в соответствии с синтаксисом php 7, добавить фигурные скобки: $config_file->{$config['group']}
:
- while (isset($config['group']) AND isset($config_file->$config['group'])) + while (isset($config['group']) AND isset($config_file->{$config['group']}))
Иначе будет ошибка ErrorException [ Notice ]: Array to string conversion в классе Pagination:
4. Следующая ошибка вывалится в kohana только в том случае, если вы используете Memcache расширение.
Memcache PHP extention not loaded
Ошибка возникает, т.к. данное расширение не выпущено разработчиками под 7-ую версию php (можно попробовать собрать ручками, но готовый пакет не предоставляется).
Как альтернатива, теперь будем использовать memcached. Соответственно, нужно найти и загрузить модуль memcached для kohana. Я взял вот этот модуль с github - https://github.com/gimpe/kohana-memcached
Кроме подключения модуля в bootstrap.php, не забываем исправить driver в конфиге application/config/cache.php c memcache на memcached.
5. У меня в kohana использовался ckeditor вместе с ckfinder для загрузки и просмотра картинок на сервере. При попытке ckfinder "Просмотреть на сервере" возникает ошибка в kohana "A non well formed numeric value encountered" в файле assets/vendors/ckfinder/core/connector/php/php5/Utils/Misc.php. См. скриншот:
Ошибка не в ядре kohana, а в 3rdparty. Ошибка (варнинг) возникает в функции returnBytes:
/** * convert shorthand php.ini notation into bytes, much like how the PHP source does it * @link http://pl.php.net/manual/en/function.ini-get.php * * @static * @access public * @param string $val * @return int */ public static function returnBytes($val) { $val = trim($val); if (!$val) { return 0; } $last = strtolower($val[strlen($val)-1]); switch($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; }
Это происходит в момент когда мы пытаемся в php 7.1 (в php 7.0 всё ок!) умножить строку на число:
'128M' * 1024
Решением является вставить перед констукцией switch приведение к типу integer:
$val = (int) $val;
Это не бага, а фича php 7.1 - https://wiki.php.net/rfc/invalid_strings_in_arithmetic:
Warn about invalid strings in arithmetic
при выполнении арифметических операций с невалидными строками будет варнинг с текстом "Warn about invalid strings in arithmetic". В зависимости от уровня настроек может быть выброшен exception.
6. Следующая ошибка может возникнуть в неожиданный момент, когда что то пошло не так.
ErrorException [ Fatal Error ]:
Ошибка в php 7 kohana связана с тем, что в php 7 внесены изменения в механизм обработки ошибок.
Как пофиксить? Красивой альтернативы, обеспечивающей обратную совместимость, сообщество kohana еще не предлагало. Есть простой вариант с удалением typehint. Нужно в классе system/classes/Kohana/Kohana/Exception.php удалить во всех объявлениях функций ожидаемый тип аргумента Exception
, т.е. вместо:
function handler(Exception $e) function _handler(Exception $e) function log(Exception $e, function text(Exception $e) function response(Exception $e)
Делаем:
function handler($e) function _handler($e) function log($e, function text($e) function response($e)
Подробнее см. commit в kohana core.
Это весь список ошибок и их фиксов, которые возникли у меня при миграции kohana с php 5 на php 7 (php 7.0) на примере jeka.by.
UPD 1 июня 2022:
Пользуйтесь тулзами анализа кода, такими как phpcs со стандартом PHPCompatibility (нужно установить отдельно), чтобы найти проблемы совместимости с новыми версиями php. Полезно для всех проектов, не только kohana.
Несколько примеров (в моем случае phpcs установлен через composer как dev зависимость в самом проекте):
php vendor/bin/phpcs --standard=PHPCompatibility application/classes --runtime-set testVersion 7.3 -n
php vendor/bin/phpcs --standard=PHPCompatibility modules --runtime-set testVersion 7.4 -n
Запуск первой phpcs команды проверит все файлы внутри директории application/classes на совместимость с php 7.3 и выведет ошибки если они есть: в каком файле и какой строке есть проблема. Вторая команда - проверит все php-файлы в директории modules на совместимость с версией php 7.4.
Kohana php 7.4 migration:
modules/orm/classes/Kohana/ORM.php :: ErrorException в методе has
ErrorException [ Warning ]: count(): Parameter must be an array or an object that implements Countable.
Ведь второй параметр $far_keys
может быть просто id'шником, на который нельзя сделать count, исправить можно так:
Ошибки касательно kohana-ckfinder
ErrorException [ Deprecated ]: The each() function is deprecated. This message will be suppressed on further calls
Нужно избавиться от устаревшей функции each
в файле assets/vendors/ckfinder/core/connector/php/php5/Core/Config.php:
Строку:
while (list($_key,$_resourceTypeNode) = each($GLOBALS['config']['ResourceType'])) {
Меняем на:
foreach ($GLOBALS['config']['ResourceType'] as $_resourceTypeNode) {
Комментарии 1
-$model = 'Model_'.$model;
+$model = 'Model_'.ucfirst($model);