kamilwylegala / cakephp2-php8

CakePHP 2 fork that supports PHP 8
127 stars 62 forks source link

Call to undefined function PHP81_BC\strftime() #79

Open filippodona opened 1 month ago

filippodona commented 1 month ago

Hi, Kamil I stumbled upon your repository because I'm looking for a way to make my project made in CakePHP2 work on PHP 8. I followed all the documentation, the project is perfectly working on PHP 7.4, however updating the cakephp dependency using yours I continue to get this error _Call to undefined function PHP81BC\strftime(). In the documentation you write the following _"In order to get rid of strftime() deprecation notices, it's required to switch to IntlDateFormatter class. This class is available in intl extension. Fork doesn't require it explicitly but to be able to use its functions Symfony ICU Polyfill is installed. To provide strftime behavior compatibility, PHP81_BC\strftime is used. PHP81BC doesn't fully cover strftime, your code should work but there is a chance you'll get slightly different results." however I can't understand what exactly I have to do. Should I change my code and replace $this->Time->format with another syntax? Should I change some configuration? Would you be so kind as to help me? Also, could you tell me up to which PHP version your project is compatible (8.1, 8.2, 8.3)? Thank you

kamilwylegala commented 1 month ago

Hi Filippo,

Thanks for reporting this. It's a breaking change introduced in fork. Fork now relies on Intl extension. But you made me realize that Int is not optional, it's mandatory due to PHP81_BS/strftime package :see_no_evil:

So PHP version on your server must have php-intl installed. If your project is managed by composer, when switching to this fork, composer will install all necessary dependencies. Composer is a must have. Does your project use composer to manage deps?

strftime was removed in PHP8.1, if your application code relies on it, it will use underneath the pollyfill lib (the one mentioned in issue title).

Mine project runs on PHP 8.3 and is using this fork. No problems. Although, since I'm trying to get rid of cakephp2 dependency, I'm not using many features.

Let me know if it answers your questions.

filippodona commented 1 month ago

Hi Kamil, thanks for taking the time to answer my questions. I confirm that my project uses Composer to manage dependencies so I should have everything I need; if I understand correctly the only thing I'm missing is the installation and activation of the Intl extension, right? Do I have to install it at server level?

pbarabe commented 1 month ago

Hi @filippodona,

I believe you do need to install it at the host/server level.

On Debian-based systems (eg. Ubuntu), you'd need to run:

sudo apt install php-intl

On Redhat-based systems:

sudo yum install php-intl

Hope that helps!

filippodona commented 1 month ago

Hi Patrick, thank you very much for your contribution. I am currently testing everything in a DDEV environment; I have installed the Intl extension (I see it correctly in the PHP extension list) however I continue to get the error. Below I leave you some information

This is my composer.json { "require": { "cakephp/cakephp": "dev-master as 2.10.24", "cakephp/debug_kit": "^2.2.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.13" }, "config": { "vendor-dir": "Vendor", "allow-plugins": { "composer/installers": true } }, "repositories": [ { "type": "vcs", "url": "https://github.com/kamilwylegala/cakephp2-php8" } ] }

This is my configuration image

filippodona commented 1 month ago

The message appears when this statement is used in a controller: <?php echo $this->Time->format($client[$modelClass]['created'], '%d/%m/%Y %H:%M:%S'); ?>

kamilwylegala commented 1 month ago

@filippodona Make sure also that all dependencies required by fork are installed. Please provide error call stack + list of composer dependencies that are actually installed in your project.

filippodona commented 1 month ago

Hi Kamil, this is the error stack image

This is my composer.lock with all dependences installed (I rename it due to upload extensions restrictions) composer.lock.json

kamilwylegala commented 1 month ago

Composer has a command that outputs all installed dependencies with their version.

filippodona commented 1 month ago

This is the composer show command oputput: cakephp/cakephp dev-master cb3382f The CakePHP framework cakephp/debugkit 2.2.9 CakePHP Debug Kit clue/ndjson-react 1.3.0 Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP. composer/installers 1.12.0 A multi-framework Composer library installer composer/pcre 3.3.1 PCRE wrapping library that offers type-safe preg replacements. composer/semver 3.4.3 Semver library that offers utilities, version constraint parsing and validation. composer/xdebug-handler 3.0.5 Restarts a process without Xdebug. evenement/evenement 3.0.2 Événement is a very simple event dispatching library for PHP fidry/cpu-core-counter 1.2.0 Tiny utility to get the number of CPU cores. friendsofphp/php-cs-fixer 3.64.0 A tool to automatically fix PHP code style php81_bc/strftime 0.7.5 Locale-formatted strftime using IntlDateFormatter (PHP 8.1 compatible) psr/container 2.0.2 Common Container Interface (PHP FIG PSR-11) psr/event-dispatcher 1.0.0 Standard interfaces for event handling. psr/log 3.0.2 Common interface for logging libraries react/cache 1.2.0 Async, Promise-based cache interface for ReactPHP react/child-process 0.6.5 Event-driven library for executing child processes with ReactPHP. react/dns 1.13.0 Async DNS resolver for ReactPHP react/event-loop 1.5.0 ReactPHP's core reactor event loop that libraries can use for evented I/O. react/promise 3.2.0 A lightweight implementation of CommonJS Promises/A for PHP react/socket 1.16.0 Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP react/stream 1.4.0 Event-driven readable and writable streams for non-blocking I/O in ReactPHP sebastian/diff 5.1.1 Diff implementation symfony/console 6.4.12 Eases the creation of beautiful and testable command line interfaces symfony/deprecation-contracts 3.5.0 A generic function and convention to trigger deprecation notices symfony/event-dispatcher 6.4.8 Provides tools that allow your application components to communicate with each other by dispatching events and listenin... symfony/event-dispatcher-contracts 3.5.0 Generic abstractions related to dispatching event symfony/filesystem 6.4.12 Provides basic utilities for the filesystem symfony/finder 6.4.11 Finds files and directories via an intuitive fluent interface symfony/options-resolver 6.4.8 Provides an improved replacement for the arrayreplace PHP function symfony/polyfill-ctype 1.31.0 Symfony polyfill for ctype functions symfony/polyfill-intl-grapheme 1.31.0 Symfony polyfill for intl's grapheme functions symfony/polyfill-intl-icu 1.31.0 Symfony polyfill for intl's ICU-related data and classes symfony/polyfill-intl-normalizer 1.31.0 Symfony polyfill for intl's Normalizer class and related functions symfony/polyfill-mbstring 1.31.0 Symfony polyfill for the Mbstring extension symfony/polyfill-php80 1.31.0 Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions symfony/polyfill-php81 1.31.0 Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions symfony/process 6.4.12 Executes commands in sub-processes symfony/service-contracts 3.5.0 Generic abstractions related to writing services symfony/stopwatch 6.4.8 Provides a way to profile code symfony/string 6.4.12 Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way

kamilwylegala commented 1 month ago

Looks good, so the package is there.

Try to isolate the problem, and e.g. write a tiny script that loads autoload.php from composer and runs strftime to see if the function is available or not.

filippodona commented 1 month ago

I did some tests following your instructions.

This simple code inserted inside the view pages/home.ctp... <?php echo strftime ("%A"); ?> ...works perfectly as you can see from the screenshot below so this is good news image

The problem persists when I use the following helper in a view: <?php echo $this->Time->format('2024-10-04 11:53:00', '%B %e, %Y %H:%M %p'); ?>

image There is probably something wrong with the CakeTime class

I made a very stupid test by modifying the _strftime function of the CakeTime class like this: `protected static function _strftime($format, $timestamp) { $format = PHP81_BC\strftime($format, $timestamp);

    $encoding = Configure::read('App.encoding');
    if (!empty($encoding) && $encoding === 'UTF-8') {
        if (function_exists('mb_check_encoding')) {
            $valid = mb_check_encoding($format, $encoding);
        } else {
            $valid = Multibyte::checkMultibyte($format);
        }
        if (!$valid) {
            $format = mb_convert_encoding($format, 'UTF-8', 'ISO-8859-1');
        }
    }
    return $format;
}`

...to this: ` protected static function _strftime($format, $timestamp) { $format = strftime($format, $timestamp);

    $encoding = Configure::read('App.encoding');
    if (!empty($encoding) && $encoding === 'UTF-8') {
        if (function_exists('mb_check_encoding')) {
            $valid = mb_check_encoding($format, $encoding);
        } else {
            $valid = Multibyte::checkMultibyte($format);
        }
        if (!$valid) {
            $format = mb_convert_encoding($format, 'UTF-8', 'ISO-8859-1');
        }
    }
    return $format;
}`

..and not it works image

However, I am not convinced that this is the most correct solution.

filippodona commented 1 month ago

Could this be a PHP81_BC namespace issue?

kamilwylegala commented 1 month ago

If you run in your project PHP_81\strftime() directly, does it work? Please run it anywhere in controller class.

I wonder if it's composer class mapping issue.

filippodona commented 1 month ago

I alway got Call to undefined function PHP_81\strftime()

In the autoload_static.php file there is no references to the PHP_81\strftime function. Could be a problem with the second level deps ?

kitgrose commented 3 weeks ago

I had the same issue (apparently caused by my composer.json having its vendor-dir set to app/Vendor), and fixed it by manually adding the Composer autoload file to my ${APP}/Config/bootstrap.php file:

require APP . 'Vendor' . DS . 'autoload.php';
filippodona commented 3 weeks ago

amazing @kitgrose your suggestion works fine!

I have your same configuration (vendor-dir set to app/Vendor).