Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Add autoloader root directory config #8387

Closed
marekdedic opened this issue Oct 22, 2019 · 11 comments
Closed

[RFC] Add autoloader root directory config #8387

marekdedic opened this issue Oct 22, 2019 · 11 comments
Labels

Comments

@marekdedic
Copy link

Current behaviour

composer.json:

"config": {},
"autoload": {
    "psr-4": {
        "MyApp\\": "src/php/MyApp/"
    }
},

Gives the following vendor/composer/autoload_psr4.php:

<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'MyApp\\' => array($baseDir . '/src/php/MyApp')
);

Proposed behaviour

composer.json:

"config": {
    "autoloader-root-dir": "src/php/"
},
"autoload": {
    "psr-4": {
        "MyApp\\": "MyApp/"
    }
},

Would give the following vendor/composer/autoload_psr4.php:

<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'MyApp\\' => array($baseDir . '/MyApp')
);

I.e. the generated file would look as if composer.json were in the src/php/ directory. Only descending the folder tree would be allowed, so you cannot do something like "autoloader-root-dir": "../somewhereElse/". The name autoloader-root-dir is tentative.

Motivation

Built applications

In modern web development, codebases quite often use multiple languages, some of them compiled (typically something akin to TypeScript compiled to JavaScript). This means that the final application needs to be built. To cleanly separate the source files from the build artifacts, one would want to place all the source files into one directory (e. g. src) and have the built app in another one (e. g. dist). However, the composer.json file would typically be in the root of the repository - that is, not in the src folder. Under the current behaviour, there is no way to do this, not have the final php files somewhere like dist/src/ and have a working autoloader. This RFC would enable that by setting "autoloader-root-dir": "src/".

Separating configuration files from the application itself

When an app is deployed, sometimes it is undesirable to deploy configuration files such as .travis-ci.yml or similar. With this RFC, one could put the actual application in a dedicated directory (e. g. app/), keep all the configuration files (including composer.json) in the root of the repo and still have a working autoloader by setting "vendor-dir": "app/vendor" and "autoloader-root-dir": "app/".

This issue is a continuation of the recent debate in #5198. I would be willing to take a try at a PR, if the feature is deemed appropriate for inclusion in composer.

@stof
Copy link
Contributor

stof commented Oct 22, 2019

For PHP 5.6+, the relevant file for the autoloader is not autoload_psr4.php but autoload_static.php which makes such that no variables are ever used in the config array so that the array of paths can stay in the OPCache shared memory.
And IIRC, composer uses the shortest relative path possible for that. So with your own code in app/MyApp and the vendors in app/vendor, autoload_static.php may already have the expected ../MyApp path (to be confirmed). So the second case my already be solved.

@marekdedic
Copy link
Author

marekdedic commented Oct 22, 2019

Thanks, I didn't know that.

For me the main use case is the first one, however the second one was mentioned by some people in the linked issue. If it turns out to be solved already, that's great.

@Seldaek
Copy link
Member

Seldaek commented Oct 24, 2019

What if you set vendor-dir to src/vendor? then the relative path should be ../MyApp, and if you then copy src/vendor to dist/vendor it should still work.

I'd rather avoid adding a new parameter for such a custom use case if it can be achieved with existing infrastructure.

@Seldaek
Copy link
Member

Seldaek commented Oct 24, 2019

Hmm yeah no sorry re-reading the description I guess this isn't gonna work. I am not sure I fully understand what you are trying to achieve though, more details would be good to really see what the point is and whether it's something we want to support if it isn't yet.

@alcohol
Copy link
Member

alcohol commented Oct 29, 2019

I find the arguments rather weak and lacking. In "modern" web development, one deploys build artifacts, not entire git repositories. So the structure of your git repository is irrelevant. This immediately solves both "issues" (separation of source and distribution files, and config files from build services and such).

@marekdedic
Copy link
Author

And IIRC, composer uses the shortest relative path possible for that. So with your own code in app/MyApp and the vendors in app/vendor, autoload_static.php may already have the expected ../MyApp path (to be confirmed). So the second case my already be solved.

I've tried it and can confirm that that works. That leaves the first issue which I would like to solve

I have a git repo of the following:

├── composer.php
├── src
│   ├── php
│   │   ├── index.php
│   │   └── MyApp
│   │         └── MyClass.php
│   └── js
│         └── ...
├── vendor
      └── ...

I would like to create (with any build system, I don't really care) a dist directory which I could upload to a webhosting (it being a build artifact as @alcohol pointed out). I imagined it being of the sort:

├── index.php
├── MyApp
│   └── MyClass.php
├── js
      └── ...
└── vendor
      └── ...

But, by now, the path from vendor/composer/autoload_static.php to MyApp/MyClass.php has changed. So the autoloading would no longer work. But with the proposed new config parameter, I could set

"config": {
    "autoloader-root-dir": "src/php/"
}

and then autoloading would work in the build artifact directory.

Why not just use vendor-dir then? Because that would require me putting the vendor dir in src/php. But the vendor dir is not source code for me - therefore, I wouldn't want it in the src directory.

Clearer now? I think the exact organization of the dist directory could be different a bit, but the overall idea would stay the same. I'd like to hear your thoughts on this.

@Seldaek
Copy link
Member

Seldaek commented Jan 21, 2020

What you need to configure here is your webhosting's webroot to point to src/php/ so it can find index.php at the root, but vendors are not present within the webroot. This is a best practice as having vendors in the webroot mean people can easily access your dependencies which might reveal vulnerable software etc.

@marekdedic
Copy link
Author

This is a best practice as having vendors in the webroot mean people can easily access your dependencies which might reveal vulnerable software etc.

Thanks for the advice, I did not know that.

However, unfortunately, this is not a good solution on its own - I can't set the webroot to src/php as the files in src are sources - not build artifacts. And the web/app needs to run from the build artifacts, not the sources... Any other ideas? Solving this without needing to add anything would of course be preferable...

@Seldaek
Copy link
Member

Seldaek commented Jan 24, 2020

Then put the build artifacts wherever you need, and make sure that's the web root, and that the web root contains an index.php which includes whatever path is needed so it finds vendor dir etc, even tho that should be in a separate directory.

For example Symfony's standard distro has a web dir with app.php being the index file/front controller, you can see what's in the web dir, it should be only things that should be accessible by user browsers. And the web root should be web/

@RaymondBakker
Copy link

It baffles me this hasn't just been added yet. Just give people the flexibility instead of point towards web host configs.

@alcohol
Copy link
Member

alcohol commented Feb 18, 2020

Yes, well, luckily we don't have to make decisions based on what baffles some individuals and what not.

@composer composer locked as too heated and limited conversation to collaborators Feb 18, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants