1. Go to this page and download the library: Download ingenerator/kohana-view library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
// bootstrap.php
\Ingenerator\KohanaView\ViewModel\DisplaySchema\ViewDisplaySchemaProviderInstance::init(
cache: match(Kohana::$environment) {
Kohana::DEVELOPMENT => new \Symfony\Component\Cache\Adapter\ArrayAdapter(),
default => new \Symfony\Component\Cache\Adapter\ApcuAdapter(),
}
);
//application/classes/View/Hello/WorldView.php
namespace View\Hello;
class WorldView extends \Ingenerator\KohanaView\ViewModel\AbstractViewModel
{
/**
* The `name` variable will be passed into the view's `->display()` method.
*/
public protected(set) string $name;
/**
* The `is_morning` property will be computed on each access
*/
public bool $is_morning {
get => new \DateTimeImmutable()->format('H') < 12;
}
}
//application/views/hello/hello_world.php
use function Ingenerator\KohanaView\OutputValue\raw;
/**
* @var \View\Hello\WorldView $view
* @var \Ingenerator\KohanaView\Renderer\HTMLRenderer $renderer
*/
//application/classes/Controller/Welcome.php
class Controller_Welcome extends Controller
{
public function action_index()
{
$view = new View\Hello\WorldView;
$view->display(['name' => $this->request->query('name')]);
$renderer = $this->dependencies->get('kohanaview.renderer.html');
/** @var \Ingenerator\KohanaView\Renderer\HTMLRenderer */
$this->response->body($renderer->render($view));
}
}
namespace View\Layout;
class SitePageTemplateView extends Ingenerator\KohanaView\ViewModel\PageLayout\AbstractPageLayoutView
{
}
namespace View\Layout;
class ContentWithSidebarLayoutView extends Ingenerator\KohanaView\ViewModel\PageLayout\AbstractIntermediateLayoutView
{
public function __construct(
SitePageTemplateView $page,
public readonly ViewModel $sidebar
)
{
parent::__construct($page);
}
}
namespace View\Layout;
class SidebarView extends Ingenerator\KohanaView\ViewModel\AbstractViewModel
{
// Whatever you want it to show
}
namespace View\Layout;
class SitePageContentView extends Ingenerator\KohanaView\ViewModel\PageLayout\AbstractPageContentView {
/**
* $view->page will be the top-level parent view. The generic AbstractPageContentView types this as any
* NestedParentView - if you know that your site will always inject a SitePageTemplateView then you can
* extend this view variable with the correct type to allow autocompletion in your templates.
*/
public SitePageTemplateView $page {
get => {
$page = parent::$page::get();
assert($page instanceof SitePageTemplateView, 'Expected to be within a SitePageTemplateView, got ' . $page::class);
return $page;
}
}
}
namespace View\Pages;
class HelloWorldView extends View\Layout\SitePageContentView
{
public protected(set) string $name;
}
//application/views/site_page_template.php
use function Ingenerator\KohanaView\OutputValue\raw;
/**
* @var \View\Layout\SitePageTemplateView $view
* @var \Ingenerator\KohanaView\Renderer\HTMLRenderer $renderer
*/
//application/views/content_with_sidebar_layout.php
use function Ingenerator\KohanaView\OutputValue\raw;
/**
* @var \View\Layout\ContentWithSidebarLayout $view
* @var \Ingenerator\KohanaView\Renderer\HTMLRenderer $renderer
*/
//application/views/pages/hello_world.php
/**
* @var \View\Pages\HelloWorldView $view
* @var \Ingenerator\KohanaView\Renderer\HTMLRenderer $renderer
*/
// You can do this here if you want to keep templatey-type stuff together
// Or in your view model at display time if it's a bit more involved
$view->page->setTitle('Hello World');
class Controller_Welcome extends Controller // Look, extend any controller! No more Controller_Template!
{
public function action_index()
{
// You probably want to put your views into the dependency container too
$content = new HelloWorldView(
new ContentWithSidebarLayoutView(
new SitePageTemplateView(),
new SidebarView()
)
);
$content->display(['name' => $this->request->query('name')]);
$renderer = $this->dependencies->get('kohanaview.renderer.page_layout');
/** @var \Ingenerator\KohanaView\Renderer\PageLayoutRenderer $renderer */
$this->response->body($renderer->render($content));
}
}
use Ingenerator\KohanaView\Attribute\InternalDisplayVariable;
use Ingenerator\KohanaView\Attribute\OptionalDisplayVariable;
use Ingenerator\KohanaView\Attribute\RequiredDisplayVariable;
class View_Something extends AbstractViewModel {
/**
* `caption` MUST be */
#[OptionalDisplayVariable]
public protected(set) string $title = 'My page title';
/**
* `internal` MUST be isplayVariable]
public readonly string $some_var;
/**
* `now` MUST NOT be view->caption; // ''
$view->display(['caption' => 'Something', 'title' => 'A title', 'internal'=> 'foo']);
print $view->title; // 'A title'
print $view->caption; // 'Something'
$view->display(['caption' => 'Something else', 'internal'=> 'foo']);
print $view->title; // 'My page title'
print $view->caption; // 'Something else'
class View_That_Does_Work extends \Ingenerator\KohanaView\ViewModel\AbstractViewModel {
public protected(set) string $user_email;
public array $user_activity {
get => $this->getCached(__PROPERTY__, $this->loadUserActivity(...))
}
public function __construct (
private readonly DatabaseAdapter $database
) {
}
private function loadUserActivity(): array
{
$activity = [];
foreach ($this->database->loadActivityForUser($this->user_email) as $activity) {
$activity[] = (string) $activity;
}
return $activity;
// Future usage of $view->user_activity will now get the value cached in the variables array without calling
// this method again until the next ->display() call.
}
}
class View_Container extends \Ingenerator\KohanaView\ViewModel\AbstractViewModel {
public protected(set) array $users;
public function __construct(View_User_FaceWidget $face_widget)
{
$this->face_widget = $face_widget;
}
protected function var_face_widget()
{
return $this->face_widget;
}
}