mobileka/scope-applicator-yii2

View on GitHub
readme.md

Summary

Maintainability
Test Coverage
[![Build Status](https://travis-ci.org/mobileka/scope-applicator-yii2.svg)](https://travis-ci.org/mobileka/scope-applicator-yii2)
[![Code Climate](https://codeclimate.com/github/mobileka/scope-applicator-yii2.svg)](https://codeclimate.com/github/mobileka/scope-applicator-yii2)
[![Coverage Status](https://coveralls.io/repos/mobileka/scope-applicator-yii2/badge.svg?branch=master)](https://coveralls.io/r/mobileka/scope-applicator-yii2?branch=master)

[ScopeApplicator](https://github.com/mobileka/scope-applicator) brings an elegant way of sorting and filtering data to your Yii2 projects.

- [Overview](#overview)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)

## Overview

ScopeApplicator is an easy and logical way to achieve something like this:

`/posts` – returns a list of all posts

`/posts?recent` – returns only recent posts

`/posts?author_id=5` – returns posts belonging to an author with an `id=5`

`/posts?author_id=5&order_by_title=desc&status=active` – returns only active posts belonging to an author with an `id=5` and sorts them by a title in a descending order

## Requirements

– PHP 5.4 or newer

– Yii 2.0.x

## Installation

`composer require mobileka/scope-applicator-yii2 1.0.*`

## Usage

Let's learn by example. First of all, we'll implement an `author_id` filter for `post` table.

These are steps required to achieve this:

1. Create a `PostQuery` class which extends `Mobileka\ScopeApplicator\Yii2\ActiveQuery` and define a `userId` method
2. Create a `Post` model which extends `Mobileka\ScopeApplicator\Yii2\Model` and make it use the `PostQuery` instead of a regular `ActiveQuery`
3. Create a basic `PostController` which outputs a list of posts when `/posts` route is hit
4. Tell ScopeApplicator that `userId` scope is available and give it an alias
5. Visit `/posts?author_id=1` and enjoy the result

Ok, let's cover these step by step.

— Create a `PostQuery` class in `app/models/queries` directory with the following content:

```php
<?php

namespace app\models\queries;

use Mobileka\ScopeApplicator\Yii2\ActiveQuery;

class PostQuery extends ActiveQuery
{
    public function userId($id = 0)
    {
        if ($id) {
            return $this->andWhere(['user_id' => $id]);
        }

        return $this;
    }
}

```

I'll refer the `userId()` method as a `userId` *scope* in the future.

Make sure that this class extends `Mobileka\ScopeApplicator\Yii2\ActiveQuery`.

– Create a `Post` model and override the `find` method like follows:

```php
<?php

namespace app\models;

use app\models\queries\PostQuery;
use Mobileka\ScopeApplicator\Yii2\Model;
use Yii;

class Post extends Model
{
    public static function find()
    {
        return Yii::createObject(PostQuery::className(), [get_called_class()]);
    }
}

```

This makes sure that our `userId` scope will be available to the `Post` model.

– Next, create a `PostController`:

```php
<?php

namespace app\controllers;

use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;

class PostController extends Controller
{
    public function actionIndex()
    {
        return Post::find()->all();
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator']['formats'] = [
            'application/json' => Response::FORMAT_JSON
        ];

        return $behaviors;
    }
}
```

In this case I extend the `yii\rest\Controller` and make sure that its output format is set to JSON.

– Now let's modify this controller to make it use ScopeApplicator:

```php
<?php

namespace app\controllers;

use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;

class PostController extends Controller
{
    /**
     * Scope configuration array
     */
    protected $scopes = ['userId'];

    public function actionIndex()
    {
        return Post::applyScopes($this->scopes)->all();
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator']['formats'] = [
            'application/json' => Response::FORMAT_JSON
        ];

        return $behaviors;
    }
}

```

Note that I added a new protected property which describes available scopes. Right now we have only `userId`.

Also note that I have replaced `Post::find()` with `Post::applyScopes($this->scopes)`.

If you have done all the above steps, you should be able to populate your `post` table and try to filter data like follows:
`/posts?userId=x`.

But we wanted it to be `author_id` instead of `userId`, so we have to configure our scope and add an alias:

```php
<?php

namespace app\controllers;

use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;

class PostController extends Controller
{
    /**
     * Scope configuration array
     */
    protected $scopes = [
        'userId' => [
            // here it is!
            'alias' => 'author_id'
        ]
    ];

    public function actionIndex()
    {
        return Post::applyScopes($this->scopes)->all();
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator']['formats'] = [
            'application/json' => Response::FORMAT_JSON
        ];

        return $behaviors;
    }
}
```

— That's it! Now you can visit `/posts?author_id=x` and check the result.

`alias` is only one of the many available scope configuration options. These are described in ScopeApplicator's [documentation](https://github.com/mobileka/scope-applicator#configuration-options).

## Contributing

If you have noticed a bug or have suggestions, you can always create an issue or a pull request (use PSR-2). We will discuss the problem or a suggestion and plan the implementation together.

## License

ScopeApplicator is an open-source software and licensed under the [MIT License](https://github.com/mobileka/scope-applicator-yii2/blob/master/license).