Search by

flyo / nitro-yii2

Flyo Nitro Yii2 Framework Module

Maintainers

Package info

github.com/flyocloud/nitro-yii2

Type:yii2-extension

pkg:composer/flyo/nitro-yii2

Transparency log

Statistics

Installs: 1 997

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 1

3.7.2 2026-09-03 08:26 UTC

README

PHPUnit

composer require flyo/nitro-yii2

add the module to your config

'modules' => [
    'flyo' => [
        'class' => \Flyo\Yii\Module::class,
        'token' => 'YOUR_TOKEN',
        'liveEdit' => !YII_ENV_PROD, // this is the default behavior, set to `true` to enable live edit in production as well
    ]
]

add the cms page resolve to your views in the folder /views/nitro.php, all the routes from flyo nitro will now be resolved into this view file:

<?php
use Flyo\Yii\Widgets\PageWidget;
/** @var \Flyo\Model\Page $page */
?>
<h1><?= $page->getTitle(); ?>
<?= PageWidget::widget(['page' => $page]); ?>

In order to render those blocks use the Flyo\Yii\Widgets\PageWidget which will lookup all blocks inside the folder /views/flyo/*, so for instance you have a HeroTeaser component defined in flyo the view file is stored in /views/flyo/HeroTeaser.php with example content:

/** @var \Flyo\Model\Block $block */
print_r($block->getContent());
print_r($block->getConfig());
print_r($block->getItems());
print_r($block->getSlots());

Layout

Generate a navigation in the layout file, use the NavWidget:

<?php $nav = ContainerWidget::begin(['identifier' => 'main']) ?>
    <ul>
        <?php foreach ($nav->getItems() as $item): ?>
            <li><?= Html::a($item->getLabel(), $item->getHref()); ?></li>
        <?php endforeach; ?>
    </ul>
<?php $nav::end(); ?>

Layout blocks with children

An example where a block contains child blocks, defined in the slot content:

<?php
use Flyo\Yii\Widgets\BlockWidget;
/** @var \Flyo\Model\Block $block */
$config = $block->getConfig();
?>
<div class="container">
    <?php foreach ($block->getSlots()['content']->getContent() as $childBlock): ?>
        <div class="w-full">
            <?= BlockWidget::widget([
                'block' => $childBlock,
            ]); ?>
        </div>
    <?php endforeach; ?>
</div>
<?php SectionWidget::end(); ?>

Extend existing Routes

Its possible to extend the routing system for existing pages. This can help when building dynamic sub pages which need to ensure that you are still on the same CMS page (not not entity detail), in order to do add the following url rule in the UrlManager section:

'<path:(the-requested-slug)>/<slug:[a-z\-]+>' => 'flyo/nitro/index',

In order to link to extended route, its not possible to use Url::toRoute, since this is a fixed rule in routes anyhow you have to use:

<a href="/the-requested-slug/<?= ...; ?>">Detail</a>

Live Edit

As long as the liveEdit module property is enabled, the module registers the Nitro JS Bridge together with its boot script (page refresh, scroll to block, editor handshake and the click handlers for all elements with a data-flyo-uid attribute) whenever a page is rendered by a web application. This happens independently of the Editable widget, therefore live edit also works in projects which mark their blocks by hand or do not mark them at all, and it is switched on and off in one single place.

Yii2 Widget: Editable

This widget makes Flyo blocks editable inside the Flyo preview iframe by rendering the data-flyo-uid marker, which is picked up by the bridge registered through Live Edit.

Usage

Wrap content

<?php
use Flyo\Yii\Widgets\Editable;
?>

<?php Editable::begin(['block' => $block]); ?>
    <h2><?= $block->getTitle(); ?></h2>
    <p><?= $block->getText(); ?></p>
<?php Editable::end(); ?>

Renders:

<div data-flyo-uid="block-uid-here">
  <h2>…</h2>
  <p>…</p>
</div>

Attribute only

If you already have a wrapper element, use the static helper:

<section <?= Editable::attr($block) ?>>
  <h1><?= $block->getTitle(); ?></h1>
</section>

Renders:

<section data-flyo-uid="block-uid-here">
  <h1>…</h1>
</section>

Notes

Highlighting/click-to-edit works only inside Flyo’s preview iframe.

Outside preview, the page behaves normally.

Entity Detail and Draft Links

An entity detail is rendered with the EntityAction, the finder callable resolves the entity from the api:

public function actions()
{
    return [
        'detail' => [
            'class' => \Flyo\Yii\Actions\EntityAction::class,
            'finder' => fn (\Flyo\Api\EntitiesApi $api) => $api->entityBySlug(Yii::$app->request->get('slug')),
        ],
    ];
}

Flyo can hand out a draft link for an entity which is still offline: an expiring snapshot addressed by a token which takes the place of the unique id or the slug, so it is resolved through the very same call. Two things to keep in mind: a draft token does not look like a normal slug or unique id, therefore an url rule which validates the parameter against a pattern has to let it through, and typeId does not apply to a draft token.

Whenever the api answers with a draft, the action turns every cache layer off for that request — server page cache, cdn cache and client cache — and the response is sent with Cache-Control: no-store (plus no-store for the cdn headers and without the Last-Modified / Etag validators). A draft is deliberately never stored anywhere, so there is no copy left which could outlive the draft or hide a change made in the meantime.

Because that decision can only be made after the entity has been resolved, controllers which serve an EntityAction have to use Flyo\Yii\Filters\NitroPageCache instead of yii\filters\PageCache. It is the same filter, but it throws the recorded output away when the cache has been disabled during the request:

public function behaviors()
{
    return [
        [
            'class' => \Flyo\Yii\Filters\NitroPageCache::class,
            'only' => ['detail'],
            'enabled' => YII_ENV_PROD && \Flyo\Yii\Module::getInstance()->serverPageCache,
            'duration' => \Flyo\Yii\Module::getInstance()->serverPageCacheDuration,
            'dependency' => new \Flyo\Yii\Cache\VersionCacheDependency(),
            'variations' => [Yii::$app->request->getQueryParam('slug')],
        ],
    ];
}

In the view the draft state is available on the entity, use it to render a hint for the editor:

<?php if ($entity->getIsDraft()): ?>
    <p>Draft preview, this entity is not online yet.
       <?php if ($expiresAt = $entity->getDraftExpiresAt()): ?>
           The link expires on <?= Yii::$app->formatter->asDatetime((int) $expiresAt); ?>.
       <?php endif; ?>
    </p>
<?php endif; ?>

Any action which must not be cached can use the same switch: \Flyo\Yii\Module::getInstance()->disableCache();.

Documentation

Read More about Flyo Nitro in general