laravel5.5 __Resource路由__RESTFul风格控制器

一、背景描述

经常我们在写某一个功能模块时,要用到的功能无非就是增删改查,如果按照基础的实现方式,我们会发现,做一个模块功能时,获取文件列表,需要写一个路由,打开编辑页面,需要一个路由,甚至删除某条数据,仍然需要一个路由,这种重复工作,让人会觉得很难受。而且如果每一个页面或者功能都去写一个路由的话,路由文件也会显得特别冗杂,重复性也很大。

我们希望代码美观且简洁,如果只写一个路由,然后根据请求方式(GET/PUT/POST/DELETE等)或者是否传参来判断访问的是哪个方法,这样一个功能模块,只需要一个路由就可以解决了。刚好,Laravel不愧是美誉盛传的PHP框架,刚好就有这样一个路由机制,Resource。大部分情况下,一个模块只需要在路由文件中定义一个resource路由,就可以实现对整个模块的请求。

下面,我们实操完成一个文章模块。

二、Resouce路由使用步骤

1. 注册资源路由

// 普通注册
Route::resource('article', 'ArticleController');

// 限制指定路由
Route::resource('article', 'ArticleController', ['only' => [
    'index', 'show', 'store', 'update', 'destroy'
]]);

 注意

(1)我这里是在做后台的文章模块,所以在Controllers下新建了一个Admin文件夹,所以新建后台的文章模块控制器需要加一个文件夹 “ Admin ” 。

(2)当前这个路由文件是一个自定义的admin.php路由文件,直接路由到 “/Controllers/Admin/” 文件夹下的。如何在Laravel中自定义路由文件,参考我的另一篇博文:Laravel5.5添加新路由文件并制定规则

(3)resource路由包含多个子路由,具体参考下表:

方法 路径 动作 路由名称
GET /article index article.index
GET /article/create create article.create
POST /article store article.store
GET /article/{id} show article.show
GET /article/{id}/edit edit article.edit
PUT/PATCH /article/{id} update article.update
DELETE /article/{id} destroy article.destroy

2. 跳转到项目根目录(windows进入dos系统),创建控制器:

php artisan make:controller Admin\ArticleController

3. 填充控制器对应Resource指定方法

<?php
namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class ArticleController extends Controller
{
    /**
     * 显示文章列表.
     *
     * @return Response
     */
    public function index()
    {
        //
    }

    /**
     * 创建新文章表单页面
     *
     * @return Response
     */
    public function create()
    {
        //
    }

    /**
     * 将新创建的文章存储到存储器
     *
     * @param Request $request
     * @return Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * 显示指定文章
     *
     * @param int $id
     * @return Response
     */
    public function show($id)
    {
        //
    }

    /**
     * 显示编辑指定文章的表单页面
     *
     * @param int $id
     * @return Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * 在存储器中更新指定文章
     *
     * @param Request $request
     * @param int $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * 从存储器中移除指定文章
     *
     * @param int $id
     * @return Response
     */
    public function destroy($id)
    {
        //
    }
}

注意:这几个方法不是自己随便定义的,是Resource路由规则规定好的,所以不要随便改变喔。

4. 创建文章数据库模型 及 迁移文件

php artisan make:model Models\Article -m

注意:我把数据库模型文件全部放进app/Models/目录下的,这个目录是自己创建的。

5. 填充迁移文件,设置数据库结构,并执行迁移创建articles数据库

(1) 填充迁移文件

<?php

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

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('category_id')->comment('文章类别id')->default(0);
            $table->string('category_name',20)->comment('文章类别名称')->default('其他');
            $table->string('title',100)->comment('文章标题');
            $table->string('author',30)->comment('文章作者')->default('未知作者');
            $table->string('descr',255)->comment('文章简介')->nullable();
            $table->string('image',255)->comment('文章导图');
            $table->text('content')->comment('文章内容');
            $table->unsignedTinyInteger('status')->comment('文章状态,1-草稿;2-发表')->default(1);
            $table->unsignedInteger('click_count')->comment('文章点击数量')->default(0);
            $table->unsignedTinyInteger('top_status')->comment('置顶状态,0-普通 1-置顶')->default(0);
            $table->unsignedInteger('top_time')->comment('置顶时间')->default(0);
            $table->timestamps();
        });
    }

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

(2)跳转到项目根目录(windows打开dos系统),执行迁移,创建articles数据库

php artisan migrate

Laravel迁移相关知识点可以参考博文:laravel5.5数据库迁移入门实践 

6. 配置Article.php数据库模型文件

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    protected $fillable = ['category_id', 'category_name', 'title', 'author', 'descr', 'image', 'content', 'status', 'click_count', 'top_status', 'top_time'];
}

7. 数据库批量填充测试数据

(1)跳转到项目根目录(windows进入dos系统),创建seeder文件

php artisan make:seed ArticlesTableSeeder

(2)工厂生成数据,操作文件\database\factories\ModelFactory.php

<?php
 
use Faker\Generator as Faker;
 
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/
$factory->define(\App\Models\Article::class, function (\Faker\Generator $faker) {

    $arr = [1=>'php', 2=>'mysql', 3=>'linux', 4=>'laravel'];
    $k = mt_rand(1,4);
    $category = [ $k,$arr[$k] ]; 

    return [
        'category_id'   =>  $category[0],
        'category_name' =>  $category[1],
        'title'         =>  $faker->title,
        'author'        =>  $faker->name,
        'descr'         =>  $faker->text,
        'image'         =>  $faker->imageUrl(),
        'content'       =>  $faker->text,
        'status'        =>  mt_rand(1,2),
        'click_count'   =>  $faker->numberBetween(100,3000),
        'top_status'    =>  mt_rand(0,1),
        'top_time'      =>  time()
    ];
});

(3)填充\database\seeds\ArticlesSeeder.php文件的run方法

<?php

use Illuminate\Database\Seeder;

class ArticlesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // 创建10条测试数据
        $articles = factory(\App\Models\Article::class,10)->make(); 

        \App\Models\Article::insert( $articles->toArray() );
    }
}

(4)添加ArticlesSeeder文件到\database\seeds\DatabaseSeeder.php中

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(ArticlesTableSeeder::class);
    }
}

laravel填充数据相关知识可以参考博文:laravel5.5数据库之数据填充(实践)

8. 完成ArticleController.php控制器的业务逻辑方法

<?php
namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Admin\BaseController;
use App\Repositories\ArticleRepository;

class ArticleController extends BaseController
{

    protected $article;

    public function __construct(ArticleRepository $article)
    {
        $this->article = $article;
    }

    /**
     * 显示文章列表.
     *
     * @return Response
     */
    public function index(Request $request)
    {
        // 默认获取已发表文章
        $status = $request->input('status') == 2 ? 2 : 1;

        $list = $this->article->paginate(10, ['status'=>$status]);

        return view('admin.article.index', compact('list','status'));
    }

    /**
     * 创建新文章表单页面
     *
     * @return Response
     */
    public function create()
    {
        $cate = [1=>'php', 2=>'mysql', 3=>'linux', 4=>'laravel'];

        return view('admin.article.create',compact('cate'));
    }

    /**
     * 将新创建的文章存储到存储器
     *
     * @param Request $request
     * @return Response
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'category_id'   =>  'required',
            'title'         =>  'required',
            'author'        =>  'required',
            'image'         =>  'required',
            'status'        =>  'required',
            'click_count'   =>  'required',
            'descr'         =>  'nullable',
            'content'       =>  'required'
        ]);

        $cate = [1=>'php', 2=>'mysql', 3=>'linux', 4=>'laravel'];

        $data['category_name'] = $cate[ $data['category_id'] ];

        $re = $this->article->create($data);

        return redirect()->route('article.index');
    }

    /**
     * 显示指定文章
     *
     * @param int $id
     * @return Response
     */
    public function show($id)
    {
        $article = $this->article->find($id);

        return view('admin.article.show', compact('article'));
    }

    /**
     * 显示编辑指定文章的表单页面
     *
     * @param int $id
     * @return Response
     */
    public function edit($id)
    {
        $cate = [1=>'php', 2=>'mysql', 3=>'linux', 4=>'laravel'];

        $article = $this->article->find($id);

        return view('admin.article.edit', compact('article', 'cate'));
    }

    /**
     * 在存储器中更新指定文章
     *
     * @param Request $request
     * @param int $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $data = $request->validate([
            'status' => 'required'
        ]);

        return $this->article->update($data, $id, "id");
    }

    /**
     * 从存储器中移除指定文章
     *
     * @param int $id
     * @return Response
     */
    public function destroy($id)
    {
        return $this->article->delete($id);
    }
}

注意:因为我封装了一层用来解耦的数据库操作层,所以没有直接操作数据库模型,仅供参考哈。

三、界面展示

终于写完了,我的模版文件就不展示了,看几张效果图:

四、补充

  如果需要额外再添加其他方法,可以 在资源路由前面 定义方法,如:

// 注意:一定要放在resource资源路由上面哈
Route::post('test', 'ArticleController@test');

Route::resource('article', 'ArticleController');

如果还有疑问,欢迎留言讨论哈! 

猜你喜欢

转载自blog.csdn.net/createNo_1/article/details/81738665