2017 © Pedro Peláez
 

framework starter-framework

The Laravel / Lumen Starter Framework.

image

milkmeowo/starter-framework

The Laravel / Lumen Starter Framework.

  • Wednesday, March 29, 2017
  • by milkmeowo
  • Repository
  • 2 Watchers
  • 3 Stars
  • 68 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 1 Forks
  • 1 Open issues
  • 7 Versions
  • 5 % Grown

The README.md

starter-framework

Latest Stable Version Latest Unstable Version Total Downloads StyleCI Code Climate Scrutinizer Code Quality Build Status Analytics License, (*1)

Overview

This package is suitable for Restful API oriented projects, (*2)

The Restful APIs as a backend layer which provide simple unified interfaces for frontend: Web and Mobile apps., (*3)

It utilized Laravel Passport to authenticate protected resources., (*4)

It is fully utilised Repository Design pattern., (*5)

Features

  • Dingo Api Support
  • l5-Repository Support
  • Laravel Passport Support
  • ide-helper Support
  • clockwork support
  • Cors support
  • All of the above are supported for laravel & lumen

Getting started

Installation via Composer

composer require milkmeowo/starter-framework

Register the ServiceProvider

Register the starter-framework service provider by adding it to the providers array., (*6)

Laravel, (*7)

'providers' => array(
    ...
    Milkmeowo\Framework\Base\Providers\LaravelServiceProvider::class,
)

Lumen, (*8)

Modify the bootstrap flow (bootstrap/app.php file), (*9)

// Enable Facades
$app->withFacades();

// Enable Eloquent
$app->withEloquent();

$providers = [
    ...
    Milkmeowo\Framework\Base\Providers\LumenServiceProvider::class,
];

array_walk($providers, function ($provider) use ($app) {
    $app->register($provider);
});

Publish the configure

then copy config files into your project.you can finish this manually, (*10)

cp -R vendor/milkmeowo/starter-framework/config ./config

or for Laravel you can use, (*11)

php artisan vendor:publish

and change config/auth.php api guards driver to passport, (*12)

 'guards' => [
        ...
        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],

Migrate and install Laravel Passport

# Create new tables for Passport
php artisan migrate

# Install encryption keys and other necessary stuff for Passport
php artisan passport:install

Packages Documents

Dingo

, (*13)

improve, (*14)

Exception Handle Register, (*15)

add src/Framework/Dingo/Providers/ExceptionHandlerServiceProvider to register the common Exception handle, (*16)

  • Illuminate\Auth\Access\AuthorizationException
  • Illuminate\Auth\AuthenticationException
  • Illuminate\Database\Eloquent\ModelNotFoundException
  • Illuminate\Http\Exception\HttpResponseException
  • League\OAuth2\Server\Exception\OAuthServerException
  • Prettus\Validator\Exceptions\ValidatorException

ResponseWasMorphed Event Listener, (*17)

fire src/Framework/Dingo/Listeners/AddPaginationLinksToResponse, (*18)

Auth Providers, (*19)

add Passport and improved Oauth2 Auth Providers, (*20)

you can use with config, (*21)

// file config/api.php

...
    'auth' => [
        Milkmeowo\Framework\Dingo\Auth\Providers\OAuth2::class,
        Milkmeowo\Framework\Dingo\Auth\Providers\Passport::class,
    ],
...

reference:, (*22)

Dingo Api, (*23)

Dingo Api Wiki documentation, (*24)

dingo-api-wiki-zh., (*25)

l5-Repository

, (*26)

improve, (*27)

artisan command, (*28)

// example for generate Post Entity Repository
php artisan starter:entity Post

auto generate below files, (*29)

modified:   routes/api.php
modified:   app/Providers/RepositoryServiceProvider.php

     add:   app/Api/Controllers/V1/PostsController.php
     add:   app/Models/Post.php
     add:   app/Presenters/PostPresenter.php
     add:   app/Repositories/Criteria/PostCriteria.php
     add:   app/Repositories/Eloquent/PostRepositoryEloquent.php
     add:   app/Repositories/Interfaces/PostRepository.php
     add:   app/Transformers/PostTransformer.php
     add:   app/Validators/PostValidator.php
     add:   database/migrations/2017_01_12_091412_create_posts_table.php
     add:   database/seeds/PostSeeder.php
  • Controller(index store show update destory trashedIndex trashedShow restore)
  • Models(BaseModel with ObserveEvent auto track record modify with create(update/delete)_at(by/ip))
  • Presenter
  • Transformer(league/fractal)
  • Repositories/Criteria
  • Repositories/Eloquent(BaseEloquent with ObserverEvents,Cacheable,SoftDeletes Support)
  • Repositories/Interfaces
  • Validator(prettus/laravel-validator support)
  • migrations(new blueprint methods recordStamps[create(update)_at(by/ip)] softDeletesRecordStamps[delete_at(by/ip)])
  • Seeder
  • append Route(file routes/api.php(web.php) with placeholder //:end-routes: can auto-inject Restful api)
  • bind Repository Interface and Eloquent

Routes Endpoint, (*30)

files routes/api.php with placeholder //:end-routes:, (*31)

<?php

$api = app('Dingo\Api\Routing\Router');

// v1 version API
// choose version add this in header    Accept:application/vnd.lumen.v1+json
$api->version('v1', [
    'namespace' => 'App\Api\Controllers\V1',
], function ($api) {

    /*
    |------------------------------------------------
    | User Routes
    |------------------------------------------------
    */

    // trashed listing
    $api->get('/users/trashed', ['as' => 'users.trashed.index', 'uses' => 'UsersController@trashedIndex']);

    // show trashed special resource
    $api->get('/users/trashed/{id}', ['as' => 'users.trashed.show', 'uses' => 'UsersController@trashedShow']);

    // restore
    $api->put('/users/{id}/restore', ['as' => 'users.restore', 'uses' => 'UsersController@restore']);

    // listing
    $api->get('/users', ['as' => 'users.index', 'uses' => 'UsersController@index']);

    // create
    $api->post('/users', ['as' => 'users.store', 'uses' => 'UsersController@store']);

    // show
    $api->get('/users/{id}', ['as' => 'users.show', 'uses' => 'UsersController@show']);

    // update
    $api->put('/users/{id}', ['as' => 'users.update', 'uses' => 'UsersController@update']);

    // delete
    $api->delete('/users/{id}', ['as' => 'users.destroy', 'uses' => 'UsersController@destroy']);

    //:end-routes:
});
Verb URI Action Route Name
GET /users index users.index
GET /users/trashed trashedIndex users.trashed.index
POST /users store users.store
GET /users/{id} show users.show
GET /users/trashed/{id} trashedShow users.trashed.show
PUT /users/{id} update users.update
PUT /users/{id}/restore restore users.restore
DELETE /users/{id} destroy users.destroy

ObserveEvent, (*32)

Models and Repositories/Eloquent has listen below methods events with $priority = 99, (*33)

  • onCreating()
  • onCreated()
  • onUpdating()
  • onUpdated()
  • onSaving()
  • onSaved()
  • onDeleting()
  • onDeleted()
  • onRestoring()
  • onRestored()

Models also has default record track event listen, (*34)

fields default description
$autoRelatedUserId protect / true Indicates if the model should be auto set user_id.
$userstamps protect / true Indicates if the model should be recorded users.
$ipstamps protect / true Indicates if the model should be recorded ips.
RELATED_USER_ID const / 'user_id' The name of the "related user id" column.
CREATED_BY const / 'created_by' The name of the "created by" column.
UPDATED_BY const / 'updated_by' The name of the "updated by" column.
CREATED_IP const / 'created_ip' The name of the "created ip" column.
UPDATED_IP const / 'updated_ip' The name of the "updated ip" column.
DELETED_IP const / 'deleted_ip' The name of the "deleted ip" column.
DELETED_BY const / 'deleted_by' The name of the "deleted by" column.
  • onCreating()
    // auto set related user id
    if ($this->autoRelatedUserId && empty($this->{static::RELATED_USER_ID}) && $this->hasTableColumn(static::RELATED_USER_ID)) {
        $user_id = $this->getAuthUserId();
        if ($user_id > 0) {
            $this->{static::RELATED_USER_ID} = $user_id;
        }
    }
  • onSaving()
    // update ipstamps if true
    if ($this->ipstamps) {
        $this->updateIps();

    // update userstamps if true
    if ($this->userstamps) {
        $this->updateUsers();
    }

    protected function updateIps()
    {
        $ip = smart_get_client_ip();

        if (! $this->isDirty(static::UPDATED_IP) && $this->hasTableColumn(static::UPDATED_IP)) {
            $this->{static::UPDATED_IP} = $ip;
        }

        if (! $this->exists && ! $this->isDirty(static::CREATED_IP) && $this->hasTableColumn(static::CREATED_IP)) {
            $this->{static::CREATED_IP} = $ip;
        }
    }

    protected function updateUsers()
    {
        $user_id = $this->getAuthUserId();
        if (! ($user_id > 0)) {
            return;
        }

        if (! $this->isDirty(static::UPDATED_BY) && $this->hasTableColumn(static::UPDATED_BY)) {
            $this->{static::UPDATED_BY} = $user_id;
        }

        if (! $this->exists && ! $this->isDirty(static::CREATED_BY) && $this->hasTableColumn(static::CREATED_BY)) {
            $this->{static::CREATED_BY} = $user_id;
        }
    }
  • onDeleting()
    if (static::usingSoftDeletes()) {
        if ($this->hasTableColumn(static::DELETED_BY)) {
            $this->{static::DELETED_BY} = $this->getAuthUserId();
        }

        if ($this->hasTableColumn(static::DELETED_IP)) {
            $this->{static::DELETED_IP} = smart_get_client_ip();
        }

        $this->flushEventListeners();
        $this->save();
    }
  • onRestoring()
    if ($this->hasTableColumn(static::DELETED_BY)) {
        $this->{static::DELETED_BY} = null;
    }
    if ($this->hasTableColumn(static::DELETED_IP)) {
        $this->{static::DELETED_IP} = null;
    }

Repositories/Eloquent, (*35)

  • Cacheable, (*36)

  • SoftDeletes Support, (*37)

    • withTrashed
    • withoutTrashed
    • onlyTrashed
    • restore
    • restoreWhere
    • ForceDelete
    • forceDeleteWhere

reference:, (*38)

l5-repository, (*39)

l5-repository Usage, (*40)

prettus/laravel-validator, (*41)

league/fractal, (*42)

Laravel 的中大型專案架構., (*43)

Illuminate Database

improve, (*44)

  • support fulltext index
  • add a set of blueprint methods
    • add ipStamps(create_ip update_ip)
    • add userStamps(create_by update_by)
    • add recordStamps(timestamps ipStamps userStamps)
    • add softDeletesStamps(delete_ip delete_by)
    • add softDeletesRecordStamps(softDeletes softDeletesStamps)
    • add dropIpStamps
    • add dropUserStamps
    • add dropRecordStamps
    • add dropSoftDeletesStamps
    • add dropSoftDeletesRecordStamps
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();

            $table->recordStamps();

            $table->softDeletesRecordStamps();

            $table->text('content')->fulltext()
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('users');
    }
}

laravel passport

, (*45)

Laravel, (*46)

reference:, (*47)

Laravel Passport, (*48)

Official Documentation., (*49)

Lumen, (*50)

Installed routes, (*51)

Adding this service provider, will mount the following routes:, (*52)

Verb Path NamedRoute Controller Action Middleware
POST /oauth/token \Laravel\Passport\Http\Controllers\AccessTokenController issueToken -
GET /oauth/tokens \Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController forUser auth
DELETE /oauth/tokens/{token_id} \Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController destroy auth
POST /oauth/token/refresh \Laravel\Passport\Http\Controllers\TransientTokenController refresh auth
GET /oauth/clients \Laravel\Passport\Http\Controllers\ClientController forUser auth
POST /oauth/clients \Laravel\Passport\Http\Controllers\ClientController store auth
PUT /oauth/clients/{client_id} \Laravel\Passport\Http\Controllers\ClientController update auth
DELETE /oauth/clients/{client_id} \Laravel\Passport\Http\Controllers\ClientController destroy auth
GET /oauth/scopes \Laravel\Passport\Http\Controllers\ScopeController all auth
GET /oauth/personal-access-tokens \Laravel\Passport\Http\Controllers\PersonalAccessTokenController forUser auth
POST /oauth/personal-access-tokens \Laravel\Passport\Http\Controllers\PersonalAccessTokenController store auth
DELETE /oauth/personal-access-tokens/{token_id} \Laravel\Passport\Http\Controllers\PersonalAccessTokenController destroy auth

Please note that some of the Laravel Passport's routes had to 'go away' because they are web-related and rely on sessions (eg. authorise pages). Lumen is an API framework so only API-related routes are present., (*53)

reference:, (*54)

Lumen Passport, (*55)

Ide-helper

Register service provider when APP_ENV != production, (*56)

Automatic phpDoc generation for Laravel Facades, (*57)

php artisan ide-helper:generate

Automatic phpDocs for models, (*58)

php artisan ide-helper:models

PhpStorm Meta for Container instances, (*59)

php artisan ide-helper:meta

reference:, (*60)

IDE Helper Generator, (*61)

Clockwork

Register service provider when APP_DUBUG = true and APP_ENV != production, (*62)

reference:, (*63)

Clockwork, (*64)

Cors

Usage, (*65)

The ServiceProvider adds a route middleware you can use, called cors. You can apply this to a route or group to add CORS support., (*66)

Route::group(['middleware' => 'cors'], function(Router $router){
    $router->get('api', 'ApiController@index');
});

If you want CORS to apply for all your routes, add it as global middleware in app/http/Kernel.php:, (*67)

protected $middleware = [
    ....
    \Barryvdh\Cors\HandleCors::class
];

reference:, (*68)

barryvdh/laravel-cors, (*69)

License

The starter-framework is open-sourced software licensed under the MIT license., (*70)

The Versions