What is the difference between __contstruct() and create()?

In Drupal, both the __construct() and create() methods play key roles in the instantiation of objects, particularly when services are injected via Dependency Injection. However, they serve different purposes and are used in different ways.

Key Differences Between __construct() and create():

1. Purpose:

  • __construct():
    • The constructor method (__construct()) is responsible for initializing the object once it's created. It sets up the object’s internal state, including assigning dependencies (services or other objects) passed into it.
    • It is a core part of object-oriented programming (OOP) and is called when the object is instantiated.
  • create():
    • The create() method is a factory method. It is used to instantiate the object and inject the required services from the service container.
    • In Drupal, the create() method is used when the object needs to be instantiated by the service container with dependencies, usually when using the ContainerFactoryPluginInterface. The service container calls create() to pass the required services into the constructor.

2. When They're Called:

  • __construct():
    • Called automatically when the object is instantiated via new or create(). For example:
$block = new MyCustomBlock($configuration, $plugin_id, $plugin_definition, $my_custom_service);
  • create():
    • create() is manually called by the service container when it needs to instantiate the object and provide necessary services.
    • For example, when a plugin is instantiated by Drupal's service container:
$block = MyCustomBlock::create($container, $configuration, $plugin_id, $plugin_definition);

3. Role in Dependency Injection:

  • __construct():
    • Receives and sets dependencies that are required by the class.
    • The constructor defines what dependencies (usually services) are needed by the object, and these are passed into the class through the constructor parameters.
  • create():
    • Retrieves services from the container and passes them into the constructor. It acts as a factory method to create the object.
    • In the context of Drupal, the create() method extracts the required services from the service container (using $container->get()) and passes them into the constructor.

4. Example:

Here’s how they work together in a typical scenario:

  • __construct(): Sets up the class by receiving dependencies.
  • create(): Retrieves the dependencies from the service container and instantiates the class by calling __construct().
namespace Drupal\my_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;

/**
 * Provides a custom block.
 *
 * @Block(
 *   id = "my_custom_block",
 *   admin_label = @Translation("My Custom Block")
 * )
 */
class MyCustomBlock extends BlockBase implements ContainerFactoryPluginInterface {

  protected $entityTypeManager;

  /**
   * The constructor method that initializes the object with dependencies.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * The create() method is called by the service container to instantiate the object.
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    // Extracts the service from the container and passes it to the constructor.
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')
    );
  }

  public function build() {
    // Example of using the injected service.
    return [
      '#markup' => $this->t('This block uses dependency injection.'),
    ];
  }

}

Summary:

  • __construct(): The constructor is responsible for initializing the object and setting its internal state, including setting dependencies passed in as arguments. It is part of basic object instantiation.
  • create(): The factory method create() is responsible for retrieving services from the service container and passing them into the constructor to create the object. It’s used when the class is instantiated by Drupal's service container, allowing for proper service injection.

In Drupal, create() is used when you need to inject services, while __construct() is where the actual object is initialized with those services.