Skip to content

Conversation

@samsonasik
Copy link
Member

@samsonasik samsonasik commented Oct 8, 2025

@TomasVotruba @staabm per rectorphp/rector#9416 (comment) this is ensure load early preload.php on bootstrap.php when running PHPUnit.

This preload is needed to avoid user require different nikic/PHP-Parser or phpstan/phpdoc-parser versions because of their project requirement, eg:

# get rector
composer require --dev rector/rector

# get nikic/php-parser v4
# when on phpunit < 12, 
# it resolvable by load vendor/rector/rector/preload.php in phpunit bootstrap config
# on phpunit >=12 use case, the autoload is too early loaded.
composer require nikic/php-parser:^4.0

# get phpstan/phpdoc-parser v1
composer require phpstan/phpdoc-parser:^1.0

without the preload early, this will cause error as we are using nikic/php-parser v5 and phpstan/phpdoc-parser v2.

This patch ensure on version PHPUnit 12 only so we have issue patch isolated.

@samsonasik
Copy link
Member Author

PHPUnit has PHPUnit\Runner\Version, I added handling to load early on phpunit 12.0+ only 👍 d0fbaf9

@samsonasik
Copy link
Member Author

samsonasik commented Oct 8, 2025

/cc @Androoha1 @nikophil @staabm @megawubs @ivastly @nikophil @devnix @ostrolucky @smnandre I need help to test this patch:

Please try this patch:

  1. First, ensure you're using PHPUnit 12+ already, as this patch is only handling on PHPUnit 12+.
  2. Remove previous hack on composer.json -> files handling if exists
  3. Run composer update
  4. Manually update file: vendor/rector/rector/bootstrap.php and update with this patch on this PR
  5. Run phpunit.

I myself tested in repository https://github.com/ostrolucky/rector-rules and seems working ok

  1. git clone https://github.com/ostrolucky/rector-rules
  2. Run composer install
  3. Manually update Open vendor/rector/rector/bootstrap.php and update with this patch
  4. Run vendor/bin/phpunit

@samsonasik
Copy link
Member Author

All checks have passed 🎉 @TomasVotruba it is ready for review.

@samsonasik samsonasik changed the title [Scoped] Load early preload.php on scoped bootstrap.php on phpunit running [Scoped] Load early preload.php on scoped bootstrap.php on phpunit 12+ running Oct 8, 2025
@nikophil
Copy link
Contributor

nikophil commented Oct 8, 2025

Hi @samsonasik

here is what I did:

  • upgrade to rector dev-main
  • tweak the vendor/rector/rector/bootstrap.php
  • used this bootstrap.php in my bootstrap.php file, instead of preload.php
  • run vendor/bin/phpunit -c phpunit-rector.xml.dist (phpunit >=12)

and I still have the error

@samsonasik
Copy link
Member Author

samsonasik commented Oct 8, 2025

@nikophil you don't need to include it in your phpunit bootstrap, in phpunit 12, vendor/autoload.php is loaded too early, here to fix yours:

-require \dirname(__DIR__).'/../../bin/tools/rector/vendor/rector/rector/preload.php';

the rector bootstrap is auto-included it.

@nikophil
Copy link
Contributor

nikophil commented Oct 8, 2025

still the same problem 🤷

@samsonasik
Copy link
Member Author

@nikophil Ok, it seems it is due to you load from different paths vendor locations, phpunit is load vendor/autoload.php of the project even you don't write it, create custom autoload will make it loaded twice.

Could you create simpler repo so I can run locally? currently got database error. Thank you.

@nikophil
Copy link
Contributor

nikophil commented Oct 8, 2025

you have DB error running vendor/bin/phpunit -c phpunit-rector.xml.dist ?

@samsonasik
Copy link
Member Author

I got error failed to open stream for that

➜  foundry git:(2.x) vendor/bin/phpunit -c phpunit-rector.xml.dist
PHP Warning:  require(/Users/samsonasik/www/foundry/utils/rector/../../bin/tools/rector/vendor/rector/rector/preload.php): Failed to open stream: No such file or directory in /Users/samsonasik/www/foundry/utils/rector/tests/bootstrap.php on line 12

Warning: require(/Users/samsonasik/www/foundry/utils/rector/../../bin/tools/rector/vendor/rector/rector/preload.php): Failed to open stream: No such file or directory in /Users/samsonasik/www/foundry/utils/rector/tests/bootstrap.php on line 12
PHPUnit 12.4.0 by Sebastian Bergmann and contributors.

Probably some installation steps missing?

@nikophil
Copy link
Contributor

nikophil commented Oct 8, 2025

we're using https://github.com/bamarni/composer-bin-plugin for tools like rector, phpstan, ...

please run

composer bin rector install
composer bin phpstan install

@samsonasik
Copy link
Member Author

samsonasik commented Oct 8, 2025

Okay, I reproduce the error

git clone git@github.com:zenstruck/foundry.git
cd foundry
composer install

➜  foundry git:(2.x) composer update phpunit/phpunit:^12 brianium/paratest -W
➜  foundry git:(2.x) composer bin phpstan install
➜  foundry git:(2.x) composer bin rector install

➜  foundry git:(2.x) vendor/bin/phpunit -c phpunit-rector.xml.dist           
PHP Fatal error:  Cannot declare interface PhpParser\NodeVisitor, because the name is already in use in /Users/samsonasik/www/foundry/bin/tools/rector/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php on line 6

Fatal error: Cannot declare interface PhpParser\NodeVisitor, because the name is already in use in /Users/samsonasik/www/foundry/bin/tools/rector/vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php on line 6

I will look into it 👍

@samsonasik
Copy link
Member Author

samsonasik commented Oct 8, 2025

@nikophil I see, it seems you're using custom path for rector path, this is not recommended as autoload juggling may happen.

Your Project autoload: vendor/autoload.php
Your Rector autoload: /../../bin/tools/rector/vendor/autoload.php

Use same path of autoload should be easier to catch the autoload bug.

This may not resolvable by this tweak, as autoload are different, can't guarantee if I can get the solution, as autoload are juggling, but I will still look into it for your use case :)

@TomasVotruba
Copy link
Member

I'll try this once I'm near laptop 👍

@samsonasik
Copy link
Member Author

samsonasik commented Oct 8, 2025

@nikophil after back and forth check, the solution for your use case is to avoid multiple autoloads definition, on this patch is the following steps:

  1. Use only single vendor/autoload.php as your project dependencies autoload for project and rector, so require-dev it:
# open root project
cd foundry

composer require --dev rector/rector
  1. open phpunit-rector.xml.dist and change:
-         bootstrap="utils/rector/tests/bootstrap.php"
+         bootstrap="vendor/autoload.php"
  1. Change Manually root vendor/rector/rector/bootstrap.php, add this patch
  2. run phpunit
➜  foundry git:(2.x) php84 \vendor/bin/phpunit -c phpunit-rector.xml.dist
PHPUnit 12.4.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.4.0RC1
Configuration: /Users/samsonasik/www/foundry/phpunit-rector.xml.dist

.......................................                           39 / 39 (100%)

Time: 00:00.345, Memory: 78.50 MB

OK (39 tests, 49 assertions)

That's the way, PHPUnit 12 custom autoload is just not works as it should be, as the project autoload is loaded to early, this is the only way.

I commented at PHPUnit issue on it:

@samsonasik
Copy link
Member Author

@TomasVotruba I got the line starter error why preload.php is by default loaded later after vendor/autoload.php, it is because it defined in AbstractLazyTestCase::includePreloadFilesAndScoperAutoload()

private function includePreloadFilesAndScoperAutoload(): void
{
if (file_exists(__DIR__ . '/../../../preload.php')) {
if (file_exists(__DIR__ . '/../../../vendor')) {
require_once __DIR__ . '/../../../preload.php';

this still needs to be verified if remove this from order may cause issue as rely on vendor/autoload.php may cause invalid class/logic definitions, I will look into it.

@samsonasik
Copy link
Member Author

@TomasVotruba I created alternative PR for patch on AbstractLazyTestCase instead so it has isolated patch:

@TomasVotruba
Copy link
Member

Just testing it on ostrolucky rules. Works well 👍 I forgot we can change autolaod position by leveraging the bootstrap.php file in composer.json. Cool trick :)

I'll merge this, but keep the issue open, to track whole context around it and look for native ways solve this.

@TomasVotruba TomasVotruba merged commit 188b90a into main Oct 9, 2025
50 checks passed
@TomasVotruba TomasVotruba deleted the load-preload branch October 9, 2025 13:54
@samsonasik
Copy link
Member Author

@TomasVotruba I am thinking that the alternative solution is possibly better, since only change the rector code testing area;

This PR is too a little too drastic since it change the autoload.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants