3. 开始
Govern Fu edited this page May 24, 2019
·
15 revisions
默认情况下,模块类不会自动加载。您可以使用自动加载模块 psr-4
。例如:
{
"autoload": {
"psr-4": {
"App\\": "app/",
"Modules\\": "modules/"
}
}
}
提示:不要忘记 composer dump-autoload
之后运行。
code phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Feature">
<directory suffix="Test.php">./modules/**/Tests/</directory>
</testsuite>
<testsuite name="Unit">
<directory suffix="Test.php">./modules/**/Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="false">
<directory suffix=".php">./modules</directory>
<exclude>
<directory suffix=".php">./modules/**/Routes</directory>
<directory suffix=".php">./modules/**/Resources</directory>
<directory suffix=".php">./modules/**/Tests</directory>
<directory suffix=".php">./modules/**/Config</directory>
</exclude>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
</php>
</phpunit>
php artisan module:update
php artisan module:make Demo
php artisan module:make-model Example -m Example
你也可以将其分开创建
php artisan module:make-model Example Example
php artisan module:make-migration create_examples_table Example
php artisan module:make-seed ExampleTableSeeder Example
php artisan module:make-repository ExampleRepository -pr Example
你也可以将其分开创建
php artisan module:make-repository ExampleRepository Example
php artisan module:make-presenter ExamplePresenter Example
php artisan module:make-resource ExampleTransformer Example
php artisan module:make-service ExampleService Example
php artisan module:make-api ExampleController Example
php artisan module:make-request ExampleStoreRequest Example
php artisan module:make-request ExampleUpdateRequest Example
php artisan module:make-test ExampleTest Example
通过迁移文件在数据库中添加数据字段:
code modules/Example/Database/Migrations/*_create_examples_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateExamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('examples', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique()->comment('键名');
$table->string('value')->comment('键值');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('examples');
}
}
php artisan module:migrate
在模型文件中添加可填充字段:
code modules/Example/Entities/Example.php
<?php
namespace Modules\Example\Entities;
use Illuminate\Database\Eloquent\Model;
use Modules\Core\Traits\CamelMutatorTrait;
class Example extends Model
{
use CamelMutatorTrait;
protected $fillable = [
'name',
'value',
];
}
通过填充文件在数据库中添加数据:
code modules/Example/Database/Seeders/ExampleTableSeederTableSeeder.php
<?php
namespace Modules\Example\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use Modules\Example\Entities\Example;
class ExampleTableSeederTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Example::truncate();
Example::create([
'name' => 'demo',
'value' => 'hello world',
]);
}
}
code modules/Demo/Database/Seeders/DemoDatabaseSeeder.php
<?php
namespace Modules\Example\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class ExampleDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
$this->call(ExampleTableSeederTableSeeder::class);
}
}
php artisan module:seed
在转化器中添加输出字段转化:
code modules/Example/Transformers/ExampleTransformer.php
<?php
namespace Modules\Example\Transformers;
use Modules\Core\Abstracts\TransformerAbstract;
/**
* Class ExampleTransformer
*
* @package Modules\Example\Transformers
*/
class ExampleTransformer extends TransformerAbstract
{
/**
* Transform the Example entity.
*
* @param \Modules\Example\Entities\Example $attribute
*
* @return array
*/
public function fields($attribute)
{
return [
'id' => (int) $attribute->id,
'name' => (string) $attribute->name,
'value' => (string) $attribute->value
];
}
}
在仓库实现中定义可搜索字段:
code modules/Example/Repositories/ExampleRepositoryEloquent.php
<?php
namespace Modules\Example\Repositories;
use Modules\Example\Entities\Example;
use Modules\Example\Presenters\ExamplePresenter;
use Prettus\Repository\Eloquent\BaseRepository;
class ExampleRepositoryEloquent extends BaseRepository implements ExampleRepository
{
protected $fieldSearchable = [
'name' => 'like',
];
/**
* Specify Model
*
* @return string
*/
public function model()
{
return Example::class;
}
/**
* Specify Presenter
*
* @return mixed
*/
public function presenter()
{
return ExamplePresenter::class;
}
}
在请求条件中定义可请求字段:
code modules/Example/Http/Requests/ExampleStoreRequest.php
<?php
namespace Modules\Example\Http\Requests;
use Modules\Core\Http\Requests\Request;
class ExampleStoreRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|unique:examples',
'value' => 'required',
];
}
}
code modules/Example/Http/Requests/ExampleUpdateRequest.php
<?php
namespace Modules\Example\Http\Requests;
use Modules\Core\Http\Requests\Request;
class ExampleUpdateRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'value' => 'required',
];
}
}
code modules/Example/Services/ExampleService.php
<?php
namespace Modules\Example\Services;
use Modules\Core\Supports\Response;
interface ExampleService
{
public function index(): Response;
public function store(array $attributes): Response;
public function show(int $id): Response;
public function update(int $id, array $attributes): Response;
public function destroy(int $id): Response;
}
code modules/Example/Services/ExampleServiceI.php
<?php
namespace Modules\Example\Services;
use Modules\Core\Supports\Response;
use Modules\Example\Repositories\ExampleRepository;
class ExampleServiceI implements ExampleService
{
/**
* @var \Modules\Example\Repositories\ExampleRepository
*/
private $exampleRepository;
public function __construct(ExampleRepository $dataRepository)
{
$this->exampleRepository = $dataRepository;
}
public function index(): Response
{
return Response::handleOk($this->exampleRepository->all());
}
public function store(array $attributes): Response
{
return Response::handleCreated($this->exampleRepository->create($attributes));
}
public function show(int $id): Response
{
return Response::handleOk($this->exampleRepository->find($id));
}
public function update(int $id, array $attributes): Response
{
return Response::handleResetContent($this->exampleRepository->update($attributes, $id));
}
public function destroy(int $id): Response
{
return Response::handleNoContent($this->exampleRepository->delete($id));
}
}
code modules/Example/Http/Controllers/Api/V1/ExampleController.php
<?php
namespace Modules\Example\Http\Controllers\Api\V1;
use Modules\Core\Supports\Response;
use Modules\Core\Supports\ResponsibilityChain;
use Modules\Example\Http\Requests\ExampleStoreRequest;
use Modules\Example\Http\Requests\ExampleUpdateRequest;
use Modules\Example\Services\ExampleService;
interface ExampleController
{
public function index(ResponsibilityChain $responsibilityChain, ExampleService $exampleService): Response;
public function store(
ResponsibilityChain $responsibilityChain,
ExampleService $exampleService,
ExampleStoreRequest $exampleStoreRequest
): Response;
public function show(ResponsibilityChain $responsibilityChain, ExampleService $exampleService, int $id): Response;
public function update(
ResponsibilityChain $responsibilityChain,
ExampleService $exampleService,
int $id,
ExampleUpdateRequest $exampleUpdateRequest
): Response;
public function destroy(
ResponsibilityChain $responsibilityChain,
ExampleService $exampleService,
int $id
): Response;
}
code modules/Example/Http/Controllers/Api/V1/ExampleControllerI.php
<?php
namespace Modules\Example\Http\Controllers\Api\V1;
use Illuminate\Routing\Controller;
use Modules\Core\Supports\Response;
use Modules\Core\Supports\ResponsibilityChain;
use Modules\Example\Http\Requests\ExampleStoreRequest;
use Modules\Example\Http\Requests\ExampleUpdateRequest;
use Modules\Example\Services\ExampleService;
class ExampleControllerI extends Controller implements ExampleController
{
public function index(ResponsibilityChain $responsibilityChain, ExampleService $exampleService): Response
{
$step1 = function () use ($exampleService) {
return $exampleService->index();
};
return $responsibilityChain->append($step1)->handle();
}
public function store(
ResponsibilityChain $responsibilityChain,
ExampleService $exampleService,
ExampleStoreRequest $exampleStoreRequest
): Response {
$attributes = $exampleStoreRequest->validated();
$step1 = function () use ($exampleService, $attributes) {
return $exampleService->store($attributes);
};
return $responsibilityChain->append($step1)->handle();
}
public function show(ResponsibilityChain $responsibilityChain, ExampleService $exampleService, int $id): Response
{
$step1 = function () use ($exampleService, $id) {
return $exampleService->show($id);
};
return $responsibilityChain->append($step1)->handle();
}
public function update(
ResponsibilityChain $responsibilityChain,
ExampleService $exampleService,
int $id,
ExampleUpdateRequest $exampleUpdateRequest
): Response {
$attributes = $exampleUpdateRequest->validated();
$step1 = function () use ($exampleService, $id, $attributes) {
return $exampleService->update($id, $attributes);
};
return $responsibilityChain->append($step1)->handle();
}
public function destroy(ResponsibilityChain $responsibilityChain, ExampleService $exampleService, int $id): Response
{
$step1 = function () use ($exampleService, $id) {
return $exampleService->destroy($id);
};
return $responsibilityChain->append($step1)->handle();
}
}
code modules/Example/Routes/api.php
<?php
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::get('/example', 'ExampleController@index');
Route::group(['prefix' => 'v1', 'namespace' => 'Api\V1'], function () {
Route::group(['prefix' => 'examples'], function () {
Route::get('/', 'ExampleController@index');
Route::post('/', 'ExampleController@store');
Route::get('/{id}', 'ExampleController@show')->where('id', '\d+');
Route::put('/{id}', 'ExampleController@update')->where('id', '\d+');
Route::delete('/{id}', 'ExampleController@destroy')->where('id', '\d+');
});
});
code modules/Example/Tests/ExampleTest.php
<?php
namespace Modules\Example\Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Support\Str;
use Modules\Core\Enums\StatusCodeEnum;
use Modules\Example\Database\Seeders\ExampleTableSeederTableSeeder;
use Illuminate\Foundation\Testing\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
private $baseUri = 'api/v1/';
private $resource = 'examples';
private $uri;
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../../../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
return $app;
}
public function __construct()
{
$this->uri = $this->baseUri.Str::plural($this->resource);
parent::__construct();
}
public function testIndex()
{
$this->get("{$this->uri}")->assertStatus(StatusCodeEnum::HTTP_OK);
}
public function testStore()
{
$this->post("{$this->uri}", ['name' => 'demo', 'value' => 'hello world'])
->assertStatus(StatusCodeEnum::HTTP_CREATED);
}
public function testShow()
{
$this->seed(ExampleTableSeederTableSeeder::class);
$this->get("{$this->uri}/1")->assertStatus(StatusCodeEnum::HTTP_OK);
}
public function testUpdate()
{
$this->seed(ExampleTableSeederTableSeeder::class);
$this->put("{$this->uri}/1", ['value' => 'Hello World'])->assertStatus(StatusCodeEnum::HTTP_RESET_CONTENT);
}
public function testDestroy()
{
$this->seed(ExampleTableSeederTableSeeder::class);
$this->delete("{$this->uri}/1")->assertStatus(StatusCodeEnum::HTTP_NO_CONTENT);
}
}
./vendor/bin/phpunit
PHPUnit 7.5.11 by Sebastian Bergmann and contributors.
..... 5 / 5 (100%)
Time: 683 ms, Memory: 26.00 MB
OK (5 tests, 5 assertions)