Menjelajahi Yii3 yang rilis 31 Desember 2025: arsitektur berbasis package yiisoft/* dengan SemVer per-package, bootstrap aplikasi Yii3 minimal dari nol, serta mode worker dengan RoadRunner dan FrankenPHP untuk throughput tinggi di atas PHP 8.2.

Sampai di episode 23 ini, seluruh praktik kita memakai Yii 2.0 — dan itu pilihan yang tepat: ekosistemnya paling matang dan dokumentasinya lengkap. Tapi Yii tidak berhenti. Pada 31 Desember 2025, Yii3 resmi rilis — dan ia mengubah cara framework ini bekerja secara fundamental.
Alih-alih satu framework monolitik, Yii3 adalah kumpulan package yiisoft/* yang dirilis independen dengan SemVer masing-masing. Ini bukan sekadar "versi baru" — ini paradigma baru: kalian merakit framework sesuai kebutuhan, bukan memakai semuanya. Di episode ini kita membedah arsitektur Yii3, membuat aplikasi minimal dari nol, dan membandingkannya dengan Yii2 yang sudah kalian kuasai.
Yii2 adalah satu package besar yiisoft/yii2 yang berisi semuanya: MVC, cache, i18n, dsb. Yii3 memecahnya menjadi package kecil yang fokus:
| Package (Yii3) | Peran | Padanan di Yii2 |
|---|---|---|
yiisoft/main (yii-core) | Aplikasi, config, middleware | yii\base\Application |
yiisoft/di | Dependency injection container | yii\di\Container |
yiisoft/router | Routing + URL generation | urlManager |
yiisoft/db | Database, query builder, AR | yii\db\* |
yiisoft/view | View, render, asset | yii\web\View |
yiisoft/log | Logging (PSR-3) | yii\log\* |
yiisoft/cache | Cache PSR-16 | yii\caching\* |
Konsekuensi besar dari desain ini:
yiisoft/router bisa naik ke 2.x sementara yiisoft/db tetap 1.x. Tidak ada lagi "versi Yii" tunggal — masing-masing package ber-version sendiri.Membuat aplikasi Yii3 dari awal berarti merakit package. Cara termudah: template resmi yiisoft/app (kita sudah lihat di episode 3). Mari bedah bagaimana ia dirakit:
composer create-project --prefer-dist yiisoft/app learn-yii3-app
cd learn-yii3-app
composer installStruktur template:
learn-yii3-app/
├── config/
│ ├── common/ # konfigurasi dipakai semua environment
│ ├── web/ # konfigurasi khusus web
│ ├── console/ # konfigurasi khusus konsol
│ └── packages/ # satu file per package
│ ├── router.php
│ ├── db.php
│ └── view.php
├── public/
│ └── index.php # entry point web
├── src/
│ ├── ApplicationRunner.php
│ ├── Handler/
│ └── User/
├── resources/ # view templates
├── runtime/
└── composer.json<?php
declare(strict_types=1);
use Yiisoft\Yii\Web\Application;
use Yiisoft\Yii\Web\SapiEmitter;
use Yiisoft\Yii\Web\ServerRequestFactory;
require dirname(__DIR__) . '/vendor/autoload.php';
$container = require dirname(__DIR__) . '/config/bootstrap.php';
/** @var Application $app */
$app = $container->get(Application::class);
$server = $container->get(ServerRequestFactory::class);
$emitter = $container->get(SapiEmitter::class);
$request = $server->createFromGlobals();
$response = $app->handle($request);
$emitter->emit($response);Perhatikan perbedaannya dengan Yii2: tidak ada Yii::$app global yang otomatis ada. Semuanya disuntikkan dari container ($container->get(...)) — HTTP request dibuat eksplisit, diproses aplikasi, dan di-emit. Ini PSR-7 murni.
Di Yii3, routing bukan magic URL — ia daftar route eksplisit di config/packages/router.php:
<?php
declare(strict_types=1);
use Yiisoft\Router\Group;
use Yiisoft\Router\Route;
use App\Handler\IndexHandler;
return [
'yiisoft/router/urlManager' => [
'routes' => [
Group::create('/api')
->routes(
Route::get('/posts')->action([IndexHandler::class, 'get']),
Route::post('/posts')->action([IndexHandler::class, 'create']),
),
],
],
];Setiap route terdefinisi eksplisit: method HTTP, path, dan handler. Tidak ada resolusi controller otomatis dari URL — desain yang lebih eksplisit dan lebih mudah diaudit.
"Controller" di Yii3 diganti konsep handler — class yang menerima request dan mengembalikan response:
<?php
declare(strict_types=1);
namespace App\Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final class IndexHandler
{
public function get(ServerRequestInterface $request): ResponseInterface
{
$response = new \Nyholm\Psr7\Response();
$response->getBody()->write('Halo dari Yii3!');
return $response;
}
}Handler adalah kode PHP murni dengan dependency injection via constructor — mudah ditest, mudah dipahami, dan tidak bergantung pada state global.
Salah satu daya tarik terbesar Yii3 adalah dukungan worker mode: aplikasi PHP dimuat sekali ke memori, lalu menangani banyak request tanpa re-inisialisasi per request. Perbedaan performanya dramatis — menghilangkan overhead bootstrap yang biasanya diulang jutaan kali.
RoadRunner (Go-based app server) menjalankan worker PHP persisten:
composer require spiral/roadrunner-cli
./vendor/bin/rr get
./rr serve -c .rr.yamlserver:
command: "php public/index.php"
relay: "pipes"
http:
address: "0.0.0.0:8080"
pool:
num_workers: 8
max_jobs: 1000
rpc:
listen: "tcp://127.0.0.1:6001"FrankenPHP menawarkan pendekatan berbeda: PHP terintegrasi langsung dengan Caddy web server — tanpa Nginx, tanpa PHP-FPM terpisah:
frankenphp php-server -r publicFROM dunglas/frankenphp
COPY . /app
WORKDIR /app
CMD ["frankenphp", "php-server", "-r", "public"]Tip
Kapan memakai worker mode? Untuk aplikasi dengan traffic tinggi dan logika berat per request (banyak query, perhitungan besar), worker mode memberi percepatan 2-5x karena bootstrap framework dihilangkan. Untuk aplikasi kecil atau yang traffic-nya rendah, PHP-FPM biasa sudah lebih dari cukup. Ukur dulu, optimalkan kemudian — jangan tambah kompleksitas tanpa data.
| Aspek | Yii 2.0 | Yii3 |
|---|---|---|
| Struktur | Satu package monolitik | Package yiisoft/* per bagian |
| Versi | Satu versi untuk semua | SemVer per-package |
| PHP | 7.4+ (rekomendasi 8.2+) | 8.2+ wajib |
| HTTP | SAPI bawaan + app global Yii::$app | PSR-7 + DI container eksplisit |
| Routing | Magic URL → controller/action | Route eksplisit → handler |
| Worker mode | Tidak didukung (FPM) | RoadRunner, FrankenPHP |
| Dukungan | Keamanan hingga Nov 2027 | Hingga 2035 (freeze fitur 2030) |
Poin terpenting untuk kalian yang sudah mahir Yii2: konsep yang kalian kuasai — Active Record, migrasi, i18n, RBAC, queue — tetap relevan. Yang berubah adalah container tempat mereka duduk: dari aplikasi global ke package yang dirakit. Migrasi dari Yii2 ke Yii3 bukan upgrade satu baris, melainkan rewrite parsial yang memanfaatkan skill yang sudah ada.
Satukan langkah-langkah di atas dalam satu alur nyata:
composer create-project --prefer-dist yiisoft/app learn-yii3-app
cd learn-yii3-app
composer install
php -S 127.0.0.1:8080 -t public # server bawaan untuk developmentcurl -s http://127.0.0.1:8080/api/posts
# Halo dari Yii3!Tambahkan koneksi database dengan yiisoft/db-mysql, definisikan di config/packages/db.php, dan aplikasi Yii3 kalian mulai berbicara dengan database — menggunakan Active Record yang sintaksnya akrab dari Yii2.
Inti yang harus dibawa pulang:
yiisoft/* dengan SemVer per-package, bukan satu versi framework.yiisoft/di) → aplikasi → router → handler.Di episode 24 selanjutnya, kita memperbesar skala: scaling & high availability — membuat aplikasi stateless, memanfaatkan Redis untuk cache dan session, read replicas untuk query berat, horizontal scaling dengan load balancer, serta mengukur performa dengan load test dan tuning PHP-FPM. Sampai jumpa di episode 24!