Skip to content

[DependencyInjection] [Routing] [Config] Recursive directory loading #11059

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

Closed
wants to merge 3 commits into from
Closed

[DependencyInjection] [Routing] [Config] Recursive directory loading #11059

wants to merge 3 commits into from

Conversation

lavoiesl
Copy link
Contributor

@lavoiesl lavoiesl commented Jun 4, 2014

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #11045
License MIT
Doc PR TODO

See those about creating a cookbook for better file organization:
Issue: symfony/symfony-docs#3680
PR: symfony/symfony-docs#3885

This PR allows to specify a directory to load and it will recursively load all files from it, using the LoaderResolver.

Example

# app/config/config.yml
imports:
    - { resource: 'dev/' }
└── app
   ├── config
   │  ├── common
   │  │  └── framework.yml
   │  │  └── assetic.yml
   │  └── config.yml

It also works for routing configuration:

_common:
    resource: "common/"
    type: directory

Advantages

  1. Allows easy separation of configuration files per bundle.
  2. This could eventually allow a bundle installation tool that would automatically install needed configuration files.
  3. Could superseed the AnnotationDirectoryLoader, so it does not duplicate the logic.
  4. Is entirely optional and introduces no BC break.
  5. Files are loaded lexically with scandir, allowing someone to control the load order through a number prefix.
  6. Even if the initial configuration load may be a little bit longer, it does not impact the compiled configuration (production).

Conflicts

For now, the Routing DirectoryLoader requires the type directory to be specified so it does not conflict with AnnotationDirectoryLoader. However, this could be refactored.

The type declaration requires a patch in AsseticBundle for it to be used on framework.router.resource. The patch is already merged in master, but not in a release yet. Released in 2.5.0. Changing the main router would be like this:

framework:
    router:
        resource: "%kernel.root_dir%/config/routing/common/"
        type: directory

class DirectoryLoader extends FileLoader
{
/**
* @param mixed $file The resource

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be @param string ?

@lavoiesl
Copy link
Contributor Author

Seems like the test failures are not related to this PR.

@fabpot
Copy link
Member

fabpot commented Jun 10, 2014

The doc PR is great but I fail to see how this is related to this PR.

I'm 👎 for this PR as it makes the loading of files non-deterministic (or put another way, random). As the order of file loading is important, automatically loading a directory is not possible/desirable.

@lavoiesl
Copy link
Contributor Author

I must disagree, I am far from alone asking about directory loading, this PR merely adds support for it. It does not force you to use it and I did not even change anything about Symfony itself.

Loading configuration in this fashion is very useful when you have scripts that dump config file in a folder. Multiplying the configuration files also helps maintaining grouped configurations and reduces the risk of merge conflicts. As an example, a small project I am currently working on has 30 config files, 11 parameter files, 9 routing files and so far, everyone loves the new structure.

As for your point about non-deterministic, this is false, scandir sorts all files alphabetically. It is true that it slightly obscures this fact away from the developer’s eye, but Linux has used this scheme for ages, people simply prepend a number when they really need a file before another. You can also use manual inclusion for that specific file. Since this is usually not an issue and there are easy solutions, it seems to me that it would be a very light argument against this PR.

As for the “relation” of the linked doc PR, it is because there have been discussions around directory loading while talking about it. It also seems that if my PR was accepted, this is exactly the section of the Cookbook in which we would talk about it.

@stof
Copy link
Member

stof commented Jun 10, 2014

@fabpot For DI files, the order may not be significant depending of how you organize your files. I know that some people are splitting the semantic configuration into a separate file per bundle. In this case, the order of these files is not important as they don't override each other. This would make the import much easier to do in such case.
for the routing, it is indeed more problematic as it removes the control on the order of routes

@stof
Copy link
Member

stof commented Jun 10, 2014

and regarding the doc PR, it was documenting the usage of such a loader at some point, before figuring out that it is not available currently in core.

@lavoiesl
Copy link
Contributor Author

Routing currently uses AnnotationDirectoryLoader, written by @fabpot, that does almost exactly the same as my loader, but restricted to PHP files. This is what parses the Route annotations. It is also what conflicts with my loader (see the description). Eventually, they could even be merged together.

@javiereguiluz
Copy link
Member

Regarding the "non-deterministic loading problem", I can't really understand the differences with the current situation.

This works today and loads routes from an infinite number of controller files whose order you cannot control:

_routes:
    resource: "@AcmeDemoBundle/Controller"
    type:     annotation

The proposed solution works exactly the same, with the added advantage that you can easily prefix numbers to files and directories (as suggested by @stof and as done for the Doctrine fixture files) to control the load order (you cannot do that with controller classes):

_routes:
    resource: "common/"
    type:      directory

@xabbuh
Copy link
Member

xabbuh commented Dec 14, 2014

Should this be closed given that #11045 was closed?

@lavoiesl
Copy link
Contributor Author

It seems to me that the merging of this PR is being blocked for obscure reasons and no good chance have been given to it.

Here is an account of all the arguments I can recall:

Pros:

  1. Allows easy separation of configuration files per bundle.
  2. This could eventually allow a bundle installation tool that would automatically install needed configuration files.
  3. Could superseed the AnnotationDirectoryLoader, so it does not duplicate the logic.
  4. Is entirely optional and introduces no BC break.
  5. Files are loaded lexically with scandir, allowing someone to control the load order through a number prefix.
  6. Even if the initial configuration load may be a little bit longer, it does not impact the compiled configuration (production).

Cons:

  1. When a new file a added to a directory, it is not automatically detected in dev, one must run cache:clear manually. (This could probably be fixed) Fixed

@weaverryan, Do you think this would be of any benefit? (I’m talking about DX here).

@javiereguiluz
Copy link
Member

@lavoiesl you've certainly listed a lot of good reasons to promote this PR. I wish you can finally make it!

@stof
Copy link
Member

stof commented Jan 4, 2015

This could indeed help people.
And the case of new files can be fixed by adding the directory as a DirectoryResource btw.

@lavoiesl could you rebase your branch on top of the 2.7 branch (and resubmit the PR to the 2.7 branch) to give it a chance to make it in ?

@lavoiesl
Copy link
Contributor Author

lavoiesl commented Jan 4, 2015

Can someone give me a hand, the Travis build is failing on components=high and components=low because my class is missing. The rest runs fine (on my computer as well). I tried greping for a bunch of stuff but I’m stuck. https://travis-ci.org/lavoiesl/symfony/jobs/45859741#L2288

lavoiesl and others added 2 commits January 4, 2015 11:42
Issue #11045

For now, the Routing DirectoryLoader requires the type `directory`
to be specified so it does not conflict with `AnnotationDirectoryLoader`.
However, this could be refactored.

The type declaration requires a [patch in AsseticBundle](symfony/assetic-bundle@f76291c)
for it to be used on `framework.router.resource`. The patch is already merged in master, but not in a release yet.
@lavoiesl
Copy link
Contributor Author

lavoiesl commented Jan 4, 2015

@stof You were right for DirectoryResource, thanks. I don’t know how I missed it, I had it for the routing loader.

@lavoiesl lavoiesl closed this Jan 4, 2015
fabpot added a commit that referenced this pull request Jun 5, 2015
…ectory loading (lavoiesl, nicolas-grekas)

This PR was merged into the 2.8 branch.

Discussion
----------

[DependencyInjection] [Routing] [Config] Recursive directory loading

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #13246, #11045, #11059
| License       | MIT
| Doc PR        | -

Commits
-------

60b1c5b Added CHANGELOG entries, cleanups
73f0ee2 [DI][Routing] recursive directory loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants