-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
PHP Version
8.2
CodeIgniter4 Version
4.3.6
CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter)
Which operating systems have you tested for this bug?
Windows
Which server did you use?
apache
Database
No response
What happened?
Hello,
I created a project that uses widgets. My widgets are in folder /app/Widgets. Theses widgets are used to display partial views.
For exemple, the widget /app/Widgets/Customer/Account.php have a method lastRegistrations to display 10 last registrations to the administrator.
In the same page, I call two widgets to display latest registrations of Customers and Administrators like that :
=> <?= view_cell("\App\Widgets\Customer\Account::lastRegistration"); ?>
=> <?= view_cell("\App\Widgets\Admin\Account::lastRegistration"); ?>
Everything worked fine when I was on version 4.1 with PHP7.4.
Today, I upgraded my CodeIgniter project to the latest version 4.3.6 with PHP 8.2.
The project launches fine overall after some changes, but I noticed a problem on some pages.
In the page where I call the two previous widgets, I noticed that the second widget (Admin) displayed the same content as the first widget (Customer).
I did some research, and I found the source of the problem in the file system/Config/Factories.php in the method __callStatic.
In this method, there is a line $basename = self::getBasename($name); who return the name of the class.
=> In my case : $name = "\App\Widgets\Customer\Account";
=> Result : $basename = "Account";
This method stores the namespace in array self::$basenames using $basename as key.
The self::$basenames variable is used to check if an instance of the class already exists and to return the namespace of the class.
In my case, my two widgets have the same basename, so the second call will use an instance of the first call, because the check is based on the same basename. This is why I have the same results.
To solve this, I found two solutions:
1. Use $name instead of $basename : self::$basenames[$options['component']][$name] = $class;
2. Or, generate a hash of the $name : $basename = md5($name);
Steps to Reproduce
- Install CodeIgniter (version 4.3.6)
- Create two controllers with the same name in two subfolders :
=>/app/Controllers/SubFolderOne/Test.php
=>/app/Controllers/SubFolderTwo/Test.php - Create a method on each controllers who return different string values
- Call this two methods in view file using "view_cell" function
=><?= view_cell("\App\Controllers\SubFolderOne\Test::render"); ?>
=><?= view_cell("\App\Controllers\SubFolderTwo\Test::render"); ?> - The first call will return the result of first controller, but the second call will also return the content of first controller instead of the second controller
Expected Output
The first call will be return the result of first controller, and the second call will be return the content of the second controller.
Anything else?
No response