Skip to content

Component lifecycle

Syone edited this page Mar 7, 2025 · 4 revisions

Component lifecycle

This is what happens when we render (echo) a component

graph TD;
    Init([Construct and render]) --> A[Added] --> B[Mount] --> C(Render sub components) --> D[Mounted] --> E(Render current component);
Loading

We can add hooks that are called during different moments at component rendering process:

  1. Added event: when a component is added into another
  2. Mount event: before the rendering of sub components
  3. Mounted event: after the rendering of sub components

The Component class has 3 methods for registering callbacks for these events:

  • added(callable $callback)
  • mount(callable $callback)
  • mounted(callable $callback)

Example:

<?php

use Sy\Component;

class A extends Component {
	
	public function __construct() {
		echo 'A Construct' . PHP_EOL;
		
		$this->mounted(function () {
		    echo 'A Mounted' . PHP_EOL;
		});
		
		$this->mount(function () {
		    echo 'A Mount' . PHP_EOL;
		    $this->setVar('SLOT', new B());
		});
		
		$this->added(function () {
		    echo 'A Added' . PHP_EOL;
		});		
	}
	
	public function __toString() {
		echo 'A Render start' . PHP_EOL;
		$res = parent::__toString();
		echo 'A Render end' . PHP_EOL;
		return $res;
	}
	
}

class B extends Component {
	
	public function __construct() {
		echo 'B Construct' . PHP_EOL;
		
		$this->mounted(function () {
		    echo 'B Mounted' . PHP_EOL;
		});
		
		$this->mount(function () {
		    echo 'B Mount' . PHP_EOL;
		});
		
		$this->added(function () {
		    echo 'B Added' . PHP_EOL;
		});		
	}
	
	public function __toString() {
		echo 'B Render start' . PHP_EOL;
		$res = parent::__toString();
		echo 'B Render end' . PHP_EOL;
		return $res;
	}
	
}

echo new A();

Run this script

Will result:

A Construct
A Render start
A Added
A Mount
B Construct
B Added
B Render start
B Mount
B Mounted
B Render end
A Mounted
A Render end

When do I need to use these hooks?

As a best practice, we recommend to make all the "setVar" stuff during the mount stage. Then we ensure that all the parent component translators at transmitted before calling the translation method (underscore):

<?php

use Sy\Component;

class MyComponent extends Component {

	public function __construct() {
		$this->addTranslator(__DIR__ . '/lang');
		$this->setTemplateFile(__DIR__ . '/mycomponent.tpl');
		$this->mount(fn() => $this->init());
	}

	private function init() {
		$this->setVars([
			'HELLO'     => $this->_('hello'),
			'WORLD'     => $this->_('world'),
			'COMP_SLOT' => new MyOtherComponent(),
		]);
	}

}

class MyOtherComponent extends Component {

	public function __construct() {
		$this->setTemplateFile(__DIR__ . '/myothercomponent.tpl');

		//!\\ Be careful here, 'hello' can not be translated with the translator of MyComponent because it is not transmitted yet at the construction stage
		$this->setVar('HELLO' => $this->_('hello'));

		$this->mount(fn() => $this->init());
	}

	private function init() {
		$this->setVar('WORLD' => $this->_('world'));
	}

}
Clone this wiki locally