Sometimes you may find a .module file contain thousands lines of code so this file became not readable and hard to maintain.
So the question is:
How can i organise my .module code to be more readable and maintainable?
The answer is to create a class for each hook and implement your logic there instead of implemented it inside your .module file:
To do so let implement an hook example like hook_form_FORM_ID_alter for node_article_edit_form.
So instead of do something like:
<?php
use Drupal\Core\Form\FormStateInterface;
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function MY_MODULE_form_node_article_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Your code here the two following lines just an examples.
// Hide some fields.
$form['field_SOME_FIELD_NAME']['#access'] = FALSE;
// Attach some library ....
$form['#attached']['library'][] = 'MY_MODULE/SOME_LIBRARY';
}
You can create a class called NodeArticleEditFormHandler inside your src folder like the following:
<?php
namespace Drupal\MY_MODULE;
use Drupal\Core\Form\FormStateInterface;
/**
* Class NodeArticleEditFormHandler
*
* @package Drupal\MY_MODULE
*/
class NodeArticleEditFormHandler {
/**
* Alter Form.
*
* @param array $form
* Form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param $form_id
* String representing the id of the form.
*/
public function alterForm(array &$form, FormStateInterface $form_state, $form_id) {
// Your code here the two following lines just an examples.
// Hide some fields.
$form['field_SOME_FIELD_NAME']['#access'] = FALSE;
// Attach some library ....
$form['#attached']['library'][] = 'MY_MODULE/SOME_LIBRARY';
}
}
In case you need other services you can inject your dependencies by make your class implements ContainerInjectionInterface here is an example with current user service injection:
<?php
namespace Drupal\MY_MODULE;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class NodeArticleEditFormHandler
*
* @package Drupal\MY_MODULE
*/
class NodeArticleEditFormHandler implements ContainerInjectionInterface {
/**
* The current user account.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* NodeArticleEditFormHandler constructor.
*
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* The current user.
*/
public function __construct(AccountProxyInterface $current_user) {
$this->currentUser = $current_user;
}
/**
* @inheritDoc
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('current_user')
);
}
/**
* Alter Form.
*
* @param array $form
* Form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param $form_id
* String representing the id of the form.
*/
public function alterForm(array &$form, FormStateInterface $form_state, $form_id) {
// Example to get current user.
$currentUser = $this->currentUser;
// Your code here the two following lines just an examples.
// Hide some fields.
$form['field_SOME_FIELD_NAME']['#access'] = FALSE;
// Attach some library ....
$form['#attached']['library'][] = 'MY_MODULE/SOME_LIBRARY';
}
}
And after that change your hook into:
<?php
use Drupal\MY_MODULE\NodeArticleEditFormHandler;
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function MY_MODULE_form_node_article_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
return \Drupal::service('class_resolver')
->getInstanceFromDefinition(NodeArticleEditFormHandler::class)
->alterForm($form, $form_state, $form_id);
}
We are done!
Now your .module file more clean, readable and maintainable with less code on it.
You can do that to every hook for instance EntityHandler like:
<?php
use Drupal\MY_MODULE\EntityHandler;
/**
* Implements hook_entity_presave().
*/
function MY_MODULE_entity_presave(EntityInterface $entity) {
return \Drupal::service('class_resolver')
->getInstanceFromDefinition(EntityHandler::class)
->entityPresave($entity);
}
And so on!