Laravel 5 全球 CRUD Class

Laravel 5 Global CRUD Class

在有人问之前,我已经研究了 CRUD 生成器并且我知道所有关于 Laravel 资源路由的信息,但这并不是我在这里的目的。

我想要做的是创建一个带有几个参数的路由,以及一个全局 class(uses/extends?)模型控制器用于简单的 CRUD 操作。我们有 20 个左右的模型,为每个 table 创建一个资源 Controller 比找到一种方法来创建全局 CRUD class 来处理所有“api" 类型调用和任何 ajax json 请求,如创建/更新/销毁语句。

所以我的问题是什么是构造一个 class 来处理我们所有 Model 的所有 CRUD 请求而无需资源 controllermodel?我已经尝试对此进行研究,但似乎找不到任何链接,除了指向 CRUD 生成器的链接和描述 laravel Resource route.

的链接

最简单的方法是执行以下操作:

  1. 为您的资源控制器添加路由:

    Route::resource('crud', 'CrudController', array('except' => array('create', 'edit')));
    
  2. 创建您的 crud 控制器

    <?php namespace App\Http\Controllers;
    
    use Illuminate\Routing\Controller;
    use App\Models\User;
    use App\Models\Product;
    use Input;
    
    class CrudController extends Controller
    {
        const MODEL_KEY = 'model';
    
        protected $modelsMapping = [
            'user' => User::class,
            'product' => Product::class
        ];
    
        protected function getModel() {
            $modelKey = Input::get(static::MODEL_KEY);
            if (array_key_exists($modelKey, $this->modelsMapping)) {
                return $this->modelsMapping[$modelKey];
            }
    
            throw new \InvalidArgumentException('Invalid model');
        }
    
        public function index()
        {
            $model = $this->getModel();
            return $model::all();
        }
    
        public function store()
        {
            $model = $this->getModel();
            return $model::create(array_except(Input::all(), static::MODEL_KEY));
        }
    
        public function show($id)
        {
            $model = $this->getModel();
            return $model::findOrFail($id);
        }
    
        public function update($id)
        {
            $model = $this->getModel();
            $object = $model::findOrFail($id);
            return $object->update(array_except(Input::all(), static::MODEL_KEY));
        }
    
        public function destroy($id)
        {
            $model = $this->getModel();
            return $model::remove($id);
        }
    }
    
  3. 使用您的新控制器 :) 您必须传递 model 参数,该参数将包含模型密钥 - 它必须是允许的模型之一白名单。例如。如果你想获得 User with id=5 do

    GET /crud/5?model=user
    

请记住它越简单越好,您可能需要使代码更复杂以满足您的需要。

另请记住,此代码尚未经过测试 - 如果您发现任何拼写错误或有其他问题,请告诉我。我很乐意为你拿到它 运行。

您需要一个通用的 class 来执行所有 CRUD 操作,有很多方法可以实现这一点,一个规则可能不适合所有操作,但您可以尝试我将要采用的方法现在描述。这是一个抽象的想法,你需要去实现它,所以一开始,想到所有CRUD操作的URI。在这种情况下,您必须遵循约定,它可能是这样的:

example.com/user/{id?} // get all or one by id (if id is available in the URI)
example.com/user/create // Show an empty form
example.com/user/edit/10 // Show a form populated with User model
example.com/user/save // Create a new User
example.com/user/save/10 // Update an existing User
example.com/user/delete/10 // Delete an existing User

在这种情况下,user 可能是其他用于指定模型名称的东西,例如 example.com/product/create 并记住这一点,您需要按如下所示声明路由:

Route::get('/{model}/{id?}', 'CrudController@read');
Route::get('/{model}/create', 'CrudController@create');
Route::get('/{model}/edit/{id}', 'CrudController@edit');
Route::post('/{model}/save/{id?}', 'CrudController@save');
Route::post('/{model}/delete/{id}', 'CrudController@delete');

现在,在您的 app\Providers\RouteServiceProvider.php 文件中修改 boot 方法并使其看起来像这样:

public function boot(Router $router)
{
    $model = null;

    $router->bind('model', function($modelName) use (&$model, &$router)
    {
        $model = app('\App\User\'.ucfirst($modelName));

        if($model)
        {
            if($id = $router->input('id'))
            {
                $model = $model->find($id);
            }

            return $model ?: abort(404);
        }
    });

    parent::boot($router);
}

然后声明您的 CrudController,如下所示:

class CrudController extends Controller
{
    protected $request = null;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function read($model)
    {
        return $model->exists ? $model : $model->all();
    }

    // Show either an empty form or a form
    // populated with the given model atts
    public function createOrEdit($model)
    {
        $classNameArray = explode('\', get_class($model));

        $className = strtolower(array_pop($classNameArray));

        $view = view($className . '.form');

        $view->formAction = "$className/save";

        if(is_object($model) && $model->exists)
        {
            $view->model = $model;

            $view->formAction .= "/{$model->id}";
        }

        return $view;
    }

    public function save($model)
    {
        // Validation required so do it
        // Make sure each Model has $fillable specified
        return $this->model->fill($this->request)->save();
    }

    public function delete($model)
    {
        return $this->model->delete();
    }
}

由于相同的表单用于创建和更新模型,因此使用类似这样的方式创建表单:

<form action="{{url($formAction)}}" method="POST">

    <input
    type="text"
    class="form-control"
    name="first_name" value="{{old('first_name', @$model->first_name)}}"
    />
    <input type="Submit" value="Submit" />
    {!!csrf_field()!!}

 </form>

请记住,每个表格都应该在与模型对应的目录中,对于用户 add/edit,表格应该在 views/user/form.blade.php 中,对于产品模型使用 views/product/form.blade.php 等等.

这会起作用,并且不要忘记在保存模型之前添加验证,并且可以使用模型事件或您想要的任何方式在模型内部完成验证。这只是一个想法,但可能不是最好的方法。

除非你想手动实现CRUD,否则考虑集成一个现成的datagrid,比如phpGrid

查看集成演练:http://phpgrid.com/example/phpgrid-laravel-5-twitter-bootstrap-3-integration/不需要模型,代码最少。它几乎无所不能。

一个基本的工作 CRUD:

// in a controller
public function index()
{
    $dg = new \C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
    $dg->enable_edit("FORM", "CRUD");
    $dg->display(false);

    $grid = $dg -> get_display(true); 

    return view('dashboard', ['grid' => $grid]);
}