Quick Start
1. Install
Optional packages to extend functionality:
2. Set the cookie secret
yiisoft/cookies'
secret key. Leaving it unset throws a LogicException.
Generate a strong, random string and set it in config/params.php.
return [
'yiisoft/cookies' => [
'secretKey' => $_ENV['COOKIES_SECRET'],
],
];
3. Run migrations
Voyti provides its migration path through config/params-console.php
using the standard yiisoft/db-migration configuration keys.
With yiisoft/db-migration enabled in your console app, run:
One migration creates the user, user_profile,
user_social_account, user_token,
user_sessions, user_backup_code,
user_password_history, and user_audit_log
tables with all columns (2FA, GDPR, password expiration, last
login IP, etc.) included. config/params-console.php also
registers yiisoft/rbac-db's own item/assignment
migrations, so ./yii migrate:up creates the RBAC tables
too - no separate step needed.
If the user table is still empty after these migrations
run, a default admin account is seeded automatically: username
admin, email admin@example.com, and a random
20-character password printed to the console - copy it
immediately, it isn't stored anywhere else. The account is assigned
the administrator role, which is granted the
administratorPermissionName permission
(voyti-admin by default) needed to reach the
admin dashboard. Change this password immediately after first
login. If the user table already has rows (e.g.
re-running migrations on an existing database), seeding is skipped
entirely.
4. Register routes
Routes are not auto-registered - you must add them to your router configuration.
Pull the voyti-routes config group into your router
definition. The example below mounts them under a /user/
prefix as their own group, alongside your app's own routes -
change the prefix as needed. It also shows the optional REST API
group, mounted as its own sibling group; skip it if you don't need
the API (see below):
use Yiisoft\Config\Config;
use Yiisoft\Definitions\DynamicReference;
use Yiisoft\Router\Group;
use Yiisoft\Router\RouteCollection;
use Yiisoft\Router\RouteCollectionInterface;
use Yiisoft\Router\RouteCollector;
use Yiisoft\Session\SessionMiddleware;
use YiiRocks\Voyti\Middleware\VoytiMiddleware;
/** @var Config $config */
return [
RouteCollectionInterface::class => [
'class' => RouteCollection::class,
'__construct()' => [
'collector' => DynamicReference::to(
static fn() => (new RouteCollector())
->addRoute(
Group::create('/')
->middleware(
SessionMiddleware::class, # required for site-wide session support
VoytiMiddleware::class, # Site-wide enforcement
)
->routes(...$config->get('routes')), # Your routes
Group::create('/user/') # Voyti web URL prefix
->routes(...$config->get('voyti-routes')), # Voyti web routes
Group::create('/user/api/') # REST API URL prefix - optional
->routes(...$config->get('voyti-routes-api')), # delete this group when unneeded
)
),
],
],
];
voyti-routes and voyti-routes-api each already
wrap themselves with their own required middleware (see
config/routes.php and config/routes-api.php), so
neither group above repeats any of it, and adding
VoytiMiddleware to your own group only extends that same
coverage to your app's pages.
The REST API routes are entirely optional and not part
of voyti-routes - they live in their own
voyti-routes-api config group, which nothing else depends
on. If you don't need the API, skip pulling that group in and none of
it is registered; there's no config flag to enable it or prefix option
to set, the group's own registration is the switch. When you do want
it, mount it wherever you like - the /api/ sibling
group shown above is just one option.
5. Configure the form theme
Voyti's forms (login, registration, profile, etc.) and its
button-styled links (e.g. "Create user") render through
yiisoft/form's ThemeContainer. Voyti ships
no theme of its own, so until your app configures one, every field
and button renders with no CSS classes at all - no
form-control, no btn, nothing.
Set a theme in config/params.php. yiisoft/form
ships ready-made Bootstrap 5 configs you can use as-is:
use Yiisoft\Form\Theme\ThemePath;
use Yiisoft\FormModel\ValidationRulesEnricher;
return [
'yiisoft/form' => [
'themes' => [
'default' => [
...require ThemePath::BOOTSTRAP5_VERTICAL,
'enrichFromValidationRules' => true,
'validationRulesEnricher' => new ValidationRulesEnricher(),
],
],
'defaultTheme' => 'default',
],
];
Swap in ThemePath::BOOTSTRAP5_HORIZONTAL for a
horizontal label/input layout, or write your own array of
Theme::__construct() options if you're not using
Bootstrap. The key doesn't have to be named bootstrap5
- ThemeContainer resolves a single named config
per Theme instance, so enrichFromValidationRules
and validationRulesEnricher() below have to live in
whichever config your defaultTheme points at, not in
a separate Bootstrap-only entry. Naming it default
(matching yiisoft/form's own config/params.php
stub) keeps that clear.
enrichFromValidationRules and
validationRulesEnricher are worth setting alongside
the theme: they translate the yiisoft/validator rules
already on your form models (Required,
Length, Regex, etc.) into matching HTML5
input attributes (required, minlength/
maxlength, pattern, and so on), giving
you client-side validation for free instead of relying on a
server round-trip alone.
6. Done
DI bindings, event listeners, and console commands are auto-registered via the Yii3 config plugin. No manual wiring needed.