Bundle classes have arrived! In my opinion a major change to drupal and the way we will do theming. Introduced in branch 9.3.x.
Below are some examples of how they can be used.
For example, a custom module could declare a bundle class for a node type like this:
use Drupal\mymodule\Entity\BasicPage;
function mymodule_entity_bundle_info_alter(array &$bundles): void {
if (isset($bundles['node']['page'])) {
$bundles['node']['page']['class'] = BasicPage::class;
}
}
You can define an interface
for specific custom logic, for example, support for a body field:
namespace Drupal\mymodule\Entity;
interface BodyInterface {
/**
* Returns the body.
*
* @return string
*/
public function getBody(): string;
}
An interface
can then be created for the bundle in a custom module, extending both NodeInterface
and the custom BodyInterface
:
namespace Drupal\mymodule\Entity;
use Drupal\node\Entity\NodeInterface;
interface BasicPageInterface extends NodeInterface, BodyInterface {
}
The bundle classes themselves extend the entity class, but implement any additional required methods from the other interfaces it provides.
namespace Drupal\mymodule\Entity;
use Drupal\node\Entity\Node;
class BasicPage extends Node implements BasicPageInterface {
// Implement whatever business logic specific to basic pages.
public function getBody(): string {
return $this->get('body')->value;
}
}
Alternatively, the getBody()
implementation could live in a BodyTrait
that was shared across multiple bundle subclasses.
You can start to introduce common functionality for all of your node types with an abstract class. This approach requires defining a bundle subclass for every node type on the site (or every bundle of whatever entity type you're using this for: media, etc).
Introduce a common interface:
namespace Drupal\myproject\Entity;
use Drupal\node\NodeInterface;
class MyProjectNodeInterface extends NodeInterface {
public function getTags(): array;
public function hasTags(): bool;
}
And then introduce an abstract base class:
namespace Drupal\myproject\Entity;
use Drupal\node\Entity\Node;
abstract class MyProjectNodeBase extends Node implements MyProjectNodeInterface {
public function getTags: array {
return [];
}
public function hasTags: bool {
return FALSE;
}
}
And then even some traits:
namespace Drupal\myproject\Entity;
trait NodeWithTagsTrait {
public function getTags(): array {
// Put a real implementation here.
return $this->get('tags')->getValue();
}
public function hasTags(): bool {
return TRUE;
}
}
Then you can rewrite your basic page as follows:
namespace Drupal\mymodule\Entity;
use Drupal\node\Entity\Node;
use Drupal\myproject\Entity\NodeWithTagsTrait;
use Drupal\myproject\Entity\MyProjectNodeBase;
class BasicPage extends MyProjectNodeBase implements BasicPageInterface {
use NodeWithTagsTrait
public function getBody(): string {
return $this->get('body')->value;
}
}
More about bundle classes via this link: Introducing bundle classes