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'); });
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title>@yield('title')</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <style>body { padding-top: 60px; }</style> </head> <body> @include('layouts.nav') <div class="container"> @yield('content') </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html>
= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity = "sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va + PmSTsz / K68vbdEjh4u" crossorigin = "anonymous" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="/favicon.ico"> <title>@yield('title')</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> <style>body { padding-top: 60px; }</style> </head> <body> @include('layouts.nav') <div class="container"> @yield('content') </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html>
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/YH: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']);
- it is better to disconnect, so as not to interfere, enough autoloaders Laravel. He searches for files through getAlias('@'...)
and of course does not find it.basePath
is the root directory of the application, if improperly installed, there may be path errors. The runtime
folder is created in the same directory.assetManager.basePath, assetManager.baseUrl
- the path and URL for publishing assets, the folder name is arbitrary.assetManager.bundles
- disable jQuery publishing, as it is connected separately in the main template.request
- we redefine the request component, in which we replace work with the CSRF token, the field name is the same as in the Laravel settings.urlManager.enablePrettyUrl
- must be enabled if you need additional modules such as Gii.(new \yii\web\Application($config))
- Yii::$app = $this;
is assigned in the constructor 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 .= '<div>' . htmlspecialchars($item->product->name) . '</div>'; } 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') <h1>Orders</h1> <div class="text-right"> <a href="{{ route('admin.order.create') }}" class="btn btn-success">Create</a> </div> {!! \yii\grid\GridView::widget($gridViewConfig) !!} @endsection
dataProvider.pagination.route
and dataProvider.sort.route
, otherwise it will call Yii::$app->controller->getRoute()
, and the controller is null
. Similar to ActionColumn
, only there will be a check and an InvalidParamException
. The URL is generated via \yii\web\UrlManager
, but the result is the same as with Laravel routing. You can set the manager via dataProvider.pagination.urlManager
, if needed.\yii\web\View
component. The methods renderHeadHtml(), renderBodyBeginHtml(), renderBodyEndHtml()
are protected (it is not clear from whom, especially since all variables are public
). Oddly enough, there is a reason to use the antipattern “public morozov”. Or you can just copy them into the main template.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()
function, and the entire rendering is wrapped in a buffer, in which the CDATA
magic constants are then replaced with real assets. Emulation of this behavior is found in the initAssets()
function. We will not replace anything, we just need to fill the properties of $this->js, $this->css
and others. 'components' => [ ... 'view' => [ 'class' => \App\Yii\Web\View::class, ], ],
<!DOCTYPE html> <html lang="en"> <head> ... <?php $view = \Yii::$app->getView(); $view->initAssets(); ?> {!! \yii\helpers\Html::csrfMetaTags() !!} {!! $view->getHeadHtml() !!} </head> <body> {!! $view->getBodyBeginHtml() !!} ... {!! $view->getBodyEndHtml() !!} </body> </html>
Html::csrfMetaTags()
call is needed, since the yii.js script takes a csrf-token from the HTML page.ArrayDataProvider
works, but you need to make an ActiveDataProvider
analog in order to get only what you need from the database.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
, which will return labels for columns and field rules for filtering. For this there is a filterModel
parameter. Let's make it configurable through the constructor. 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]); }
@extends('layouts.main') @section('title', 'Index') @section('content') <h1>Order: {{ $model->id }}</h1> <p class="text-right"> <a href="{{ route('admin.order.update', ['id' => $model->id]) }}" class="btn btn-primary">Update</a> <a href="{{ route('admin.order.delete', ['id' => $model->id]) }}" class="btn btn-danger" data-confirm="Are you sure?" data-method="post">Delete</a> </p> {!! \yii\widgets\DetailView::widget($detailViewConfig) !!} <h2>Order Items</h2> {!! \yii\grid\GridView::widget($gridViewConfig) !!} @endsection
\yii\base\Model
, so that the ActiveForm
component can call the necessary methods. 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]); }
<?php $form = \yii\widgets\ActiveForm::begin() ?> {!! $form->field($formModel, 'user_id')->dropDownList(\App\User::pluck('name', 'id'), ['prompt' => '']) !!} <button type="submit" class="btn btn-primary">Submit</button> <?php \yii\widgets\ActiveForm::end() ?>
validate()
method and call the Laravel validator there. In this example, we will not do this.ActiveForm::begin()
and displays the tags and returns the value. You can explicitly write the <?php ?>
Tag, you can make a new tag through Blade::extend()
, as advised here , you can make a wrapper for ActiveForm
. For now, leave <?php ?>
.FormModel
and put all the ads there. 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
to set labels in the 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')
- the path to the files is determined via Yii::getAlias('@'...)
, therefore the path '@App/Models/Order.php'
will be checked for the App\Models\Order
class .setBaseUrl('/admin')
- you need the Yii routing to process only the part after the '/ admin'.Yii::setAlias('@App')
and ['Yii', 'autoload']
there is such a problem. If you do not disable the autoloader, then if the class or namespace is incorrectly named in the existing file, an error occurs that is incorrectly processed. It happens like this. It connects the file, but then does not find the class and throws an UnknownClassException
exception. The Laravel autoloader is called, which checks the facades and aliases and also does not find anything. Then the Composer autoloader is called, which reattaches the file, and another 'Cannot declare class' error occurs ..., because the name is already in use. The application crashes with error 500 without writing to the log. protected function resetGlobalSettings() { if (Yii::$app instanceof \yii\web\Application) { Yii::$app->assetManager->bundles = []; } }
ActionColumn
configuration to a separate class so as not to copy to different grids. 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); } } }
<?php ?>
Tags and transfer the model to each field. You can also add additional methods to initialize third-party widgets of fields of type Select2. Such a builder can also be used in projects on Yii. 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
Source: https://habr.com/ru/post/334542/
All Articles