-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


. GridView Yii 2 Laravel

, 31 2017 . 16:00 +
Yii, Yii , GridView ActiveForm, Laravel. , .
composer create-project laravel/laravel
...
composer require yiisoft/yii2


, . , . Laravel.





https://github.com/view-components/grids
https://github.com/assurrussa/grid-view-table
https://github.com/dwightwatson/bootstrap-form
https://github.com/core-system/bootstrap-form
https://github.com/adamwathan/bootforms
https://github.com/zofe/rapyd-laravel

:
Bootstrap
, ,
,


https://github.com/view-components/grids

, . . . , , .

https://github.com/assurrussa/grid-view-table

, , - .

https://github.com/dwightwatson/bootstrap-form

action, . , .

. F5 , , .

https://github.com/core-system/bootstrap-form

, / .

https://github.com/core-system/bootstrap-form

-, ActiveForm. .

https://github.com/zofe/rapyd-laravel

. , . , .
view/create/edit , get-. URL .
, . , created_at/updated_at view. 3 .




, . , .

, laravel 2.6 , symfony 4.6 , yiisoft 3.9 , Yii 5.6 .

.

SQL
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `email` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL,
  `remember_token` varchar(100) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `orders` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `orders-users` (`user_id`),
  CONSTRAINT `orders-users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `order_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` int(10) unsigned NOT NULL,
  `product_id` int(10) unsigned NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `order_items-orders` (`order_id`),
  KEY `order_items-products` (`product_id`),
  CONSTRAINT `order_items-orders` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `order_items-products` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB;



Eloquent OrderController . .
routes/web.php
Route::group(['prefix' => 'admin', 'as' => 'admin.', 'namespace' => 'Admin'], function () {
    Route::get('/order', 'OrderController@index')->name('order.index');
    Route::get('/order/view/{id}', 'OrderController@view')->name('order.view');
    Route::get('/order/create', 'OrderController@create')->name('order.create');
    Route::get('/order/update/{id}', 'OrderController@update')->name('order.update');
    Route::post('/order/create', 'OrderController@create');
    Route::post('/order/update/{id}', 'OrderController@update');
    Route::post('/order/delete/{id}', 'OrderController@delete')->name('order.delete');
});


Bootstrap- CDN.

resources/views/layouts/main.blade.php


    
        
        
        

        

        

        

        
        
        

        
    
    

        @include('layouts.nav')

        
@yield('content')



middleware .
.
routes/web.php
$initYii2Middleware = function ($request, $next)
{
    define('YII_DEBUG', env('APP_DEBUG'));
    include '../vendor/yiisoft/yii2/Yii.php';
    spl_autoload_unregister(['Yii', 'autoload']);
    $config = [
        'id' => 'yii2-laravel',
        'basePath' => '../',
        'timezone' => 'UTC',
        'components' => [
            'assetManager' => [
                'basePath' => '@webroot/yii-assets',
                'baseUrl' => '@web/yii-assets',

                'bundles' => [
                    'yii\web\JqueryAsset' => [
                        'sourcePath' => null,
                        'basePath' => null,
                        'baseUrl' => null,
                        'js' => [],
                    ],
                ],
            ],
            'request' => [
                'class' => \App\Yii\Web\Request::class,
                'csrfParam' => '_token',
            ],
            'urlManager' => [
                'enablePrettyUrl' => true,
                'showScriptName' => false,
            ],
            'formatter' => [
                'dateFormat' => 'php:m/d/Y',
                'datetimeFormat' => 'php:m/d/Y H:i:s',
                'timeFormat' => 'php:H:i:s',
                'defaultTimeZone' => 'UTC',
            ],
        ],
    ];
    (new \yii\web\Application($config));  // initialization is in constructor
    Yii::setAlias('@bower', Yii::getAlias('@vendor') . DIRECTORY_SEPARATOR . 'bower-asset');

    return $next($request);
};

Route::group(['prefix' => 'admin', 'as' => 'admin.', 'namespace' => 'Admin', 'middleware' => $initYii2Middleware], function () {
    ...
});


spl_autoload_unregister(['Yii', 'autoload']); , , Laravel. getAlias('@'...) .
basePath , . runtime.
assetManager.basePath, assetManager.baseUrl URL , .
assetManager.bundles jQuery, .
request , CSRF-, Laravel.
urlManager.enablePrettyUrl , Gii.
(new \yii\web\Application($config)) Yii::$app = $this;

:
app/Yii/Web/Request.php
namespace App\Yii\Web;

class Request extends \yii\web\Request
{
    public function getCsrfToken($regenerate = false)
    {
        return \Session::token();
    }
}

Laravel, .



. .

app/Http/Controllers/Admin/OrderController.php
public function index(Request $request)
{
    $allModels = Order::query()->get()->all();
    $gridViewConfig = [
        'dataProvider' => new \yii\data\ArrayDataProvider([
            'allModels' => $allModels,
            'pagination' => ['route' => $request->route()->uri(), 'defaultPageSize' => 10],
            'sort' => ['route' => $request->route()->uri(), 'attributes' => ['id']],
        ]),
        'columns' => [
            'id',
            'user.name',
            ['label' => 'Items', 'format' => 'raw', 'value' => function ($model) {
                $html = '';
                foreach ($model->items as $item) {
                    $html .= '
' . htmlspecialchars($item->product->name) . '
'; } return $html; }], 'created_at:datetime', 'updated_at:datetime', [ 'class' => \yii\grid\ActionColumn::class, 'urlCreator' => function ($action, $model, $key) use ($request) { $baseRoute = $request->route()->getName(); $baseRouteParts = explode('.', $baseRoute); $baseRouteParts[count($baseRouteParts) - 1] = $action; $route = implode('.', $baseRouteParts); $params = is_array($key) ? $key : ['id' => (string) $key]; return route($route, $params, false); } ], ], ]; return view('admin.order.index', ['gridViewConfig' => $gridViewConfig]); }


resources/views/admin/order/index.blade.php
@extends('layouts.main')

@section('title', 'Index')

@section('content')

    

Orders

{!! \yii\grid\GridView::widget($gridViewConfig) !!} @endsection



dataProvider.pagination.route dataProvider.sort.route, Yii::$app->controller->getRoute(), null. ActionColumn, InvalidParamException. URL \yii\web\UrlManager, , Laravel. dataProvider.pagination.urlManager, .
.
.

, -, Delete .

, \yii\web\View. renderHeadHtml(), renderBodyBeginHtml(), renderBodyEndHtml() ( , , public). , public morozov. .
app/Yii/Web/View.php
namespace App\Yii\Web;

class View extends \yii\web\View
{
    public function getHeadHtml()
    {
        return parent::renderHeadHtml();
    }

    public function getBodyBeginHtml()
    {
        return parent::renderBodyBeginHtml();
    }

    public function getBodyEndHtml($ajaxMode = false)
    {
        return parent::renderBodyEndHtml($ajaxMode);
    }

    public function initAssets()
    {
        \yii\web\YiiAsset::register($this);

        ob_start();

        $this->beginBody();
        $this->endBody();

        ob_get_clean();
    }
}


Yii endBody(), , CDATA . initAssets(). , $this->js, $this->css .

routes/web.php
'components' => [
    ...
    'view' => [
        'class' => \App\Yii\Web\View::class,
    ],
],



resources/views/admin/order/index.blade.php


    
        ...

        
        {!! \yii\helpers\Html::csrfMetaTags() !!}
        {!! $view->getHeadHtml() !!}
    
    
        {!! $view->getBodyBeginHtml() !!}

        ...

        {!! $view->getBodyEndHtml() !!}
    



Html::csrfMetaTags() , yii.js csrf- HTML .

ArrayDataProvider , ActiveDataProvider, .
app/Yii/Data/EloquentDataProvider.php
class EloquentDataProvider extends \yii\data\BaseDataProvider
{
    public $query;

    public $key;

    protected function prepareModels()
    {
        $query = clone $this->query;

        if (($pagination = $this->getPagination()) !== false) {
            $pagination->totalCount = $this->getTotalCount();
            if ($pagination->totalCount === 0) {
                return [];
            }
            $query->limit($pagination->getLimit())->offset($pagination->getOffset());
        }

        if (($sort = $this->getSort()) !== false) {
            $this->addOrderBy($query, $sort->getOrders());
        }

        return $query->get()->all();
    }

    protected function prepareKeys($models)
    {
        $keys = [];
        if ($this->key !== null) {
            foreach ($models as $model) {
                $keys[] = $model[$this->key];
            }

            return $keys;
        } else {
            $pks = $this->query->getModel()->getKeyName();

            if (is_string($pks)) {
                $pk = $pks;
                foreach ($models as $model) {
                    $keys[] = $model[$pk];
                }
            } else {
                foreach ($models as $model) {
                    $kk = [];
                    foreach ($pks as $pk) {
                        $kk[$pk] = $model[$pk];
                    }
                    $keys[] = $kk;
                }
            }

            return $keys;
        }
    }

    protected function prepareTotalCount()
    {
        $query = clone $this->query;
        $query->orders = null;
        $query->offset = null;

        return (int) $query->limit(-1)->count('*');
    }

    protected function addOrderBy($query, $orders)
    {
        foreach ($orders as $attribute => $order) {
            if ($order === SORT_ASC) {
                $query->orderBy($attribute, 'asc');
            } else {
                $query->orderBy($attribute, 'desc');
            }
        }
    }
}

app/Http/Controllers/Admin/OrderController.php
    'dataProvider' => new \App\Yii\Data\EloquentDataProvider([
        'query' => Order::query(),
        'pagination' => ['route' => $request->route()->uri(), 'defaultPageSize' => 10],
        'sort' => ['route' => $request->route()->uri(), 'attributes' => ['id']],
    ]),




.



, \yii\base\Model, . filterModel. .

app/Yii/Data/FilterModel.php
namespace App\Yii\Data;

use App\Yii\Data\EloquentDataProvider;
use Route;

class FilterModel extends \yii\base\Model
{
    protected $labels;
    protected $rules;
    protected $attributes;


    public function __construct($labels = [], $rules = [])
    {
        parent::__construct();

        $this->labels = $labels;
        $this->rules = $rules;

        $safeAttributes = $this->safeAttributes();
        $this->attributes = array_combine($safeAttributes, array_fill(0, count($safeAttributes), null));
    }

    public function __get($name)
    {
        if (array_key_exists($name, $this->attributes)) {
            return $this->attributes[$name];
        } else {
            return parent::__get($name);
        }
    }

    public function __set($name, $value)
    {
        if (array_key_exists($name, $this->attributes)) {
            $this->attributes[$name] = $value;
        } else {
            parent::__set($name, $value);
        }
    }

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

    public function attributeLabels()
    {
        return $this->labels;
    }

    public function initDataProvider($query, $sortAttirbutes = [], $route = null)
    {
        if ($route === null) { $route = Route::getCurrentRoute()->uri(); }
        $dataProvider = new EloquentDataProvider([
            'query' => $query,
            'pagination' => ['route' => $route],
            'sort' => ['route' => $route, 'attributes' => $sortAttirbutes],
        ]);

        return $dataProvider;
    }

    public function applyFilter($params)
    {
        $query = null;

        $dataProvider = $this->initDataProvider($query);

        return $dataProvider;
    }
}



, .
namespace App\Forms\Admin;

use App\Yii\Data\FilterModel;

class OrderFilter extends FilterModel
{
    public function rules()
    {
        return [
            ['id', 'safe'],
            ['user.name', 'safe'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
            'user.name' => 'User',
        ];
    }

    public function applyFilter($params)
    {
        $this->load($params);

        $query = \App\Models\Order::query();
        $query->join('users', 'users.id', '=', 'orders.user_id')->select('orders.*');

        if ($this->id) $query->where('orders.id', '=', $this->id);
        if ($this->{'user.name'}) $query->where('users.name', 'like', '%'.$this->{'user.name'}.'%');

        $sortAttributes = [
            'id',
            'user.name' => ['asc' => ['users.name' => SORT_ASC], 'desc' => ['users.name' => SORT_DESC]],
        ];

        $dataProvider = $this->initDataProvider($query, $sortAttributes);
        $dataProvider->pagination->defaultPageSize = 10;

        if (empty($dataProvider->sort->getAttributeOrders())) {
            $dataProvider->query->orderBy('orders.id', 'asc');
        }

        return $dataProvider;
    }
}

app/Http/Controllers/Admin/OrderController.php
public function index(Request $request)
{
    $filterModel = new \App\Forms\Admin\OrderFilter();

    $dataProvider = $filterModel->applyFilter($request);

    $gridViewConfig = [
        'dataProvider' => $dataProvider,
        'filterModel' => $filterModel,
        ...
    ];
    ...
}



, filterModel, , . . , .



, . . .

app/Http/Controllers/Admin/OrderController.php
public function view($id)
{
    $model = Order::findOrFail($id);

    $detailViewConfig = [
        'model' => $model,
        'attributes' => [
            'id',
            'user.name',
            'created_at:datetime',
            'updated_at:datetime',
        ],
    ];

    $gridViewConfig = [
        'dataProvider' => new \App\Yii\Data\EloquentDataProvider([
            'query' => $model->items(),
            'pagination' => false,
            'sort' => false,
        ]),
        'layout' => '{items}{summary}',
        'columns' => [
            'id',
            'product.name',
            'created_at:datetime',
            'updated_at:datetime',
        ],
    ];

    return view('admin.order.view', ['model' => $model, 'detailViewConfig' => $detailViewConfig, 'gridViewConfig' => $gridViewConfig]);
}

resources/views/admin/order/view.blade.php
@extends('layouts.main')

@section('title', 'Index')

@section('content')

    

Order: {{ $model->id }}

Update Delete

{!! \yii\widgets\DetailView::widget($detailViewConfig) !!}

Order Items

{!! \yii\grid\GridView::widget($gridViewConfig) !!} @endsection




/



, Eloquent , \yii\base\Model, ActiveForm .

app/Yii/Data/FormModel.php
namespace App\Yii\Data;

use Illuminate\Database\Eloquent\Model as EloquentModel;

class FormModel extends \yii\base\Model
{
    protected $model;
    protected $labels;
    protected $rules;
    protected $attributes;

    public function __construct(EloquentModel $model, $labels = [], $rules = [])
    {
        parent::__construct();

        $this->model = $model;
        $this->labels = $labels;
        $this->rules = $rules;

        $fillable = $model->getFillable();
        $attributes = [];
        foreach ($fillable as $field) {
            $attributes[$field] = $model->$field;
        }

        $this->attributes = $attributes;
    }

    public function getModel()
    {
        return $model;
    }

    public function __get($name)
    {
        if (array_key_exists($name, $this->attributes)) {
            return $this->attributes[$name];
        } else {
            return $this->model->{$name};
        }
    }

    public function __set($name, $value)
    {
        if (array_key_exists($name, $this->attributes)) {
            $this->attributes[$name] = $value;
        } else {
            $this->model->{$name} = $value;
        }
    }

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

    public function attributeLabels()
    {
        return $this->labels;
    }

    public function save()
    {
        if (!$this->validate()) {
            return false;
        }

        $this->model->fill($this->attributes);
        return $this->model->save();
    }
}



.

app/Http/Controllers/Admin/OrderController.php
    public function create(Request $request)
    {
        $model = new Order();
        $formModel = new \App\Yii\Data\FormModel(
            $model,
            ['user_id' => 'User'],
            [['user_id', 'safe']]
        );

        if ($request->isMethod('post')) {
            if ($formModel->load($request->input()) && $formModel->save()) {
                return redirect()->route('admin.order.view', ['id' => $model->id]);
            }
        }

        return view('admin.order.create', ['formModel' => $formModel]);
    }

    public function update($id, Request $request)
    {
        $model = Order::findOrFail($id);
        $formModel = new \App\Yii\Data\FormModel(
            $model,
            ['user_id' => 'User'],
            [['user_id', 'safe']]
        );

        if ($request->isMethod('post')) {
            if ($formModel->load($request->input()) && $formModel->save()) {
                return redirect()->route('admin.order.view', ['id' => $model->id]);
            }
        }

        return view('admin.order.update', ['formModel' => $formModel]);
    }

resources/views/admin/order/_form.blade.php


    {!! $form->field($formModel, 'user_id')->dropDownList(\App\User::pluck('name', 'id'), ['prompt' => '']) !!}

    




Yii. , validate() Laravel. .

Blade . ActiveForm::begin() . , Blade::extend(), , ActiveForm. .

, FormModel .

app/Forms/Admin/OrderForm.php
namespace App\Forms\Admin;

class OrderForm extends FormModel
{
    public function rules()
    {
        return [
            ['user_id', 'safe'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'user_id' => 'User',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
            'user.name' => 'User',
        ];
    }
}





OrderForm, app/Http/Controllers/Admin/OrderController.php.
$formModel = new \App\Forms\Admin\OrderForm($model);

$detailViewConfig = [
    'model' => $formModel,
    ...
];




.
app/Http/Controllers/Admin/OrderController.php
public function delete($id)
{
    $model = Order::findOrFail($id);
    $model->delete();

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




Gii. , , . .

composer require yiisoft/yii2-gii --dev

routes/web.php
    $config = [
        'components' => [
            ...
            'db' => [
                'class' => \yii\db\Connection::class,
                'dsn' => 'mysql:host='.env('DB_HOST', 'localhost')
                    .';port='.env('DB_PORT', '3306')
                    .';dbname='.env('DB_DATABASE', 'forge'),
                'username' => env('DB_USERNAME', 'forge'),
                'password' => env('DB_PASSWORD', ''),
                'charset' => 'utf8',
            ],
            ...
        ],
    ];

    if (YII_DEBUG) {
        $config['modules']['gii'] = ['class' => \yii\gii\Module::class];
        $config['bootstrap'][] = 'gii';
    }

    (new \yii\web\Application($config));  // initialization is in constructor
    Yii::setAlias('@bower', Yii::getAlias('@vendor') . DIRECTORY_SEPARATOR . 'bower-asset');
    Yii::setAlias('@App', Yii::getAlias('@app') . DIRECTORY_SEPARATOR . 'App');

    ...

    Route::any('gii{params?}', function () {
        $request = \Yii::$app->getRequest();
        $request->setBaseUrl('/admin');
        \Yii::$app->run();
        return null;
    })->where('params', '(.*)');


Yii::setAlias('@App') Yii::getAlias('@'...), App\Models\Order '@App/Models/Order.php'.
setBaseUrl('/admin') , Yii '/admin'.

Yii::setAlias('@App') ['Yii', 'autoload'] . , , . . , UnknownClassException. Laravel, . Composer, , 'Cannot declare class '...', because the name is already in use'. 500 .

Gii , , jQuery, , .

vendor\yiisoft\yii2-gii\Module.php
protected function resetGlobalSettings()
{
    if (Yii::$app instanceof \yii\web\Application) {
        Yii::$app->assetManager->bundles = [];
    }
}



ActionColumn , .

app/Yii/Widgets/ActionColumn.php
namespace App\Yii\Widgets;

use URL;
use Route;

class ActionColumn extends \yii\grid\ActionColumn
{
    public $keyAttribute = 'id';
    public $baseRoute = null;
    public $separator = '.';

    /**
     * Overrides URL generation to use Laravel routing system
     *
     * @inheritdoc
     */
    public function createUrl($action, $model, $key, $index)
    {
        if (is_callable($this->urlCreator)) {
            return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
        } else {
            if ($this->baseRoute === null) {
                $this->baseRoute = Route::getCurrentRoute()->getName();
            }

            $baseRouteParts = explode($this->separator, $this->baseRoute);
            $baseRouteParts[count($baseRouteParts) - 1] = $action;
            $route = implode($this->separator, $baseRouteParts);

            $params = is_array($key) ? $key : [$this->keyAttribute => (string) $key];

            return URL::route($route, $params, false);
        }
    }
}



ActiveForm, , . . Select2.

app/Yii/Widgets/FormBuilder.php
namespace App\Yii\Widgets;

use yii\widgets\ActiveForm;
use yii\helpers\Html;

class FormBuilder extends \yii\base\Component
{
    protected $model;
    protected $form;


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

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

    public function setModel($model)
    {
        $this->model = $model;
    }

    public function getForm()
    {
        return $this->form;
    }

    public function open($params = ['successCssClass' => ''])
    {
        $this->form = ActiveForm::begin($params);
    }

    public function close()
    {
        ActiveForm::end();
    }

    public function field($attribute, $options = [])
    {
        return $this->form->field($this->model, $attribute, $options);
    }

    public function submitButton($content, $options = ['class' => 'btn btn-primary'])
    {
        return Html::submitButton($content, $options);
    }
}



resources/views/admin/order/_form.blade.php
{!! $form->open() !!}

    {!! $form->field('user_id')->dropDownList(
        \App\User::pluck('name', 'id'),
        ['prompt' => ''])
    !!}

    {!! $form->submitButton('Submit'); !!}

{!! $form->close() !!}





. . .
php artisan migrate:refresh --seed


app/Yii.
:
App\Yii\Web\Request
App\Yii\Data\EloquentDataProvider
App\Yii\Data\FormModel

, :
App\Yii\Data\FilterModel
App\Yii\Web\View
App\Yii\Widgets\ActionColumn
App\Yii\Widgets\FormBuilder


, , . , .
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334542/

:  

: [1] []
 

:
: 

: ( )

:

  URL