Yii2 Best Practices & Large-Scale Application Structure

Building a Yii2 application at scale requires a well-structured architecture, clean coding practices, and efficient performance optimization. This tutorial covers best practices for Yii2 development and how to structure a large-scale Yii2 application.


1. Yii2 Application Structures

Yii2 provides two default application templates:

  1. Basic Application Template - Suitable for small projects
  2. Advanced Application Template - Designed for large applications with separate frontend and backend

For large-scale applications, the Advanced Template or a custom modular structure is recommended.


2. Best Practices for Yii2 Development

2.1 Follow MVC Properly

Yii2 is built on the MVC pattern. Keep concerns separate:

  • Models: Handle data and business logic
  • Views: Handle UI rendering
  • Controllers: Handle requests and responses

Avoid putting business logic in controllers or views.

2.2 Use Dependency Injection & Service Container

Instead of creating objects directly, use Yii2's Dependency Injection (DI) Container for better flexibility.

Example: Define a component in config/web.php:

'components' => [
    'mailer' => [
        'class' => 'yii\swiftmailer\Mailer',
        'useFileTransport' => false,
    ],
],

Then, use it anywhere in your application:

Yii::$app->mailer->compose()
    ->setTo('user@example.com')
    ->setSubject('Hello')
    ->send();

This makes it easier to replace components without modifying the entire codebase.

2.3 Use Yii2 Behaviors & Events

For reusable logic, use Behaviors and Events instead of writing redundant code in models.

Example: Attach a behavior to automatically set timestamps:

use yii\behaviors\TimestampBehavior;

public function behaviors()
{
    return [
        TimestampBehavior::class,
    ];
}

2.4 Use Yii2’s Built-in Caching

Yii2 provides multiple caching mechanisms (FileCache, MemCache, Redis).

Enable file caching in config/web.php:

'components' => [
    'cache' => [
        'class' => 'yii\caching\FileCache',
    ],
],

Use caching in queries:

$data = Yii::$app->cache->getOrSet('my-data-key', function () {
    return MyModel::find()->all();
}, 3600);

$users = User::find()->cache(3600)->all()

This reduces database queries and improves performance.


3. Structuring a Large-Scale Yii2 Application

For large projects, organize your Yii2 application into modules and service layers.

3.1 Modular Architecture

Instead of keeping all code in controllers and models, use Modules to group related functionality.

Example: Creating a "User" Module

1. Create a module:

php yii gii/module --moduleID=user

2. Register the module in config/web.php:

'modules' => [
    'user' => [
        'class' => 'app\modules\user\Module',
    ],
],

3. Access it via: https://yourapp.com/user/default/index

Each module has its own controllers, models, and views, making the application more manageable.

3.2 Service Layer for Business Logic

Instead of putting complex logic inside models or controllers, create Service Classes for better separation.

Example: services/UserService.php

namespace app\services;

use app\models\User;

class UserService
{
    public function createUser($data)
    {
        $user = new User();
        $user->attributes = $data;
        return $user->save();
    }
}

Use in controllers:

$userService = new \app\services\UserService();
$userService->createUser(Yii::$app->request->post());

This improves code reusability and testing.

3.3 Repository Pattern for Database Queries

Instead of writing queries directly in models, use a Repository Layer.

Example: repositories/UserRepository.php

namespace app\repositories;

use app\models\User;

class UserRepository
{
    public function findActiveUsers()
    {
        return User::find()->where(['status' => 1])->all();
    }
}

Use in services:

$users = (new UserRepository())->findActiveUsers();

This improves database query organization and allows easy modifications.


4. Security Best Practices

4.1 Use Yii2 Authentication & RBAC

For role-based access control, use Yii2’s RBAC system instead of checking roles manually.

Set up RBAC in console/migrations:

$auth = Yii::$app->authManager;
$admin = $auth->createRole('admin');
$auth->add($admin);

Assign roles dynamically:

$auth->assign($admin, $userId);

4.2 Protect Against SQL Injection & XSS

Always use Yii2’s ActiveRecord and Query Builder to prevent SQL injection:

User::find()->where(['email' => $email])->one();

Sanitize user input using Html::encode():

echo Html::encode($user->name);

4.3 Enable CSRF Protection

Yii2 has CSRF protection enabled by default. Ensure your forms include the CSRF token:

<?= Html::beginForm(['/user/login'], 'post', ['csrf' => true]) ?>

5. Optimizing Performance in Large Yii2 Applications

5.1 Optimize Database Queries

  • Use Indexing on frequently queried columns
  • Use Lazy Loading instead of eager loading where necessary
  • Use Pagination to limit query results

Example:

$query = User::find()->where(['status' => 1]);
$pagination = new Pagination(['totalCount' => $query->count(), 'pageSize' => 10]);
$users = $query->offset($pagination->offset)->limit($pagination->limit)->all();

5.2 Use Yii2 Queue System for Background Jobs

If your application has heavy processing (email sending, reports), use Yii2 Queue.

Install Yii2 Queue:

composer require yiisoft/yii2-queue

Run queue tasks:

php yii queue/run

5.3 Enable Gzip Compression

Add this to .htaccess for faster response times:

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css application/javascript
</IfModule>

6. Testing & Debugging in Yii2

6.1 Use Yii2 Debug Toolbar

Enable it in config/web.php:

if (YII_ENV_DEV) {
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = 'yii\debug\Module';
}

Access it at /debug.

6.2 Write Unit & Functional Tests

Install Codeception for testing:

composer require --dev codeception/codeception

Run tests:

vendor/bin/codecept run

Conclusion

For large-scale Yii2 applications, following best practices ensures:

  • Maintainable and scalable architecture
  • Secure and optimized performance
  • Efficient debugging and testing