Laravel Eloquent boolean & timestamp flagged attributes behavior.
PHP
Latest commit 215a3e5 Jan 14, 2017 @a-komarev a-komarev committed on GitHub Merge pull request #24 from cybercog/feature/implement-all-helpers
Implement all helpers common methods

README.md

cog-laravel-eloquent-flag-3

Build Status StyleCI Releases License

Introduction

Eloquent boolean & timestamp flagged attributes behavior. Enhance eloquent models with commonly used state flags like Active, Published, Approved and others in a minutes!

Features

  • Designed to work with Laravel Eloquent models
  • Each model can has as many flags as required
  • Each flag adds global query scopes to models
  • 2 logical groups of flags: Classic, Inverse
  • 2 types of flags: Boolean, Timestamp
  • Covered with unit tests

Available flags list

Trait name Logic Database column Flag type Conflict
HasAcceptedAt Classic accepted_at Timestamp HasAcceptedFlag
HasAcceptedFlag Classic is_accepted Boolean HasAcceptedAt
HasActiveFlag Classic is_active Boolean -
HasApprovedAt Classic approved_at Timestamp HasApprovedFlag
HasApprovedFlag Classic is_approved Boolean HasApprovedAt
HasClosedAt Inverse closed_at Timestamp HasClosedFlag
HasClosedFlag Inverse is_closed Boolean HasClosedAt
HasExpiredAt Inverse expired_at Timestamp HasExpiredFlag
HasExpiredFlag Inverse is_expired Boolean HasExpiredAt
HasKeptFlag Classic is_kept Boolean -
HasPublishedAt Classic published_at Timestamp HasPublishedFlag
HasPublishedFlag Classic is_published Boolean HasPublishedAt
HasVerifiedAt Classic verified_at Timestamp HasVerifiedFlag
HasVerifiedFlag Classic is_verified Boolean HasVerifiedAt

Any entity can has more than one flag at the same time. If flags can't work for the same entity simultaneously they are listed in Conflict column.

How it works

Eloquent Flag is an easy way to add flagged attributes to eloquent models. All flags has their own trait which adds global scopes to desired entity.

There are 2 types of flags:

  • Boolean flags are the common ones. Stored in database as BOOLEAN or TINYINT(1) value.
  • Timestamp flags represented in database as nullable TIMESTAMP column. Useful when you need to know when action was performed.

All flags separated on 2 logical groups:

  • Classic flags displays only entities with true or timestamp flag value.
  • Inverse flags displays only entities with false or null flag value.

Omitted entities could be retrieved by using special global scope methods, unique for each flag.

Installation

First, pull in the package through Composer.

composer require cybercog/laravel-eloquent-flag

And then include the service provider within app/config/app.php.

// Service provider not using yet. This step not mandatory. Will be used to boot console commands in future.

'providers' => [
    Cog\Flag\Providers\FlagServiceProvider::class,
];

Usage

Prepare database

Boolean flag

public function up()
{
    Schema::create('post', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->boolean('is_published');
        $table->timestamps();
    });
}

Change is_published on any other Boolean flag database column name.

Timestamp flag

public function up()
{
    Schema::create('post', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->timestamp('published_at')->nullable();
        $table->timestamps();
    });
}

Change published_at on any other Timestamp flag database column name.

Setup an activatable model

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasActiveFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasActiveFlag;
}

Model must have boolean is_active column in database table.

Available functions

Get only active models

Post::all();
Post::withoutDeactivated();

Get only deactivated models

Post::onlyDeactivated();

Get active + deactivated models

Post::withDeactivated();

Activate model

Post::where('id', 4)->activate();

Deactivate model

Post::where('id', 4)->deactivate();

Setup an acceptable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasAcceptedFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasAcceptedFlag;
}

Model must have boolean is_accepted column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasAcceptedAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasAcceptedAt;
}

Model must have nullable timestamp accepted_at column in database table.

Available functions

Get only accepted models

Post::all();
Post::withoutRejected();

Get only rejected models

Post::onlyRejected();

Get accepted + rejected models

Post::withRejected();

Accept model

Post::where('id', 4)->accept();

Deactivate model

Post::where('id', 4)->reject();

Setup an approvable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasApprovedFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasApprovedFlag;
}

Model must have boolean is_approved column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasApprovedAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasApprovedAt;
}

Model must have nullable timestamp approved_at column in database table.

Available functions

Get only approved models

Post::all();
Post::withoutDisapproved();

Get only disapproved models

Post::onlyDisapproved();

Get approved + disapproved models

Post::withDisapproved();

Approve model

Post::where('id', 4)->approve();

Disapprove model

Post::where('id', 4)->disapprove();

Setup a publishable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasPublishedFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasPublishedFlag;
}

Model must have boolean is_published column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasPublishedAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasPublishedAt;
}

Model must have nullable timestamp published_at column in database table.

Available functions

Get only published models

Post::all();
Post::withoutUnpublished();

Get only unpublished models

Post::onlyUnpublished();

Get published + unpublished models

Post::withUnpublished();

Publish model

Post::where('id', 4)->publish();

Unpublish model

Post::where('id', 4)->unpublish();

Setup a verifiable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasVerifiedFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasVerifiedFlag;
}

Model must have boolean is_verified column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasVerifiedAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasVerifiedAt;
}

Model must have nullable timestamp verified_at column in database table.

Available functions

Get only verified models

Post::all();
Post::withoutUnverified();

Get only unverified models

Post::onlyUnverified();

Get verified + unverified models

Post::withUnverified();

Verify model

Post::where('id', 4)->verify();

Unverify model

Post::where('id', 4)->unverify();

Setup a keepable model

Keep functionality required when you are trying to attach related models before parent one isn't persisted in application.

Issue:

  1. User press Create Post button.
  2. Create post form has image uploader.
  3. On image uploading user can't attach image to post before post entity wouldn't been stored in database.

Solution:

  1. Add HasKeptFlag trait to model (and add boolean is_kept column to model's database table).
  2. Create empty model on form loading (it will has is_kept = 0 by default).
  3. Feel free to add any relations to the model.
  4. Model will be marked as required to be kept as soon as model will be saved\updated for the first time after creation.

Known limitations:

  • Using this methodology you wouldn't have create form, only edit will be available.
  • Not all the models allows to have empty attributes on save. Such attributes could be set as nullable to allow create blank model.
  • To prevent spam of unkept models in database they could be deleted on a predetermined schedule (once a week for example).
<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasKeptFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasKeptFlag;
}

Your model is now can be marked to be kept!

Model must have boolean is_kept column in database table.

By default all records that have a is_kept equals to 0 will be excluded from your query results. To include unkept records, all you need to do is call the withUnkept() method on your query.

Available functions

Get only kept models

Post::all();
Post::withoutUnkept();

Get only unkept models

Post::onlyUnkept();

Get kept + unkept models

Post::withUnkept();

Keep model

Post::where('id', 4)->keep();

Unkeep model

Post::where('id', 4)->unkeep();

Get unkept models which older than hours

Post::onlyUnkeptOlderThanHours(4);

Output will have all unkept models created earlier than 4 hours ago.

Setup an expirable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Inverse\HasExpiredFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasExpiredFlag;
}

Model must have boolean is_expired column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasExpiredAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasExpiredAt;
}

Model must have nullable timestamp expired_at column in database table.

Available functions

Get only not expired models

Post::all();
Post::withoutExpired();

Get only expired models

Post::onlyExpired();

Get expired + not expired models

Post::withExpired();

Set expire flag to model

Post::where('id', 4)->expire();

Remove expire flag from model

Post::where('id', 4)->unexpire();

Setup a closable model

With boolean flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Inverse\HasClosedFlag;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasClosedFlag;
}

Model must have boolean is_closed column in database table.

With timestamp flag

<?php

namespace App\Models;

use Cog\Flag\Traits\Classic\HasClosedAt;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasClosedAt;
}

Model must have nullable timestamp closed_at column in database table.

Available functions

Get only not closed models

Post::all();
Post::withoutClosed();

Get only closed models

Post::onlyClosed();

Get closed + not closed models

Post::withClosed();

Set close flag to model

Post::where('id', 4)->close();

Remove close flag from model

Post::where('id', 4)->open();

Testing

Run the tests with:

vendor/bin/phpunit

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email a.komarev@cybercog.su instead of using the issue tracker.

Credits

Change log

Please see CHANGELOG for more information on what has changed recently.

Alternatives

Not found.

Feel free to add more alternatives as Pull Request.

License

About CyberCog

CyberCog is a Social Unity of enthusiasts. Research best solutions in product & software development is our passion.

cybercog-logo