Hình ảnh giao diện như sau :
If you have not read Alex Bronstein's (effulgentsia's) excellent blog post about creating your first Drupal 8 module, go read it: Drupal 8: Hello OOP, Hello world! This post will expand on Alex's discussion and introduce the new configuration API in Drupal 8. Here we will have the modest goal of making the display of the text "Hello, World!" configurable -- more specifically, we will give site administrators the ability to make the text UPPERCASE or Title Case. I can tell you are excited.
Fortunately, the .info.yml
file does not need to change:
hello.info.yml
We need to add some code to the routing file, and it will follow a similar organization as before:
hello.routing.yml
Notice that instead of adding _content
, this route adds a _form
so that when a visitor goes to hello/config
, the HelloConfigForm
will get called. So far so good.
The .module file also should look rather familiar:
hello.module
The second of the two $items
connects the URL hello/config
with the route hello.settings_form
, which will appear again in the next few code examples. Still seems fairly straightforward.
When the Hello module is installed, we want to have a default case setting configured, so let's make the text title case by default.
config/hello.settings.yml
Out of the box, Drupal's new configuration system uses two directories for configuration: active and staging. When the Hello module is enabled, the configuration system will look in the Hello module's config
directory and find hello.settings.yml
. Then it will create a new file in the "active" configuration directory, also named hello.settings.yml
, with the same single line that reads case: title
. The default location for the active and staging directories is sites/default/files/config_xxx
, with xxx being a hash that is unique to each Drupal installation for security purposes (security options were discussed at length in this thread: https://groups.drupal.org/node/155559).
Although we could have accomplished the same thing in an install file by implementing hook_install()
and callingDrupal::config('hello.settings')->set('case', 'title')->save();
, the preferred -- and easier -- method is to provide default configuration for the module in a config
directory (as we have done).
The HelloController
class needs to be altered so that it will display the correct case:
lib/Drupal/hello/Controller/HelloController.php
While hello.install
interacted with the configuration system using the Drupal class, calling Drupal::config()
, the Drupal class exists only to support legacy code. In HelloController
we take another shortcut of sorts by extending a fairly recent addition to Drupal core,ControllerBase. This class was created to "stop the boilerplate code madness" by providing access to a number of utility methods, including config()
. This class should only be used for "trivial glue code," and I think our Hello, World! module qualifies.
To give site administrators the ability to change the display from title case to uppercase, we will use a form. Much like putting the controller in lib/Drupal/hello/Controller/HelloController.php
, the code for the configuration form goes inlib/Drupal/hello/Form/HelloConfigForm.php
. It's not a requirement, but it is a convention to put forms in a Form directory and use the word Form in the filename. Here is the code for the form:
lib/Drupal/hello/Form/HelloConfigForm.php
This form contains what was previously described as "boilerplate madness" and illustrates the preferred way of interacting with Drupal's configuration system: via dependency injection. The "boilerplate" parts include the use
statements near the top, the__construct()
method, and the create()
method.
Dependency injection is the design pattern that all of the cool kids use. It allows developers the ability to standardize and centralize the way objects are constructed. If you want to read more about dependency injection, check out Crell's WSCCI Conversion Guide orthis change record. If you want to watch a presentation about it, check out Kat Bailey's talk Dependency Injection in Drupal 8. If you want to explain it to a five year old, read this stackoverflow answer.
For the HelloConfigForm
, dependency injection enables code like this: $config = $this->configFactory->get('hello.settings')
. It's a lot more code than writing Drupal::config() or ControllerBase::config() -- and we could have dropped three of the four use
statements and omitted two of the methods -- but I assure you that dependency injection is the preferred method.
The rest of the code should look rather familiar if you already know about writing modules with Drupal 7. You can read more about the {@inheritdoc}
in this issue, but the basic idea is that it is less code. (If you want to read more about forms in Drupal 8, check outDrupal 8: Forms, OOP style).
This may seem like a fair amount of code just to use the configuration system, but in fact this Hello module takes advantage of multiple new features offered by Drupal 8. The meat of this process could be reduced to four steps, and only the last two access configuration:
- Implement
hook_menu()
- Add a route in
hello.routing.yml
- Create a controller to display the text
- Create a configuration form
Of course the most important part of this code is that we're using Drupal's new configuration system. This Hello module stores its configuration data in a configuration file (and in the database in the cache_config table), and each time the form is changedsites/default/files/config_xxx/active/hello.settings.yml
is updated, thus allowing the ability to transfer configuration between sites. That, however, is a topic for another post.
Until then, you can come to this site to learn more about the Configuration Management Initiative, find links to documentation, issues that need work, and much more. If you would like to get involved, the issues that are the most important for Configuration Management are listed on http://drupal8cmi.org/focus.