Objective
-
Given #2241633: Simplify site-specific service overrides, a
services.ymlfile in the site directory is automatically picked up. -
Various services are environment-configurable via
$settingsin settings.php (→Settings); e.g.:$settings['twig_debug'] = TRUE;…whereas these are consumed and injected basically like an
$optionshashmap:class CoreServiceProvider { public function register(ContainerBuilder $container) { $container ->register('twig', 'Drupal\Core\Template\TwigEnvironment') ->addArgument(array( 'debug' => Settings::get('twig_debug', FALSE), ) + $default_options); } } -
Various factory services can be customized via
$settingsin settings.php (→Settings); e.g.:$settings['keyvalue_service_state'] = 'keyvalue.database';…whereas these are consumed by a
ContainerAwarefactory:class KeyValueFactory { public function get($collection) { // [simplified for clarity] $service_id = Settings::get('keyvalue_service_' . $collection, 'keyvalue.database'); return $this->container->get($service_id)->get($collection); } } -
In both cases,
Settingsactually presents an alien to the code. -
In addition, each of those
$settingsin settings.php requires additional documentation to explain that changes to them are only picked up after rebuilding the service container.
Proposed solution
-
Instead of
$settingsin settings.php, leverage the newservices.ymlfile to specify container parameters:parameters: twig.config: debug: true auto_reload: true keyvalue.services: state: keyvalue.database
| Comment | File | Size | Author |
|---|---|---|---|
| #71 | requirements.png | 55.29 KB | dawehner |
| #71 | 2251113-70.patch | 46.83 KB | dawehner |
| #71 | interdiff.txt | 701 bytes | dawehner |
| #66 | 2251113.66.patch | 46.15 KB | alexpott |
| #66 | 62-66-interdiff.txt | 19.93 KB | alexpott |
Comments
Comment #1
sunComment #2
dawehnerI asked myself multiple time why we don't use container parameters. Some possible answers could be: you need to rebuild the container to get new data in there (at least by default),
we just didn't knew about that etc.
This basically means that all Settings we do have are things which are needed before the container is booted up, and so it is a limited amount of usecases we potentially could
all add new methods onto Settings.
Comment #3
berdirThe way Settings *started* was for things that we need *before* we have a container, like the APC classloader setting.
Comment #4
sunInitial prototype to see how it could work + look like.
Converting the two examples that happen to be contained in the issue summary.
Comment #5
sunThe change to Twig worked fine; the change to state (keyvalue) somehow triggers a circular dependency... anyway, needs review. :-)
Comment #7
Crell commentedThis makes sense to me, and seems like a good use of the tools already at our disposal. Caveat is the need to rebuild the container any time you change these values. We have rebuild.php right now, but to make that really easy we ought to add a CLI version too. That would, for me, adequately address the DX question.
I especially love this!
Comment #8
sunNote: Settings that are consumed by service provider classes require a container rebuild already today. (e.g., the Twig settings)
Moving all of those into
services.ymlinherently self-documents on its own that the container needs to be rebuilt for changes to take effect.The common
'factory.'prefix for parameters of factories tries to address #2160705: settings.php setting names are inconsistent (and undocumented) through a simple standard pattern:The idea is that all (
ContainerAware) factories would follow this pattern. That way, whenever you see a factory that gets a%factory.xyz%parameter injected, you immediately know how to customize the services, and you know where to look up the default parameter.Most settings would be converted into container parameters. As @Berdir said, settings only exist for pre-kernel/container configuration. (e.g., custom classloader)
We likely want to adjust the installer to write a
services.ymlfile. (which will be a lot easier than the current code for rewriting the raw PHP code of settings.php)Comment #9
dawehnerAdded a couple of bits:
Comment #11
dawehnerSome progress ...
Comment #12
dawehnerComment #13
dawehnerThis fixes some of the failures. The remaining ones are caused by the missing functionality of being able to inject parameters into the kernel container rebuild.
Comment #15
dawehnerThe YamlFileLoader had internal caching which caused issues as cache is per file, so changing the services.yml file doesn't end up in the container.
Remove the assignment so it is clear that this kinda ready for review.
Comment #17
dawehnerRerolled.
Comment #19
dawehnerThis could be it.
Comment #20
wim leersShouldn't this patch also remove the twig debug/autoreload/cache/… settings from
example.settings.local.php?Other than that, I only could find one nitpick. I looked at everything except the installer.
80 cols.
Comment #21
Crell commentedI couldn't find anything other than #20 to object to, either. Thanks, dawehner!
Comment #22
dawehnerGood catch. I decided to copy over the documentation of the settings.php example into the yml file.
It is so great that we have this standards, now the patch just gets much "easier" to review.
Comment #23
dawehnerTagging.
Comment #24
wim leersFixed a typo and more 80 cols nitpicks.
Combined with #21, I think this is RTBC.
Comment #26
wim leersOops! A lot of unrelated stuff ended up in that patch.
Comment #27
wim leersThis needs a change record, but it needs to update an existing change record. But https://www.drupal.org/node/1922666 is already published and we'd need to create a draft revision of the changes, which d.o doesn't support. So I created a new draft change notice that contains the changes over at https://www.drupal.org/node/2317817. We can then copy that to the existing change record once this is committed.
Comment #28
alexpottWe need a change record that announces that the installer is going to create a
services.ymlfile - or fail if it can not create one.Comment #29
wim leersDone: https://www.drupal.org/node/2317985.
Comment #30
neclimdulThis doesn't look right. I think you're using "/" to mean "or" but we're talking about file paths in this context and / has a very specific meaning.
Comment #31
dawehnerwhat about that?
Comment #32
Crell commentedfiles should be plural. (Do not credit me.)
Comment #33
dawehnerThis seems actually rather major tbh.
Comment #35
dawehnerPerfect 3way merge.
Comment #37
dawehnernot my day.
Comment #38
dawehnerit is green
Comment #39
larowlanhow much cleaner is this than our writing of php in settings.php in the installer.
love it.
next step down this path - db connection settings...
Comment #40
dawehnerdb connection settings is a litte bit difficult due to fast page caching.
Comment #41
moshe weitzman commentedAre we OK with all of this backend config being exposed to the public? Cache backends, bins, etc.? As far as I can tell .yml files are served up by our default .htaccess rules. I suggest we block that for whole Drupal site. If I am off base here, please reset to RTBC.
Comment #42
dawehnerWe should absolutely block them but well, services.yml already exists, so opened a follow up #2321487: Ensure to not serve yml files inside Drupal
@crell agreed
Comment #43
sunStale
$settingsclass property name.Can we rename this variable to
$keyvalue_options?("config" almost always means
Config.)Missing use statement for
Parameter.Doesn't cause errors, because this code is wrapped into a condition that is obsolete and never
TRUEin HEAD.So we can either remove the entire code + condition, or just add a
usestatement (if we want to avoid scope creep).Can we rename this method to
setContainerParameter()?Unlike PHP in
settings.php, excessively lengthy comments do negatively affect the YAML parser performance. (Next to harming DX.)In the first patch, I had heavily shortened these comments already. Was there a particular reason for reverting that?
I don't think we should repeat the epic misery of settings.php comment novels. Instead, let's have minimum info inline + provide more help elsewhere — either in a separate file, or directly pointing to online documentation.
In any case, these notes are unnecessary and should be removed.
Comment #44
damiankloip commentedSome good points. I have made changes for all of those points, except the shortening of the comments.
Comment #45
damiankloip commentedSomehow removed the default settings from the main patch.
Comment #46
damiankloip commentedAnother missing file, sorry for noise!
I would also agree with @sun that comments like this seem a little on the verbose side for a yaml file.
Comment #47
dawehner@sun
Thank you for the review, good points, indeed!
While I do agree in principal dropping that information without a proper replacement yet, is a bad idea. A follow up could move this documentation to drupal.org or somewhere else in the code #2322539: Improve (and shorten) documentation in default.services.yml.
Comment #48
dawehnerSo back to RTBC
Comment #51
dawehnermuh.
Comment #53
alexpottIf settings.php or services.yml...
How come?
Comment #54
dawehnerTypical out of scope change.
Comment #55
dawehnerlet's just re-RTBC
Comment #58
dawehnerIt was green again.
Comment #59
alexpottSorry for nitpicking a comment apart but this still does not feel right.
Should this not be something like: Drupal will try to automatically create settings.php and services.yml files, which are normally in the directory sites/default (to avoid problems when upgrading, Drupal is not packaged with this file). If auto-creation of either file fails, you will need to create the file yourself. Use the template sites/default/default.settings.php or sites/default/default.services.yml respectively.
Comment #60
sunWe could avoid most of the mumbo-jumbo in
install.core.incby maintaining the core-supplied default file in/core/default.services.yml.Most of that utterly complex file copying code only exists, because
default.settings.phpis located in a directory that isn't supposed to contain any default files but is explicitly meant to contain your custom, site-specific code. Therefore, the installer wastes hundreds of lines of code to check whether the default file exists, perform a lame check to ensure it still contains the unmodified original code, ensure file permissions, throw ugly requirements errors, try to copy, and futz with permissions again.For the same reason, the proposal in #1757536: Move settings.php to /settings directory, fold sites.php into settings.php moves
default.settings.phpinto the/coredirectory, too.Still not happy with the excessive verbosity and formatting of docs in default.services.yml. Don't want to block this issue on that though. Can we at least create a follow-up issue, so as to explicitly revisit them after commit?
Comment #61
sunRegarding my second point - Apologies, I didn't recognize the link to #2322539: Improve (and shorten) documentation in default.services.yml in #47.
Comment #62
dawehnerWell, then you are back in having to merge the values when building the container right? Feel free to open a follow up.
You can't be worse than the bot :P Just copy and pasted your solution. It sounded better to read.
Comment #63
sunNope, only the location of the source file differs:
Still copied into
/sites/$site/services.yml. Nothing is merged. But we avoid the hefty belly-dance in install.core.inc to assert that the default/source file hasn't been tampered with.Comment #64
dawehner@sun
Well your approach would certainly be nice as you would no longer have to figure out whether a default file exists etc. though you would have to either special case the logic
for the services.yml file, which is a bad idea, or move the default settings file as well, which feels like a good idea tbh. as long we have a good way to discover it.
Comment #65
dawehnerI guess we can move this back to RTBC now ?
Comment #66
alexpotthere is the lovely exception you get
Patch attached tidies up some stuff and add important checking to system_requirements().
Comment #67
alexpottI have not fixed the exception - you get it if you have a non writeable empty services.yml in place.
Comment #68
dawehner@alexpott
When exactly does that happen for you?
The patch does the exact some for the services file as for the settings.php file. Do you have some special way to run your installation?
Well, the actual reason for that crazyness already exists without that patch: #2325385: Ensure that the error handler does not throw exception itself.
Comment #69
alexpottTo recreate the exception:
This should result in a requirement error.
Comment #70
alexpott#2325385: Ensure that the error handler does not throw exception itself. might have resolved this
Comment #71
dawehnerWow, showing permissions feels almost like getting naked.
According to your description I tried to setup the directory and files:
It tells me that both services.yml and settings.php is not writable, as expected.
Sadly the code never wents into _drupal_log_error().
Looking bad at your exception all I needed to reproduce the issue is to drop the readable flag from the services file.
Now we just have to ensure that the kernel doesn't load a non-readable file. This results in a proper settings page, see screenshot.
Comment #72
moshe weitzman commentedBack to RTBC.
Comment #73
webchickI was able to do a clean install with no issues, apart from #2306271: drupal_set_message(t('whatever')) is double escaped. Didn't spot any code issues in my review.
The DX of this looks like a big win. I've always hated the $settings vs. $config separation, because site builders shouldn't be expected to understand this level of sausage factory. I understand this patch doesn't get us all the way there, but it's a good step in the right direction. The docs improvements are welcome, as well.
One concern that was raised in IRC by beejeebus is the fact that rebuilding the container is an expensive operation, and particularly gnarly on a multi-web head environment with a shared filesystem. Originally it was apparently discussed to only do this during module install/uninstall to keep this pain down, but this will make it so we may do it at random times. ATM this doesn't feel like a commit-blocker, because the settings moved to container parameters in this patch are those you'd only want to change on a dev environment, where this would be less of an issue, generally. But something to keep in mind for future patches we try and use this pattern elsewhere.
In the meantime, committed and pushed to 8.x. Thanks!
Comment #75
star-szrI just updated https://www.drupal.org/node/1922666, not sure if we want to update the timestamp on that one. Made a minor correction for the twig_debug default. I think someone with privileges can delete https://www.drupal.org/node/2317817 now.
And I published https://www.drupal.org/node/2317985 after making one minor tweak. Thanks @Wim Leers for writing both of those up!