Skip to content

Pinto is capable of auto executing nested components.

Automatically building nested components

Component design

Typically, Pinto requires you to invoke the builder method of components:

php
#[Slots]
final class InnerComponent {
  use DrupalInvokableSlotsTrait; 
}
php
#[Slots(slots: ['obj'])]
final class OuterComponent {
  use DrupalInvokableSlotsTrait;

  protected function build(Slots\Build $build): Slots\Build { 
    $inner = new InnerComponent();
    return $build 
      ->set('obj', $inner()); 
  }
}
php
$obj = new OuterComponent();
$build = $obj();

Auto invokation

Because InnerComponent is recognised as a registered Pinto component, you can avoid invoking the component yourself, and associated parenthesis paralysis. It will be invoked automatically:

The above OuterComponent snippet becomes:

php
#[Slots(slots: ['obj'])]
final class OuterComponent {
  use DrupalInvokableSlotsTrait;

  protected function build(Slots\Build $build): Slots\Build { 
    $inner = new InnerComponent();
    return $build 
      ->set('obj', $inner); 
  }
}

This way, only the outermost component needs to be invoked, as usual.

php
$obj = new OuterComponent();
$build = $obj();

Timing

Auto invokation happens after the builder phase, so an inner component will not be invoked and made available to a builder method.

To conditionally prevent a component from being invoked, you may set the slot value to any value, including anything empty/nullish.

php
#[Slots(bindPromotedProperties: TRUE)]
final class OuterComponent {
  use DrupalInvokableSlotsTrait;
  
  public function __construct(
    private InnerComponent $innerComponent = new InnerComponent(),
  ) {
  }

  protected function build(Slots\Build $build): Slots\Build { 
    return $build 
      ->set('obj', NULL); 
  }
}