Problem/Motivation
When Package Manager executes Composer, it invokes it directly (e.g. vendor/bin/composer ...). The first line of that file is the shebang line #!/usr/bin/env php, which can cause Composer to execute through the wrong PHP interpreter -- i.e., a version different than the one being used to run Drupal -- if that's the one that's first found in the web server's PATH.
Since the running PHP version has an influence on Composer's dependency solver, this can potentially cause bigger problems that would be very hard to debug in retrospect.
Proposed resolution
It is possible to execute Composer's binary through the PHP interpreter: php vendor/bin/composer ....
So let's override Composer Stager's Composer runner and have it always run Composer through the current PHP interpreter, which we can discover using PHP_BINDIR and which should work pretty consistently across different SAPIs and operating systems.
This change would require no UI or API changes, nor would it affect backwards compatibility. It would change some explicitly internal (and final) classes in Package Manager, and allow us to remove a fairly obvious and slightly brittle hack.
Issue fork drupal-3501582
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- run-composer-thru-php
changes, plain diff MR !12614
Comments
Comment #2
phenaproximaThis already exists. Package Manager has a configuration object where you can set the explicit path to Composer: https://git.drupalcode.org/project/drupal/-/blob/11.x/core/modules/packa...
So you could just do this:
drush cset package_manager.settings executables.composer /path/to/composerSetting this value is probably not necessary in DDEV because I think Composer is available to the web server, but outside of DDEV I'm not sure there's much that Drupal CMS can do about this since it is completely server-specific.
Leaving this open for now in case anyone has some idea about what we could do here, but I'm kinda tempted to call this a "won't fix".
Comment #3
juxelle commentedThanks phenaproxima. That command didn't work but I found there was some help text in the package_manager module and after installing the help module I could see how to add the config to my settings.
So you're right, there is a config available and it works on shared hosting. Thanks.
Comment #4
phenaproximaGreat! Closing this out, since everything works as designed here.
Comment #5
bigbaldy commented#2 only solves half of the problem. "drush cset package_manager.settings executables.composer /path/to/composer" works but on the hosting server (pair.com) I use the wrong PHP client version is used. There needs to be a way to also point to the proper php cli version. For PHP.cgi I can point to the proper version for Drupal but accessing composer though package_manager connects to the hosting server's default of PHP 7.4.33 and so far, I have not been able to find a way to force the connection to a valid version of PHP needed for the needed version of composer.
Comment #6
phenaproximaWhen it comes to the PHP interpreter, there's not a ton we can do about that, honestly, at least not in Drupal CMS. This probably would need to be fixed upstream in Package Manager (which is a core module).
Moving to core's issue queue and retitling for that.
Comment #7
phenaproximaComment #8
quietone commentedComment #9
bigbaldy commentedHere is a workaround for FastCGI on a shared hosting server with ssh access.
The challenge is that composer only looks for 'php' and there isn't a direct way to identify an alternatively named php and php.ini location.
The following script can be placed in your local bin folder. Follow the instructions in the script and edit it for your environment:
Add the following lines to your Drupal settings.ini file:
'additional_trusted_composer_plugins' is need for some of the CMS recipies.
'include_unknown_files_in_project_root' is needed if you need to modify your environment using assets stored outside of Drupal CMS's root. In my case I need to modify .htaccess for FastCGI.
Comment #10
londova commentedThe whole idea of Drupal CMS was to make the installation process simple and accessible even to non-coding users.
This bug definitely needs to be fixed, otherwise Drupal CMS become a NON-SENSE.
Comment #11
londova commentedComment #12
mediameriquat commentedI'm also struggling with this issue. Drupal CMS was supposed to work out of the box :(
#2 does not work for me. However, I'm not 100% sure my Composer path is correctly written (my installation is on a shared hosting):
drush cset package_manager.settings executables.composer /home/accountname/.composer
Comment #13
londova commentedComment #14
phenaproximaThis issue definitely belongs in Drupal core, since that's where Package Manager comes from.
A workaround already exists (setting the path the Composer at the command line with Drush), as documented towards the top of the issue.
And, in reply to #10: we know this needs to be improved, but there are some tricky considerations here (such as what happens when moving the config between environments), and we don't want the bug fix to introduce more bugs. Complaining is not helpful; actually working on a merge request (or testing one) would be greatly appreciated.
Comment #15
catch@mediameriquat are you able to check the version of composer installed on your hosting? I think there's another issue somewhere where the message when composer is too outdated is not very explanatory.
Comment #16
mediameriquat commented@catch My Composer version was outdated indeed. Looks like cPanel installs 2.3.10 by default.
After updating Composer to 2.8.8. and setting the path to /home/[username]/bin/composer/composer.phar, I get a less verbose error message :
Composer was not found. The error message was: Syntax error
Still the wrong path, I guess...
+++
Take note that running the "composer diagnose" command generates an error after updating to 2.8.8:
Checking composer.lock: FAIL
platform : Array value found, but an object is required
platform-dev : Array value found, but an object is required
This has to do with curly brackets being replaced by [ ]. But fixing the typo does not solve the above syntax error.
Comment #17
phenaproximaDid you make composer.phar executable (
chmod +x /path/to/composer.phar)?Comment #18
mediameriquat commented@phenaproxima My composer.phar is executable, yes. Thanks for reminding me of checking those pesky permissions.
Comment #19
bigbaldy commented@mediameroquat check #9. My host has and outdated Composer as default and the default PHP points to an outdated version. I have had Composer and PHP working for a few months now.
Comment #20
mediameriquat commentedI contacted my web host to know the server-wide Composer path. On a cPanel shared hosting, I ran the #2 drush command as follows and bingo!
drush cset package_manager.settings executables.composer /opt/cpanel/composer/bin/composer
However, automatic updates are not yet possible, because I get another error message: rsync is not available. This is a totally different issue.
+++
As far as my experience goes, I don't see how Drupal CMS can ever compete with WordPress and/or hosted solutions such as Wix. WordPress is overrated and chaotic, but it can be installed in 5 minutes without DDEV or other cumbersome local environments, and automatic updates will work on any shared platform.
Comment #21
phenaproximarsync is another one where you can configure the path to it, if it's on the web server and you have permission to execute it. If you can SSH in,
which rsyncshould give you the path, then you can do:Comment #22
catchComment #24
phenaproximaStill needs an issue summary update, but the MR was pretty simple to write. This removes an internal class that was very clearly and explicitly marked as internal, and subject to change or removal at any time...so I feel okay about it. It's also a significantly cleaner way to change the way Composer is executed, without having to resort to the weird hacks that ProcessFactory used.
The use of
PHP_BINDIRshould work even in cases where PHP is being run through, say, PHP-FPM (which would be the case withPHP_BINARY).Comment #25
phenaproximaComment #26
phenaproximaComment #27
catchThis looks encouraging to me, I only scanned the MR so far, but it's a net reduction in the diff too.
Comment #28
phenaproximaHmmm...we might need to think a little bit more about this, because of https://stackoverflow.com/questions/35460281/php-bindir-on-windows-incor...
That could get squirrelly in some situations, especially Windows, since people aren't compiling PHP on Windows. I wonder if
dirname(PHP_BINARY)is a safer approach.Comment #29
phenaproximaComment #30
phenaproximaI think we're probably safe if we use the
PhpExecutableFinderclass that comes with Symfony's Process component. It does a pretty robust job of searching for the PHP interpreter, based on the current OS and server API, and is the standard tool for finding the PHP interpreter. It's a documented part of the Symfony Process API: https://symfony.com/doc/current/components/process.html#finding-the-exec...Comment #31
tim.plunkettThis looks great, thanks for the explanation in #30.
Comment #34
catchThis looks really good to me and I can't really see a problem doing it. No API surface involved - everything is explicitly @internal, so we can backport to 11.2.x. Some of the related issues are trickier but this one is mostly straightforward.
Committed/pushed to 11.x and cherry-picked to 11.2.x, thanks!