Drupal Association blog: Join us for 10 Days of Drupal 10!

Drupal 10 is almost here, and we cannot wait for the community to experience the latest version of Drupal! With an expected release date of 14 December, we have less than two weeks to go. The Drupal Association is hosting 10 Days of Drupal 10 giveaways in celebration of the release! 

From 5 December to 14 December, tag us daily on Twitter with a Drupal 10-themed meme or graphic for the chance to WIN an exclusive Drupal 10 hoodie. Your Drupal 10 meme or graphic can be highlighting one of your favorite Drupal 10 features, upgrades, or anything else related to Drupal 10.

Here are some examples for inspiration:

Image removed. Image removed.

Then, on #Drupal10’s expected release day, 14 December, we’re giving two lucky winners a chance to win a ticket to DrupalCon Lille or DrupalCon Pittsburgh (your choice!). To win, all you have to do is tag us with a video of your Drupal 10 release party. After that, we’ll randomly choose two winners to receive one ticket each.

We want to see how you celebrate the release, so feel free to get creative and show us your celebration. We can’t wait to see all of your videos!

On Monday, 5 December, head to the Drupal Association Twitter account, @DrupalAssoc, for the kickoff of 10 Days of Drupal 10 and your chance to win! In the meantime, check out the new features on the Drupal 10 page. The Drupal 10 page also contains all the information you’ll need to ensure a smooth upgrade to Drupal 10.

Are you hosting a Drupal 10 party in celebration of the release? Share it with the community by adding it to the Community Events page on Drupal org!

Envato Tuts+: Top 20 Most Usable Content Management Systems

* { box-sizing: border-box; } body {margin: 0;}*{box-sizing:border-box;}body{margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;}

There are plenty of options when picking a content management system for a development project. Depending on how advanced you need the CMS to be, what language it's built in, and who is going to be using it, it can be a nightmare trying to find the "perfect" CMS for a project.

However, some examples of CMSs (or content management systems) have a slight edge over the rest of the competition because of the usability of the software. Some are just easier to install, use, and extend, thanks to some thoughtful planning by the lead developers.

Looking for web content management system examples? We have a number of themes and resources to support these top content management systems. If you're looking for WordPress themes, Drupal themes, or Joomla themes, we have you covered on Envato Market.

We also support additional popular CMS systems, CMS tools and a variety of WordPress plugins, Drupal plugins, Joomla plugins, and more. Visit our ThemeForest or CodeCanyon marketplaces to browse through a ton of professional options.

Here are the most usable CMSs on the web, so you can choose the one that fits your needs best.

1. WordPress

Image removed.Image removed.Image removed.

What is left to say about WordPress that hasn't already been said? The PHP blogging platform is far and away the most popular CMS for blogging, and probably the most popular CMS overall. It's a great platform for beginners, thanks to its excellent documentation and super-quick installation wizard. Five minutes to a running CMS is pretty good. Not to mention the fact that the newest versions auto-update the core and plugins from within the back end, without having to download a single file.

For those users not familiar with HTML or other markup languages, a WYSIWYG editor is provided straight out of the box. The back-end layout is streamlined and intuitive, and a new user should be able to easily find their way around the administration section. WordPress also comes with built-in image and multimedia uploading support.

For developers, the theming language and the Plugin API are fairly simple and straightforward.

The WordPress Community is a faithful and zealous bunch. WordPress probably has the widest base of plugins and themes to choose from. We also have thousands of professional WordPress themes and WordPress plugins available for sale on Envato Market, with a full suite of styles and options to choose from.

A great thing about the WordPress community is the amount of help and documentation online you can find on nearly every aspect of customizing WordPress. If you can dream it, chances are it's already been done with WordPress and documented somewhere.

2. Drupal

Image removed.Image removed.Image removed.

Drupal is another CMS that has a very large, active community. Instead of focusing on blogging as a platform, Drupal is more of a pure CMS. A plain installation comes with a ton of optional modules that can add lots of interesting features like forums, user blogs, OpenID, profiles, and more. It's easy to create a site with social features with a simple install of Drupal, and it offers some useful third-party modules.

One of Drupal's most popular features is the Taxonomy module, a feature that allows for multiple levels and types of categories for content types. And you can find plenty of professional Drupal themes, which are ready to be customized and worked with. You can also grab Drupal plugins.

Drupal also has a very active community powering it, and has excellent support for plugins and other general questions.

3. Joomla!

Image removed.Image removed.Image removed.

Joomla is a very advanced CMS in terms of functionality. That said, getting started with Joomla is fairly easy, thanks to its installer. Joomla's installer is meant to work on common shared hosting packages and is very straightforward considering how configurable the software is.

Joomla is very similar to Drupal in that it's a complete CMS, and it might be a bit much for a simple portfolio site. It comes with an attractive administration interface, complete with intuitive drop-down menus and other features. The CMS also has great support for access control protocols like LDAP, OpenID, and even Gmail.

The Joomla site hosts more than 3,200 extensions, so you know the developer community behind the popular CMS is alive and kicking. Like WordPress, you can add just about any needed functionality with an extension. However, the Joomla theme and extension community relies more on paid resources, so if you're looking for customizations, be ready to pull out your wallet. You can also grab Joomla plugins.

4. Shopify

Image removed.Image removed.Image removed.

You can use the Shopify eCommerce software to create a great website design and add products with images, titles, and descriptions. You can also set up a full checkout functionality, where customers can pay for your products.

Shopify has a great free store theme that you can use to customize your website images, fonts, and colors to your satisfaction with no design skills required, and the themes are fully responsive. With Shopify, you manage your products, inventory, payments, and shipping, and you can also sell your products on the web, mobile, social media, and marketplaces.

One of the unique features of Shopify is that you can accept credit cards instantly, without third-party accounts.

When dealing with other CMS systems, you'll have to upgrade your tool to the current version to obtain new features, but Shopify is cloud-based and hosted, so you won't have to worry about software or web servers being upgraded or maintained. This allows you to access and manage your business from practically any location, even on your mobile device.

5. Wix

Image removed.Image removed.Image removed.

Wix is a cloud-based content management system with web hosting and design capabilities. Wix makes it simple for users to create websites without needing to pay web experts or have specialized knowledge. Wix sites are mobile-friendly and can be quickly constructed, maintained, and managed through the Wix website. It also allows you complete control over how you create, design, manage, and develop your online presence.

Wix's distinguishing feature is its drag-and-drop editor, which allows you to create a great website without knowing a single line of code. Wix is perfect for anything from online personal portfolios to small company websites, and it is completely scalable.

6. Magento

Image removed.Image removed.Image removed.

Magento is an open-source content management system that includes all of the essential eCommerce features and allows users to create a one-of-a-kind online store from the ground up. Magento Open Source is a free version that you may download and install on your web hosting account.

There are so many reasons Magento is ideal:

  • It is very easy to maintain and upgrade your site.
  • Payment is easy and secure.
  • It has a reliable and supportive community.
  • Magento is very flexible and offers free services for users.
  • You can easily integrate the Google Analytics service into your site, which will provide you with multiple reports.

7. Webflow

Image removed.Image removed.Image removed.

You have complete design freedom when using Webflow. It's a flexible content management system for building custom blogs, portfolios, and eCommerce stores. Webflow allows you to complete projects more quickly.

  • For web design, Webflow offers a drag-and-drop page builder.
  • It features a good, clean code quality that allows you to make changes on the page.

8. WooCommerce

Image removed.Image removed.Image removed.

WooCommerce is one of the best eCommerce platforms, and it's built on WordPress. It is a free tool for you to start up your eCommerce store. WooCommerce is flexible and easy to manage. However, it isn't quite a content management system (CMS). It is a WordPress plugin that runs on your site, so you'll have to integrate it into your WordPress site.

WooCommerce is by far the most popular eCommerce plugin for WordPress.

9. Ghost

Image removed.Image removed.Image removed.

Modern businesses want an eye-catching website that makes an impression on their target audience. Ghost helps you achieve that. It's a content management system (CMS) for blogging that comes in both self-hosted and hosted versions.

Ghost is used to power a wide range of websites, from individual bloggers just getting started to massive groups of editors and writers at some of the world's largest companies.

Ghost CMS is ideal for blogs that only require the publication and management of posts and pages. It can also effectively handle membership sites.

Benefits of Using Ghost

  • It has a lot of SEO (search engine optimization) help built-in. This can be delivered without the need for any plugins.
  • It features a variety of themes that are both responsive and attractive. They're simple and designed to keep you focused on your reading.
  • It is very easy to create your theme in Ghost CMS, and these themes use handlebars to insert data, which is very easy to learn.

10. BigCommerce

Image removed.Image removed.Image removed.

BigCommerce is the most flexible and open SaaS platform, and it is leading a new era of eCommerce platforms. It not only hosts your site, but also provides the CMS platform. It also takes care of your security and backups.

It is one of the most popular eCommerce platforms and offers a high level of scalability for online shops. It has more sales tools built in than any of its competitors, and it combines these features with smart SEO and fantastic multi-channel connectivity.

11. PrestaShop

Image removed.Image removed.Image removed.

PrestaShop is a powerful and innovative eCommerce platform that includes all of the tools you'll need to set up an online store and expand your business. And you can also install it on any web hosting platform that supports it.

Why you should use PrestaShop:

  • You can easily develop SEO-friendly URLs.
  • With PrestaShop CMS, you can fully customize your online store.
  • PrestaShop has different modules which provide security to your sites.
  • You can manage your products, orders, and statistics.

12. Blogger

Image removed.Image removed.Image removed.

Blogger is a CMS platform that’s specifically geared up for blogging. It’s a free service provided by Google. You can use it to create and publish a blog, and you can get a free domain or buy your domain name. The platform is beginner-friendly, and you can earn money from the platform by using Google AdSense.

13. HubSpot CMS

Image removed.Image removed.Image removed.

So many marketers and business owners use HubSpot CMS because it provides metrics on your current content marketing strategy and where improvements can be made, such as indicating the need for more internal links, calls to action, or landing pages. With HubSpot CMS, you can track relevant traffic, page performance, and significant impact, among other things.

Why HubSpot?

  • It aids businesses in attracting visitors.
  • For each visitor, you may quickly develop and personalize your website pages.
  • You can keep track of all of your stuff in one spot.
  • You can create a site that is unified without having to worry about inappropriate designs, logos, or navigation.

14. TYPO3 CMS

Image removed.Image removed.Image removed.

The TYPO3 CMS is an open-source content management system with a big global community, backed by the TYPO3 Association's approximately 900 members. It combines open-source code, dependability, and genuine scalability in a single package.

This professional CMS offers services and solutions for the whole team across industries, organization sizes, and use cases.

Typo3 is excellent because it is powerful and has a lot of potential to fill in the gaps left by many other products. Because of its flexibility, TYPO3 is ideal for quickly producing online content across a wide range of formats. It can also be used for assistance, marketing, and in-house projects.

15. ExpressionEngine

Image removed.Image removed.Image removed.

ExpressionEngine (EE) is an elegant, flexible CMS solution for any type of project. Designed to be extensible and easy to modify, EE sets itself apart in how clean and intuitive its user administration area is. It takes only a matter of minutes to understand the layout of the back end and to start creating content or modifying the look. It's fantastic for creating websites for less-than-savvy clients who need to use the back end without getting confused.

ExpressionEngine is packed with helpful features like the ability to have multiple sites with one installation of software. For designers, EE has a powerful templating engine that has custom global variables, custom SQL queries, and a built-in versioning system. Template caching, query caching, and tag caching keep the site running quickly too.

One of my favorite features of EE is the global search and replace functionality. Anyone who's ever managed a site or blog knows how useful it is to change lots of data without having to manually search and open each page or post to modify it.

16. Textpattern

Image removed.Image removed.Image removed.

Textpattern is a popular choice for designers because of its simple elegance. Textpattern isn't a CMS that throws in every feature it can think of. The code base is svelte and minimal. The main goal of Textpattern is to provide an excellent CMS that creates well-structured, standards-compliant pages. Instead of providing a WYSIWYG editor, Textpattern uses textile markup in the text areas to create HTML elements within the pages. The pages that are generated are extremely lightweight and fast-loading.

Even though Textpattern is deliberately simple in design, the back end is surprisingly intuitive and easy to use. New users should be able to find their way around the administration section easily.

While Textpattern may be very minimal at the core level, you can always extend the functionality by using third-party extensions, mods, or plugins. Textpattern has an active developer community, with lots of help and resources at the Textpattern.org site.

17. Radiant CMS

Image removed.Image removed.Image removed.

The content management systems that we've listed so far are all PHP programs. PHP is the most popular language for web development, but that doesn't mean we should overlook other popular web languages like Ruby.

Radiant CMS is a fast, minimal CMS that might be compared to Textpattern. Radiant is built on the popular Ruby framework Rails, and the developers behind Radiant have done their best to make the software as simple and elegant as possible, with just the right amount of functionality. Like Textpattern, Radiant doesn't come with a WYSIWYG editor and relies on Textile markup to create rich HTML. To make it easier to create templates intuitively, Radiant also has its own templating language, Radius, which is very similar to HTML.

18. Cushy CMS

Image removed.Image removed.Image removed.

Cushy CMS is a different type of CMS altogether. Sure, it has all the basic functionality of a regular content management system, but it doesn't rely on a specific language. In fact, the CMS is a hosted solution. There are no downloads or future upgrades to worry about.

Cushy works by taking FTP info and uploading content to the server. The developer or the designer can then modify the layout, as well as the posting fields in the back end, just by changing the classes of the styles. Very, very simple.

Cushy CMS is free for anyone, even for professional use. There is an option to upgrade to a pro account to use your own logo and color scheme, as well as other fine-grain customizations in the way Cushy CMS functions.

19. SilverStripe

Image removed.Image removed.Image removed.

SilverStripe is another PHP CMS that behaves much like WordPress, except that it has many more configurable options and is tailored towards content management, not blogging. SilverStripe is unique because it was built upon its very own PHP framework, Saphire. It also provides its own templating language to help with the design process.

SilverStripe has some interesting features built into the base, like content version control and native SEO support. What's really unique with SilverStripe is that developers and designers can customize the administration area for their clients, if need be. While the development community isn't as large as other projects, there are some modules, themes, and widgets to add functionality. Also, you'll want to modify the theme for each site, as SilverStripe doesn't provide much in terms of style, to give the designer more freedom.

20. Contao

Image removed.Image removed.Image removed.

Contao seems to have the perfect balance of features built into the CMS. In terms of functionality, Contao ranks with Drupal and ExpressionEngine, and it even offers some unique bundled modules like newsletters and calendars. Developers can save time with the built-in CSS generator, and there are plenty of resources for learning more about the CMS.

If there is a downside to Contao, it's that it has so many features and configurable options. Even though the back end is thoughtfully organized, there are still a lot of options to consider. But if you want to build a site with advanced functionality and little extra programming, Contao could be a great fit.

Learn More

Now you've got enough CMS examples, types of CMSs, different CMS systems and CMS tools to get you started. If you want to expand your knowledge on content management system list or explore more examples of CMS, check out some related tutorials: 

Editorial Note: This post has been updated with contributions from Janila Castañeda. Janila is a staff writer with Envato Tuts+.

Envato Tuts+: New Course: Code a Custom Drupal Module

Image removed.Image removed.Image removed.What You'll Be Creating

If you want an easy way to create engaging, content-driven websites for you and your customers, you should give Drupal 8 a try. And Drupal modules allow you to take things a step further and create highly customized functionality for your site. 

In our new course, Code a Custom Drupal Module, Envato Tuts+ instructor Derek Jensen will get you up and running with modules in no time. You'll build a simple calculator module, and along the way you'll learn about creating routes, controllers, parameters, and more.

You can take our new course straight away with a subscription to Envato Elements. For a single low monthly fee, you get access not only to this course, but also to our growing library of over 1,000 video courses and industry-leading eBooks on Envato Tuts+. 

Plus you now get unlimited downloads from the huge Envato Elements library of 200,000+ photos and 26,000+ design assets and templates. Create with unique fonts, photos, graphics and templates, and deliver better projects faster.

Image removed.

Looking for a shortcut? Try downloading some of the ready-made Drupal themes on Envato Market.

Envato Tuts+: New Code eBooks Available for Subscribers

Do you want to learn more about asynchronous Android programming? How about the Ionic framework, or JavaScript design patterns? Our latest batch of eBooks will teach you all you need to know about these topics and more.

Image removed.Image removed.Image removed.

Our Latest Selection of eBooks

This month we’ve made eight new eBooks available for Envato Tuts+ subscribers to download. Here’s a summary of those books and what you can learn from them.

  • Image removed.Image removed.Image removed.

    Xamarin: Cross-Platform Mobile Application Development

    Developing a mobile application for just one platform is becoming a thing of the past. Companies expect their apps to be supported on iOS, Android and Windows Phone, while leveraging the best native features on all three platforms. Xamarin's tools help ease this problem by giving developers a single toolset to target all three platforms. The main goal of this book is to equip you with knowledge to successfully analyze, develop, and manage Xamarin cross-platform projects using the most efficient, robust, and scalable implementation patterns.

  • Image removed.Image removed.Image removed.

    Drupal 8 Theming With Twig

    Drupal 8 is an open-source content management system and powerful framework that helps deliver great websites to individuals and organizations, including non-profits, commercial, and government around the globe. Starting from the bottom up, in this eBook you will learn to install, set up, and configure Drupal 8. You'll get a walk-through of a real-world project to create a Twig theme from concept to completion while adopting best practices to implement CSS frameworks and JavaScript libraries. You will see just how quick and easy it is to create beautiful, responsive Drupal 8 websites while avoiding the common mistakes that many front-end developers make.

  • Image removed.Image removed.Image removed.

    Asynchronous Android Programming: Second Edition

    Asynchronous programming has acquired immense importance in Android programming, especially when we want to make use of the number of independent processing units (cores) available on the most recent Android devices. With this guide in your hands, you’ll be able to bring the power of asynchronous programming to your own projects, and make your Android apps more powerful than ever before!

  • Image removed.Image removed.Image removed.

    Ionic Framework by Example

    With Ionic, mobile development has never been so simple, so elegant and obvious. By helping developers to harness AngularJS and HTML5 for mobile development, it’s the perfect framework for anyone obsessed with performance, and anyone that understands just how important a great user experience really is. This book shows you how to get started with Ionic framework immediately. But it doesn’t just give you instructions and then expect you to follow them. Instead it demonstrates what Ionic is capable of through three practical projects you can follow and build yourself.

  • Image removed.Image removed.Image removed.

    Sass and Compass Designer's Cookbook

    Sass and Compass Designer's Cookbook helps you to get most out of CSS3 and harness its benefits to create engaging and receptive applications. This book will help you develop faster and reduce the maintenance time for your web development projects by using Sass and Compass. You will learn how to use with CSS frameworks such as Bootstrap and Foundation and understand how to use other libraries of pre-built mixins. You will also learn setting up a development environment with Gulp.

  • Image removed.Image removed.Image removed.

    Android Sensor Programming by Example

    Android phones available in today’s market have a wide variety of powerful and highly precise sensors. This book will give you the skills required to use sensors in your Android applications. It will walk you through all the fundamentals of sensors and will provide a thorough understanding of the Android Sensor Framework. By the end of the book, you will be well versed in the use of Android sensors and programming to build interactive applications.

  • Image removed.Image removed.Image removed.

    Mastering Yii

    The successor of Yii Framework 1.1, Yii2 is a complete rewrite of Yii Framework, one of the most popular PHP 5 frameworks for making modern web applications. This book has been written to enhance your skills and knowledge with Yii Framework 2. Starting with configuration and how to initialize new projects, you’ll learn how to configure, manage, and use every aspect of Yii2 from Gii, DAO, Query Builder, Active Record, and migrations, to asset manager. With this book by your side, you’ll have all the skills you need to quickly create rich modern web and console applications with Yii2.

  • Image removed.Image removed.Image removed.

    Mastering JavaScript Design Patterns: Second Edition

    In this book, you will explore how design patterns can help you improve and organize your JavaScript code. You’ll get to grips with creational, structural and behavioral patterns as you discover how to put them to work in different scenarios. Then, you'll get a deeper look at patterns used in functional programming, as well as model view patterns and patterns to build web applications. By the end of the book, you'll be saved of a lot of trial and error and developmental headaches, and you will be on the road to becoming a JavaScript expert.

Start Learning With a Yearly Subscription

Subscribe to Envato Tuts+ for access to our library of hundreds of eBooks. With a Yearly subscription, you can download up to five eBooks per month, while the Yearly Pro subscription gives you unlimited access.

You can also build on your newfound knowledge by using some of the fantastic code scripts and plugins on Envato Market.

Envato Tuts+: Drupal 8: Properly Injecting Dependencies Using DI

As I am sure you know by now, dependency injection (DI) and the Symfony service container are important new development features of Drupal 8. However, even though they are starting to be better understood in the Drupal development community, there is still some lack of clarity about how exactly to inject services into Drupal 8 classes.

Many examples talk about services, but most cover only the static way of loading them:

1 $service = \Drupal::service('service_name');

This is understandable as the proper injection approach is more verbose, and if you know it already, rather boilerplate. However, the static approach in real life should only be used in two cases:

  • in the .module file (outside of a class context)
  • those rare occasions within a class context where the class is being loaded without service container awareness

Other than that, injecting services is the best practice as it ensures decoupled code and eases testing.

In Drupal 8 there are some specificities about dependency injection that you will not be able to understand solely from a pure Symfony approach. So in this article we are going to look at some examples of proper constructor injection in Drupal 8. To this end, but also to cover all the basics, we will look at three types of examples, in order of complexity:

  • injecting services into another of your own services
  • injecting services into non-service classes
  • injecting services into plugin classes

Going forward, the assumption is that you know already what DI is, what purpose it serves and how the service container supports it. If not, I recommend checking out this article first.

Services

Injecting services into your own service is very easy. Since you are the one defining the service, all you have to do is pass it as an argument to the service you want to inject. Imagine the following service definitions:

1 services: 2 demo.demo_service: 3 class: Drupal\demo\DemoService 4 demo.another_demo_service: 5 class: Drupal\demo\AnotherDemoService 6 arguments: ['@demo.demo_service']

Here we define two services where the second one takes the first one as a constructor argument. So all we have to do now in the AnotherDemoService class is store it as a local variable:

1 class AnotherDemoService { 2 /** 3 * @var \Drupal\demo\DemoService 4 */ 5 private $demoService; 6 7 public function __construct(DemoService $demoService) { 8 $this->demoService = $demoService; 9 } 10 11 // The rest of your methods 12 }

And that is pretty much it. It's also important to mention that this approach is exactly the same as in Symfony, so no change here.

Non-Service Classes

Now let's take a look at classes that we often interact with but that are not our own services. To understand how this injection takes place, you need to understand how the classes are resolved and how they are instantiated. But we will see that in practice soon.

Controllers

Controller classes are mostly used for mapping routing paths to business logic. They are supposed to stay thin and delegate heavier business logic to services. Many extend the ControllerBase class and get some helper methods to retrieve common services from the container. However, these are returned statically.

When a controller object is being created (ControllerResolver::createController), the ClassResolver is used to get an instance of the controller class definition. The resolver is container aware and returns an instance of the controller if the container already has it. Conversely, it instantiates a new one and returns that. 

And here is where our injection takes place: if the class being resolved implements the ContainerAwareInterface, the instantiation takes place by using the static create() method on that class which receives the entire container. And our ControllerBase class also implements the ContainerAwareInterface.

So let's take a look at an example controller which properly injects services using this approach (instead of requesting them statically):

1 /** 2 * Defines a controller to list blocks. 3 */ 4 class BlockListController extends EntityListController { 5 6 /** 7 * The theme handler. 8 * 9 * @var \Drupal\Core\Extension\ThemeHandlerInterface 10 */ 11 protected $themeHandler; 12 13 /** 14 * Constructs the BlockListController. 15 * 16 * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler 17 * The theme handler. 18 */ 19 public function __construct(ThemeHandlerInterface $theme_handler) { 20 $this->themeHandler = $theme_handler; 21 } 22 23 /** 24 * {@inheritdoc} 25 */ 26 public static function create(ContainerInterface $container) { 27 return new static( 28 $container->get('theme_handler') 29 ); 30 } 31 }

The EntityListController class doesn't do anything for our purposes here, so just imagine that BlockListController directly extends the ControllerBase class, which in turn implements the ContainerInjectionInterface.

As we said, when this controller is instantiated, the static create() method is called. Its purpose is to instantiate this class and pass whatever parameters it wants to the class constructor. And since the container is passed to create(), it can choose which services to request and pass along to the constructor. 

Then, the constructor simply has to receive the services and store them locally. Do keep in mind that it's bad practice to inject the entire container into your class, and you should always limit the services you inject to the ones you need. And if you need too many, you are likely doing something wrong.

We used this controller example to go a bit deeper into the Drupal dependency injection approach and understand how constructor injection works. There are also setter injection possibilities by making classes container aware, but we won't cover that here. Let's instead look at other examples of classes you may interact with and in which you should inject services.

Forms

Forms are another great example of classes where you need to inject services. Usually you either extend the FormBase or ConfigFormBase classes which already implement the ContainerInjectionInterface. In this case, if you override the create() and constructor methods, you can inject whatever you want. If you don't want to extend these classes, all you have to do is implement this interface yourself and follow the same steps we saw above with the controller.

As an example, let's take a look at the SiteInformationForm which extends the ConfigFormBase and see how it injects services on top of the config.factory its parent needs:

1 class SiteInformationForm extends ConfigFormBase { 2 3 ... 4 public function __construct(ConfigFactoryInterface $config_factory, AliasManagerInterface $alias_manager, PathValidatorInterface $path_validator, RequestContext $request_context) { 5 parent::__construct($config_factory); 6 7 $this->aliasManager = $alias_manager; 8 $this->pathValidator = $path_validator; 9 $this->requestContext = $request_context; 10 } 11 12 /** 13 * {@inheritdoc} 14 */ 15 public static function create(ContainerInterface $container) { 16 return new static( 17 $container->get('config.factory'), 18 $container->get('path.alias_manager'), 19 $container->get('path.validator'), 20 $container->get('router.request_context') 21 ); 22 } 23 24 ... 25 }

As before, the create() method is used for the instantiation, which passes to the constructor the service required by the parent class as well as some extra ones it needs on top.

And this is pretty much how the basic constructor injection works in Drupal 8. It's available in almost all class contexts, save for a few in which the instantiation part was not yet solved in this manner (e.g. FieldType plugins). Additionally, there is an important subsystem which has some differences but is crucially important to understand: plugins.

Plugins

The plugin system is a very important Drupal 8 component that powers a lot of functionality. So let's see how dependency injection works with plugin classes.

The most important difference in how injection is handled with plugins is the interface plugin classes need to implement: ContainerFactoryPluginInterface. The reason is that plugins are not resolved but are managed by a plugin manager. So when this manager needs to instantiate one of its plugins, it will do so using a factory. And usually, this factory is the ContainerFactory (or a similar variation of it). 

So if we look at ContainerFactory::createInstance(), we see that aside from the container being passed to the usual create() method, the $configuration, $plugin_id, and $plugin_definition variables are passed as well (which are the three basic parameters each plugin comes with).

So let's see two examples of such plugins that inject services. First, the core UserLoginBlock plugin (@Block):

1 class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface { 2 3 ... 4 5 public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match) { 6 parent::__construct($configuration, $plugin_id, $plugin_definition); 7 8 $this->routeMatch = $route_match; 9 } 10 11 /** 12 * {@inheritdoc} 13 */ 14 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { 15 return new static( 16 $configuration, 17 $plugin_id, 18 $plugin_definition, 19 $container->get('current_route_match') 20 ); 21 } 22 23 ... 24 }

As you can see, it implements the ContainerFactoryPluginInterface and the create() method receives those three extra parameters. These are then passed in the right order to the class constructor, and from the container a service is requested and passed as well. This is the most basic, yet commonly used, example of injecting services into plugin classes.

Another interesting example is the FileWidget plugin (@FieldWidget):

1 class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface { 2 3 /** 4 * {@inheritdoc} 5 */ 6 public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ElementInfoManagerInterface $element_info) { 7 parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); 8 $this->elementInfo = $element_info; 9 } 10 11 /** 12 * {@inheritdoc} 13 */ 14 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { 15 return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('element_info')); 16 } 17 ... 18 }

As you can see, the create() method receives the same parameters, but the class constructor expects extra ones that are specific to this plugin type. This is not a problem. They can usually be found inside the $configuration array of that particular plugin and passed from there.

So these are the main differences when it comes to injecting services into plugin classes. There's a different interface to implement and some extra parameters in the create() method.

Conclusion

As we've seen in this article, there are a number of ways we can get our hands on services in Drupal 8. Sometimes we have to statically request them. However, most of the time we shouldn't. And we've seen some typical examples of when and how we should inject them into our classes instead. We've also seen the two main interfaces the classes need to implement in order to be instantiated with the container and be ready for injection, as well as the difference between them.

If you are working in a class context and you are unsure of how to inject services, start looking at other classes of that type. If they are plugins, check if any of the parents implement the ContainerFactoryPluginInterface. If not, do it yourself for your class and make sure the constructor receives what it expects. Also check out the plugin manager class responsible and see what factory it uses. 

In other cases, such as with TypedData classes like the FieldType, take a look at other examples in core. If you see others using statically loaded services, it's most likely not yet ready for injection so you'll have to do the same. But keep an eye out, because this might change in the future.

Envato Tuts+: What Is Drupal?

Drupal is a popular open-source content management system written in PHP. Having been created in the early 2000s by a Belgian student, it now powers some of the most prominent websites on the web (WhiteHouse.gov, Weather.com, etc.). It is often regarded as a competitor of CMSs such as WordPress and Joomla.

One of the most important components of the Drupal project is its community of supporters (contributors, developers, evangelists, business owners, etc.). Prominent within this community stands the Drupal Association, responsible for "fostering and supporting the Drupal software project, the community and its growth".

A giant leap from its predecessor, the 8th major release of the Drupal project has just hit the shelves. It brought about a serious modernisation of its code, practices and mentality. Many regard this shift as a real move away from the traditional notion of a CMS to more of a Content Management Framework (CMF) that provides a great platform for building complex applications.

In this article, I'm going to answer some of the more frequent questions people have about Drupal when starting up for the first time or considering doing so:

  • Is it right for me? Who is it aimed at?
  • How can it be installed, and where can I host it?
  • How can I start working with it as a developer?
  • What options do I have for extending functionality or styling it?

Who Is Drupal Aimed At?

Since the beginning of the project, Drupal has evolved from being mainly a tool for building smaller sites to one that can now power enterprise-level platforms. Especially with Drupal 8, site builders and developers can easily scale up from small websites to large platforms with many integrations. For example, the adoption of Composer allows you not only to bring external libraries into a Drupal project, but also to use Drupal as part of a bigger project of applications and libraries. It's safe to say that Drupal is flexible enough to meet the needs of a wide range of projects.

When it comes to development, Drupal has always had a relatively closed community—not because people are unfriendly, quite the contrary, but mainly because of the code typically being written in a Drupal way (resulting in what sometimes is referred to as Drupalisms). This has meant a learning curve for any developer starting up, but also less interest from developers of other PHP projects to jump in and contribute.

This is no longer the case. Especially with the release of Drupal 8, the community now promotes a new mentality of code reusability and best practice across different open-source projects. Active participation in the PHP Framework Interoperability Group is part of this effort, and using a number of popular Symfony components in Drupal 8 core is a testament to this commitment. 

With this move, the Drupal community has gotten richer by welcoming many developers from other communities and projects, and it is sure to grow even further. So if you are a Laravel developer, looking at Drupal code will no longer be so daunting.

How Can I Install Drupal, and Where Can I Host It?

Traditionally, Drupal has had a relatively easy installation process, particularly for people who at least knew their way around a Linux environment. The project simply needs to be dropped into a folder your web server can run (which needs to be using PHP and have a MySQL or MariaDB database). Then pointing your browser to the /install.php file and following the steps takes care of the rest. The most important screen you'll see is the one in which you select a specific database to use.

In terms of requirements, the LAMP stack (Linux, Apache, MySQL and PHP) environment has always been a favourite for Drupal to run in. However, it is in no way restricted to it. Solutions exist for installing it straight on Windows or Mac (e.g. using the Acquia Dev Desktop) but also on a Linux system that runs other web servers.

The easiest approach, if you go with your own setup, is to use a LAMP server for hosting. For a bit more performance you can replace Apache with Nginx, but you'll then have to take care of some specific configuration that otherwise is handled in the .htaccess file Drupal ships with.

However, if you don't want the hassle of maintaining your own hosting server, there are three main providers of specialised Drupal managed hosting: Acquia, Pantheon, and Platform.sh. These also provide a workflow for easy updates and development flow. Past that, you are looking at fully managed hosting with a Drupal development company.

How Can I Get Started Developing for It?

Developing Drupal websites has typically been the kind of thing you either liked a lot or didn't like at all. This is because when you were first introduced to Drupal, you encountered very many specificities that you didn't see in other projects. So if those tickled your fancy, you loved it forever.

With getting off this island in Drupal 8, this is no longer the case as much. You still have plenty of Drupalisms left that you can love or hate, but you now also have external components like Symfony or Guzzle and, most importantly, a more modern way of writing code in general (OOP, design patterns, reusable components, etc.). So your PHP skills from building websites with Zend will come in handy.

A good way of getting into Drupal development is to follow some online video courses. There are a couple of resources that are excellent for this purpose, most notably Drupalize.me. If, however, video is not your favourite medium, there are also many written tutorials and guides available to get you started. Check out the following links for some of the first steps you can take:

Since Drupal 8 is brand new, you'll find significantly more learning content for Drupal 7. Nevertheless, the focus in the community has been shifting recently towards Drupal 8, so you can expect more and more of these resources to crop up. And if you have no experience with any version of Drupal, it's best to focus exclusively on Drupal 8 as the changes between the two are big and perhaps you'd be facing unnecessary challenges.

How Can I Extend Drupal?

The main extension point of a core Drupal installation is its module system. 

Modules are used to encapsulate bigger chunks of reusable functionality that can/should work on different sites. Aside from the core modules, there are a large number of contributed ones, available for installation. 

Granted, most are still only for Drupal 6 and 7, but the community is catching up also for the newest version. This problem is also mitigated by the incorporation in Drupal 8 of a few popular contributed modules as well as extending the scope of what core can do out of the box (compared to Drupal 7). 

Lastly, custom modules (the ones that you write yourself) are the primary way you can add any functionality that you want and that is not available via a contributed module.

Installing modules can allow you to plug in various pieces of functionality, but you should not treat this as a green light for adding too many. It's always better to stick to the ones you actually need, and don't be afraid to be critical in this respect. You can also work on finding a good balance between contributed code and the custom one you write yourself. 

Additionally, since we are talking about open-source software, you should always evaluate the modules you install. The following indicators are good examples to pay attention to: number of downloads and usage, commit frequency, maintainer engagement, state of the issue queue.

And do keep security in mind as well. It's highly recommended you keep both Drupal core and any contributed modules up to date as this will significantly help you keep your site and server secure (though it doesn't ensure it).

What About Styling?

The styling layer of a Drupal site is handled (in large part) by its theme. Themes are similar to modules in that they are an extension point, but they have different responsibilities. They contain the styles, front-end libraries and in most cases template files that are used to output data.

There has been great progress in Drupal 8 compared to the previous version: the popular Twig engine has been adopted for templating, theming has been limited to Twig template files, debugging and overriding templates has been made much easier, etc. Similar to the advances in back-end development experience (DX), the theming layer has been made more appealing to the non-Drupal crowd. Front-end developers can now easily work with Drupal themes without having to understand the ins and outs of the back end.

Drupal core comes with a number of themes that can provide you with examples but also which you can extend from. There are also contributed themes similar to how there are modules. Popular front-end frameworks such as Bootstrap or Zurb Foundation have mature Drupal theme implementations for Drupal 7, which are also readying for Drupal 8. These work very well as base themes but also for quickly scaffolding a website and making it look decent.

Paid themes are also available to try out. Usually they are very cheap and quick to set up. The problem with them is that they are worth exactly as much as you pay for them and usually have gaping holes in their flexibility. As a beginner, these themes can seem like a great way to set up a site, and they very well may be. However, as you progress, you'll learn to avoid them and build your own, based on external designs or even plain HTML/CSS/JS templates.

Conclusion

Drupal is a powerful tool for building websites and platforms of any kind. With each new major release, Drupal has shown a commitment to better itself, become more robust and flexible, and embrace outside communities as well.

Envato Tuts+: Using and Extending the Drupal 8 Mail API: Part 2

In the previous article we looked at how we can send emails programatically in Drupal 8. We also saw how other modules can alter these outgoing mails. Today, we are going to look at how we can use the Mail API to extend this default behaviour. The purpose is to use an external service as a means for email delivery. 

For this, we will use Mandrill, although the focus of the article will not be its API or how to work with it, but rather the Drupal side of things. And remember, the working module can be found in this Git repository.

As we've seen in the previous article, sending an email in Drupal 8 happens by requesting the mail manager, passing some parameters to its mail() method, and setting up a template inside a hook_mail() implementation. What the mail manager does internally is load up the appropriate mail plugin, construct the email, and then delegate to the mail() method of whatever plugin was loaded.

But who does it actually delegate to?

Plugin Selection

An important thing to understand before writing our own plugin is the selection process of the mail manager for loading plugins. In other words, how do we know which plugin it will load, and how can we make it load our own?

The system.mail.interface configuration array holds all the answers. It contains the ids of the available plugins, keyed by the context they are used in. By default, all we have inside this configuration is default => phpmail. This means that the plugin with the id phpmail (the PHPMail class) is used as fallback for all contexts that are not otherwise specified, i.e. the default.

If we want to write our own plugin, we need to add another element into that array with the plugin id as its value. The key for this value can be one of two things: the machine name of our module (to load the plugin whenever our module sends emails) or a combination of module name and email template key (to load the plugin whenever our module sends an email using that specific key). 

An example of the latter construct is d8mail_node_insert, where d8mail is our module name we started building in the previous article, and node_insert is the email template key we defined.

So now that we know how the mail plugin selection happens, we need to make sure this config array contains the necessary information so that emails sent with our d8mail module use the new plugin we will build. We can do this inside a hook_install() implementation that gets triggered only once when the module gets installed:

d8mail.install:

1 /** 2 * Implements hook_install(). 3 */ 4 function d8mail_install() { 5 $config = \Drupal::configFactory()->getEditable('system.mail'); 6 $mail_plugins = $config->get('interface'); 7 if (in_array('d8mail', array_keys($mail_plugins))) { 8 return; 9 } 10 11 $mail_plugins['d8mail'] = 'mandrill_mail'; 12 $config->set('interface', $mail_plugins)->save(); 13 }

Not super complicated what happens above. We load the editable config object representing the system.mail configuration, and add a new element to the interface array: d8mail => mandrill_mail. We will soon create a mail plugin with the id of mandrill_mail which will be used for all emails sent by the d8mail module. And that's it.

But before we move on, we need to make sure this change is reverted when the module is uninstalled. For this, we can use the counterpart hook_uninstall() that gets called when a module gets uninstalled (there is no more module disabling in Drupal 8).

Inside the same file:

1 /** 2 * Implements hook_uninstall(). 3 */ 4 function d8mail_uninstall() { 5 $config = \Drupal::configFactory()->getEditable('system.mail'); 6 $mail_plugins = $config->get('interface'); 7 if ( ! in_array('d8mail', array_keys($mail_plugins))) { 8 return; 9 } 10 11 unset($mail_plugins['d8mail']); 12 $config->set('interface', $mail_plugins)->save(); 13 }

With the hook_uninstall() implementation we do the opposite of before: we remove our plugin id if it is set.

The install/uninstall scenario is just one way to go. You can also create an administration form that allows users to select the plugin they want and under which context. But you still need to make sure that when you disable the module defining a particular plugin, the configuration will no longer keep a reference to that plugin. Otherwise the mail manager may try to use a non-existent class and throw all kinds of errors.

Mandrill

As I mentioned before, we will work with the Mandrill API in order to illustrate our task. So let's load up Mandrill's PHP Library and make it available in our environment. There are three steps we need to do for this.

First, we need to actually get the library inside Drupal. At the time of writing, this basically means adding the "mandrill/mandrill": "1.0.*" dependency to the root composer.json file and running composer install. Keep in mind, though, that this will also clear the Drupal installation from inside the core/ folder and download the latest stable release instead. Then, you'll need to edit the root index.php file and change the path to the autoloader as per these instructions. Hopefully this last action won't be necessary soon, and I encourage you to follow the discussions around the future of Composer in Drupal 8 for managing external libraries.

Second, we need to get an API key from Mandrill. Luckily, this we can easily generate from their administration pages. Once we have that, we can store it inside a new file created on our server, at either location:

1 ~/.mandrill.key 2 /etc/mandrill.key

We can also pass the key as a constructor parameter to the main Mandrill class, but this way we won't have to hardcode it in our code. 

Thirdly, we need to create a service so that we can use dependency injection for passing the Mandrill class into our plugin:

d8mail.services.yml:

1 services: 2 d8mail.mandrill: 3 class: Mandrill

Depending on how you have loaded the Mandrill class into your application, you'll need to change the value after class. By using the composer.json approach, this will suffice.

The Mail Plugin

It's finally time to create our plugin. In Drupal 8, plugin classes go inside the src/Plugin folder of our module. Depending on their type, however, they are placed further down within other directories (in our case Mail). Let's write our class that will depend on the Mandrill API library to send emails:

src/Plugin/Mail/MandrillMail.php:

1 <?php 2 3 namespace Drupal\d8mail\Plugin\Mail; 4 5 use Drupal\Core\Mail\MailFormatHelper; 6 use Drupal\Core\Mail\MailInterface; 7 use Drupal\Core\Plugin\ContainerFactoryPluginInterface; 8 use Symfony\Component\DependencyInjection\ContainerInterface; 9 use Mandrill; 10 use Mandrill_Error; 11 12 /** 13 * Defines the Mandrill mail backend. 14 * 15 * @Mail( 16 * id = "mandrill_mail", 17 * label = @Translation("Mandrill mailer"), 18 * description = @Translation("Sends an email using Mandrill.") 19 * ) 20 */ 21 class MandrillMail implements MailInterface, ContainerFactoryPluginInterface { 22 23 /** 24 * @var Mandrill 25 */ 26 private $mandrill; 27 28 /** 29 * @param Mandrill $mandrill 30 */ 31 public function __construct(Mandrill $mandrill) { 32 $this->mandrill = $mandrill; 33 } 34 35 /** 36 * {@inheritdoc} 37 */ 38 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { 39 return new static( 40 $container->get('d8mail.mandrill') 41 ); 42 } 43 44 /** 45 * {@inheritdoc} 46 */ 47 public function format(array $message) { 48 // Join the body array into one string. 49 $message['body'] = implode("\n\n", $message['body']); 50 // Convert any HTML to plain-text. 51 $message['body'] = MailFormatHelper::htmlToText($message['body']); 52 // Wrap the mail body for sending. 53 $message['body'] = MailFormatHelper::wrapMail($message['body']); 54 55 return $message; 56 } 57 58 /** 59 * {@inheritdoc} 60 */ 61 public function mail(array $message) { 62 63 try { 64 $vars = [ 65 'html' => $message['body'], 66 'subject' => $message['subject'], 67 'from_email' => $message['from'], 68 'to' => array( 69 array('email' => $message['to']) 70 ), 71 ]; 72 73 $result = $this->mandrill->messages->send($vars); 74 if ($result[0]['status'] !== 'sent') { 75 return false; 76 } 77 78 return $result; 79 } 80 catch (Mandrill_Error $e) { 81 return false; 82 } 83 } 84 }

There are a couple of things to note before getting into what the class does.

First, the annotations above the class. This is just the most common plugin discovery mechanism for Drupal 8. The id key matches the value we added to the system.mail.interface configuration array earlier, while the rest are basic plugin definition elements.

Second, the implementation of the ContainerFactoryPluginInterface interface by which we define the create() method. The latter is part of the dependency injection process by which we can load up the Mandrill service we defined in the services.yml file earlier. This makes testing much easier and it's considered best practice.

As I mentioned, the mail plugins need to implement the MailInterface interface which enforces the existence of the format() and mail() methods. In our case, the first does exactly the same thing as the PHPMail plugin: a bit of processing of the message body. So you can add your own logic here if you want. The latter method, on the other hand, is responsible for sending the mail out, in our case, using the Mandrill API itself.

As the Mandrill documentation instructs, we construct an email message inside the $vars array using values passed from the mail manager through the $message parameter. These will be already filtered through hook_mail(), hook_mail_alter() and the plugin's own format() method. All that's left is to actually send the email. I won't go into the details of using the Mandrill API as you can consult the documentation for all the options you can use.

After sending the email and getting back from Mandrill a sent status, we return the entire response array, which contains some more information. This array then gets added by the mail manager to its own return array keyed as result. If Mandrill has a problem, rejects the email or throws an exception, we return false. This will make the mail manager handle this situation by logging the incident and printing a status message.

And that is pretty much it. We can clear the cache and try creating another article node. This time, the notification email should be sent by Mandrill instead of PHP's mail(). With this in place, though, the hook_mail_alter() implementation has become superfluous as there are no headers we are actually sending through to Mandrill (and the text is HTML already). And for that matter quite a lot of the work of the mail manager is not used, as we are not passing that on to Mandrill. But this is just meant to illustrate the process of how you can go about setting this up. The details of the implementation remain up to you and your needs.

Conclusion

And there we have it. We have implemented our own mail plugin to be used by the d8module we started in the previous article. And due to the extensible nature of Drupal 8, it didn't even take too much effort. 

What's left for you to do is to perfect the mail sending logic and adapt it to your circumstances. This can mean further integration between Mandrill and your Drupal instance, constructing nice templates or what have you. Additionally, an important remaining task is writing automated tests for this functionality. And Drupal 8 offers quite the toolkit for that as well.