#1086·PHP-Parser

Use Composer PHP required version

Author: BrianHenryIECreated Jun 1, 2025Updated Oct 8, 2025

Would it be a good idea to determine the Composer platform / minimum PHP version and use that for instantiating the parser?

php

    public function createFromComposer(): Parser {
        return $this->createForVersion(
            PhpVersion::fromString(
                $this->determineMinimumPhpVersion()
            )
        );
    }

    private function determineMinimumPhpVersion(): string {

        $phpParserNewestPhpVersion = PhpVersion::getNewestSupported();
        $phpParserNewestPhpVersionFiveDigitInt = $phpParserNewestPhpVersion->id;

        $major = intval($phpParserNewestPhpVersionFiveDigitInt / 10000);
        $minor = ($phpParserNewestPhpVersionFiveDigitInt - ($major * 10000)) / 100;

        $highestMinimumPhpVersion = "{$major}.{$minor}";

        // Try to determine the Composer minimum PHP version.
        if ( class_exists( InstalledVersions::class ) ) {

            $rootPackage = InstalledVersions::getRootPackage();

            // TODO: refactor to a real method
            $getMinimumPhpVersionFromString = function(string $versionsString) use ($highestMinimumPhpVersion): string {
                if(0 < preg_match_all('/\d+(?:\.\d+)?(?:\.\d+)?/', $versionsString, $minimumPhpVersions )) {

                    $minimumPhpVersion = array_reduce( $minimumPhpVersions[0], function ( $carry, $minimumPhpVersion ) {
                        return version_compare( $minimumPhpVersion, $carry, '<' )
                            ? $minimumPhpVersion
                            : $carry;
                    }, $highestMinimumPhpVersion );
                } else {
                    $minimumPhpVersion = $highestMinimumPhpVersion;
                }
                return $minimumPhpVersion;
            };

            /**
             * "config": {
             *   "platform": {
             *     "php": "7.3.0"
             *   }
             * }
             */
            if ( isset( $rootPackage['config'], $rootPackage['config']['platform'], $rootPackage['config']['platform']['php'] ) ) {
                $minimumPhpVersion = $rootPackage['config']['platform']['php'];
            } elseif ( isset( $rootPackage['require'], $rootPackage['require']['php'] ) ) {
                /**
                 * {
                 *   "require": {
                 *     "php": ">=7.4"
                 *   }
                 * }
                 */
                $minimumPhpVersion = $getMinimumPhpVersionFromString($rootPackage['require']['php']);
            } else {
                // Scan all required packages for their minimum PHP version.

                $reflectionClass       = new \ReflectionClass( InstalledVersions::class );
                $installedVersionsPath = $reflectionClass->getFileName();

                $minimumPhpVersionsString = '';

                $installedJsonPath = \dirname($installedVersionsPath) . '/installed.json';
                if (\file_exists($installedJsonPath)) {
                    $installedJson = \json_decode(\file_get_contents($installedJsonPath), true);
                    if (isset($installedJson['packages'])) {
                        foreach ($installedJson['packages'] as $package) {
                            if (isset($package['require']['php'])) {
                                $minimumPhpVersionsString .= ' ' . $package['require']['php'];
                            }
                        }
                    }
                }

                $minimumPhpVersion = $getMinimumPhpVersionFromString($minimumPhpVersionsString);
            }
        } else {
            // Fallback to the highest minimum PHP version supported by php-parser
            $minimumPhpVersion = $highestMinimumPhpVersion;
        }

        // Should be 7.4 or higher. Where can that be found in php-parser?
        return version_compare($minimumPhpVersion, '7.4', '<') ? '7.4' : $minimumPhpVersion;
    }

Composer doesn't seem to expose the value it uses in platform-check.php but also, I don't think that file is always created.

Image

I'm really just dipping my toes in php-parser so far. I'll open a PR if this is a good idea. And if it's not, I look forward to better understanding the tool.

I'm using it in brianhenryie/strauss which to-date has been doing namespace replacements with regex, but regex is hitting its limits.