. GridView Yii 2 Laravel |
composer create-project laravel/laravel
...
composer require yiisoft/yii2
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;
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');
});
@include('layouts.nav')
@yield('content')
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();
}
}
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]);
}
@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
, .\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();
}
}
endBody()
, , CDATA
. initAssets()
. , $this->js, $this->css
.'components' => [
...
'view' => [
'class' => \App\Yii\Web\View::class,
],
],
...
{!! \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');
}
}
}
}
'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
. .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;
}
}
public function index(Request $request)
{
$filterModel = new \App\Forms\Admin\OrderFilter();
$dataProvider = $filterModel->applyFilter($request);
$gridViewConfig = [
'dataProvider' => $dataProvider,
'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]);
}
\yii\base\Model
, ActiveForm
.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]);
}
{!! $form->field($formModel, 'user_id')->dropDownList(\App\User::pluck('name', 'id'), ['prompt' => '']) !!}
validate()
Laravel. .ActiveForm::begin()
.
, Blade::extend()
, , ActiveForm
.
.FormModel
.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');
}
composer require yiisoft/yii2-gii --dev
$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 .protected function resetGlobalSettings()
{
if (Yii::$app instanceof \yii\web\Application) {
Yii::$app->assetManager->bundles = [];
}
}
ActionColumn
, .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);
}
}
}
. Select2.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);
}
}
{!! $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