I'm building a custom form (extending ConfigFormBase) and using static method File::load($fid). How to use dependency injection to call this method? Thank you!

up vote 2 down vote accepted

In __construct() you can implement like this:

use Drupal\Core\Entity\EntityTypeManagerInterface;

public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
}

and create() method

public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
    );
}

You can use this service to get the file storage:

$file_storage = $this->entityTypeManager()->getStorage('file');

and then load the file:

$file = $file_storage->load($fid);
  • I have already checked for that possibility but in vain. entityTypeManager() is not present from ConfigFormBase calss. – fromTheFifties Sep 14 at 10:23
  • I updated my answer. – Tony Sep 14 at 10:33
  • 1
    This is only one half of it - you also need to override the ‘create` method and instantiate an appropriate instance in it. That’s how the dependency gets injected – Clive Sep 14 at 10:33
  • I added in my class declaration: class myClassForm extends ConfigFormBase implements ContainerInjectionInterface – fromTheFifties Sep 14 at 10:45
  • 4
    Yes you need to construct the parent with its required parameters as well, that's just how OOP works. It sounds like you haven't read drupal.org/docs/8/api/services-and-dependency-injection/… yet, it's important that you read an understand that before ploughing ahead with development – Clive Sep 14 at 11:29

This is my final code implementation as I was having this sort of warning:

Expected \Drupal\file\FileStorageInterface, got object Invocation parameter types are not compatible with declared.

So I updated create method to get the file storage directly:

class MyClassForm extends ConfigFormBase {

  /**
   * File storage for files.
   *
   * @var \Drupal\file\FileStorageInterface
   */
  protected $fileStorage;

  /**
   * SiteSettingsForm constructor.
   *
   * @param \Drupal\file\FileStorageInterface $file_storage
   *   File storage for files.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory) {
    parent::__construct($config_factory);
    $this->fileStorage = $entity_type_manager->getStorage('file');
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('config.factory')
    );
  }
}
  • 1
    You should use the entity_type.manager service and then in your __construct assign $file_storage with ->getStorage('file') – Ismail Cherri Sep 14 at 15:25
  • Well the best would be to inject the FileStorage in the first place. Unfortunaley standard D8 does not come up with a Storage ServiecProvider functionality. Because right now no matter you assign the FileStorage in the constructor, in your test you will have to still mock the "getStorage" method no matter what. – ssibal Sep 17 at 11:21

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.