Yii 2 работа с таблицами
По шагам.
1. Пишу под Windows. Запускаю консоль Open Server
2. composer create-project --prefer-dist yiisoft/yii2-app-basic yii2lesson
3.Настраиваем пути
4.Смотрите не напоритесть на bower
5. Сделаем такую схему
И DDL
F:\OpenServer\domains\yii2lesson\config\db.php
8. Создаем модели
9. Создаем CRUD
10. Проверьте контролеры
должно быть
namespace app\modules\lesson\controllers;
11. Связь на дочернюю таблицу
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\index.php
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\view.php
12. Использование PJAX
при поиске в таблицу получаем URL вида http://yii2lesson/lesson/worker/index?WorkerSearch[id]=&WorkerSearch[name]=&WorkerSearch[dep_id]=1&WorkerSearch[img]=
что не красиво.
в модели пропишем
public function formName()
{
return '';
}
получим http://yii2lesson/lesson/worker?id=&name=&dep_id=1&img=
что получше, но можно вообще это убрать
в index добавляем
use yii\widgets\Pjax;
и оборачиваем
при желании
13. Связь многие-ко-многим
переходим в папку с проектом
cd F:\OpenServer\domains\yii2lesson
ставим расширение
composer require --prefer-dist voskobovich/yii2-many-many-behavior "*"
в модели
use yii\helpers\Html;
создаем поведение
public function behaviors()
{
return [
[
'class' => \voskobovich\behaviors\ManyToManyBehavior::className(),
'relations' => [
'perks_list' => 'perks',
],
],
];
}
функцию
public function getPerks()
{
return $this->hasMany(Perk::className(), ['id' => 'perk_id'])
->viaTable('worker_has_perk', ['worker_id' => 'id']);
}
правила
public function rules()
{
return [
[['name', 'dep_id'], 'required'],
[['name', 'img'], 'string'],
[['dep_id'], 'integer'],
[['perks_list'], 'safe'],
];
}
в форме
<?= $form->field($model, 'perks_list')
->dropDownList(ArrayHelper::map(Perk::find()->all(), 'id', 'name'), ['multiple' => true])
?>
в модели для вывода в index
public function getMyperks()
{
$perks = $this->perks;
for($i = 0; $i <= count($perks); $i++)
{
if (!empty($perks[$i]['name']))
$perk[] = Html::a($perks[$i]['name'], ['/lesson/perk/view', 'id' => $perks[$i]['id'],], ['class' => 'btn btn-link']);
}
return ($perk) ? implode($perk) : '';
}
в index
[
'format' => 'raw',
'label' => 'Навыки',
'value' => function($data)
{
return $data->myperks;
},
],
view
DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'name:ntext',
'dep_id',
['label' => 'атрибут', 'value' => $model->dep->name,],
[
'format' => 'raw',
'label' => 'Навыки',
'value' => $model->myperks ,
],
'img:ntext',
],
])
14. Загрузка изображения
в модели
public function rules()
{
return [
[['name', 'dep_id'], 'required'],
[['name'], 'string'],
[['img'], 'file'],
[['dep_id'], 'integer'],
[['perks_list'], 'safe'],
];
}
если поле обязательное то
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'img')->fileInput() ?>
<?php echo ($model->img) ? Html::img('/uploads/' . $model->img, ['width' => 100, 'height' => 100]) : null ?>
ВАЖНО:
в начале поменяйте
<?php $form = ActiveForm::begin(); ?>
на
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
ВАЖНО:
нужно создать папку F:\OpenServer\domains\yii2lesson\web\uploads
контролер
use yii\web\UploadedFile;
public function actionCreate()
{
$model = new Worker();
if ($model->load(Yii::$app->request->post()))
{
$file = UploadedFile::getInstance($model, 'img');
if (isset($file))
{
$filename = uniqid() . '.' . $file->extension;
$path = 'uploads/' . $filename;
if ($file->saveAs($path))
{
$model->img = $filename;
}
}
if ($model->save())
{
return $this->redirect('index');
}
}
else
{
return $this->render('create', [
'model' => $model,
]);
}
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
$oldFile = 'uploads/' . $model->img;
$oldFileName = $model->img;
if ($model->load(Yii::$app->request->post()))
{
$file = UploadedFile::getInstance($model, 'img');
if (isset($file))
{
if(file_exists($oldFile)) @unlink($oldFile);
$filename = uniqid() . '.' . $file->extension;
$path = 'uploads/' . $filename;
if ($file->saveAs($path))
{
$model->img = $filename;
}
}
else $model->img = $oldFileName;
if ($model->save())
{
return $this->redirect(['index']);
}
}
else
{
return $this->render('update', [
'model' => $model,
]);
}
}
public function actionDelete($id)
{
$model = $this->findModel($id);
@unlink('uploads/' . $model->img);
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
index
[
'attribute' => 'img',
'format' => 'html',
'value' => function($data)
{
return Html::img($data->imageurl, ['width' => '100']);
},
],
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\view.php
[
'attribute' => 'img',
'value' => $model->imageurl,
'format' => ['image', ['width' => '100', 'height' => '100']],
],
Должны получить следующее
ИСХОДНИКИ
1. Пишу под Windows. Запускаю консоль Open Server
2. composer create-project --prefer-dist yiisoft/yii2-app-basic yii2lesson
3.Настраиваем пути
4.Смотрите не напоритесть на bower
5. Сделаем такую схему
И DDL
-- MySQL dump 10.13 Distrib 5.6.22, for Win32 (x86) -- -- Host: localhost Database: lesson -- ------------------------------------------------------ -- Server version 5.6.26 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Current Database: `lesson` -- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `lesson` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `lesson`; -- -- Table structure for table `dep` -- /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `dep` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `dep` -- LOCK TABLES `dep` WRITE; /*!40000 ALTER TABLE `dep` DISABLE KEYS */; /*!40000 ALTER TABLE `dep` ENABLE KEYS */; UNLOCK TABLES; -- -- Table structure for table `perk` -- /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `perk` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `perk` -- LOCK TABLES `perk` WRITE; /*!40000 ALTER TABLE `perk` DISABLE KEYS */; /*!40000 ALTER TABLE `perk` ENABLE KEYS */; UNLOCK TABLES; -- -- Table structure for table `worker` -- /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `worker` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` tinytext NOT NULL, `dep_id` int(11) NOT NULL, `img` tinytext, PRIMARY KEY (`id`), KEY `fk_worker_dep1_idx` (`dep_id`), CONSTRAINT `fk_worker_dep1` FOREIGN KEY (`dep_id`) REFERENCES `dep` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `worker` -- LOCK TABLES `worker` WRITE; /*!40000 ALTER TABLE `worker` DISABLE KEYS */; /*!40000 ALTER TABLE `worker` ENABLE KEYS */; UNLOCK TABLES; -- -- Table structure for table `worker_has_perk` -- /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `worker_has_perk` ( `worker_id` INTEGER(11) NOT NULL, `perk_id` INTEGER(11) NOT NULL, PRIMARY KEY (`worker_id`, `perk_id`) USING BTREE, KEY `fk_worker_has_perk_perk1_idx` (`perk_id`) USING BTREE, KEY `fk_worker_has_perk_worker1_idx` (`worker_id`) USING BTREE, CONSTRAINT `fk_worker_has_perk_perk1` FOREIGN KEY (`perk_id`) REFERENCES `perk` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_worker_has_perk_worker1` FOREIGN KEY (`worker_id`) REFERENCES `worker` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `worker_has_perk` -- LOCK TABLES `worker_has_perk` WRITE; /*!40000 ALTER TABLE `worker_has_perk` DISABLE KEYS */; /*!40000 ALTER TABLE `worker_has_perk` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2015-12-17 7:43:266. Подключаем базу
F:\OpenServer\domains\yii2lesson\config\db.php
<?php return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=lesson', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ];7. Создаем модуль и подключаем
8. Создаем модели
9. Создаем CRUD
10. Проверьте контролеры
должно быть
namespace app\modules\lesson\controllers;
11. Связь на дочернюю таблицу
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\index.php
<?php use yii\helpers\Html; use yii\grid\GridView; use yii\helpers\ArrayHelper; use app\modules\lesson\models\Dep; /* @var $this yii\web\View */ /* @var $searchModel app\modules\lesson\models\WorkerSearch */ /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Workers'; $this->params['breadcrumbs'][] = $this->title; ?> <div class="worker-index"> <h1><?= Html::encode($this->title) ?></h1> <?php // echo $this->render('_search', ['model' => $searchModel]); ?> <p> <?= Html::a('Create Worker', ['create'], ['class' => 'btn btn-success']) ?> </p> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'id', 'name:ntext', [ 'attribute' => 'dep_id', 'format' => 'raw', 'label' => 'раса', 'filter' => ArrayHelper::map(Dep::find()->all(), 'id', 'name'), 'value' => 'dep.name' ], 'img:ntext', ['class' => 'yii\grid\ActionColumn'], ], ]); ?> </div>F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\_form.php
<?php use yii\helpers\Html; use yii\widgets\ActiveForm; use yii\helpers\ArrayHelper; use app\modules\lesson\models\Dep; /* @var $this yii\web\View */ /* @var $model app\modules\lesson\models\Worker */ /* @var $form yii\widgets\ActiveForm */ ?> <div class="worker-form"> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'name')->textarea(['rows' => 6]) ?> <?= $form->field($model, 'dep_id')->dropDownList(ArrayHelper::map(Dep::find()->all(), 'id', 'name'), ['prompt' => 'Select...']) ?> <?= $form->field($model, 'img')->textarea(['rows' => 6]) ?> <div class="form-group"> <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> </div> <?php ActiveForm::end(); ?> </div>Параметр ['prompt' => 'Select...'] можно опустить, если поле обязательное
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\view.php
<?php use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $model app\modules\lesson\models\Worker */ $this->title = $model->name; $this->params['breadcrumbs'][] = ['label' => 'Workers', 'url' => ['index']]; $this->params['breadcrumbs'][] = $this->title; ?> <div class="worker-view"> <h1><?= Html::encode($this->title) ?></h1> <p> <?= Html::a('Update', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']) ?> <?= Html::a('Delete', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => 'Are you sure you want to delete this item?', 'method' => 'post', ], ]) ?> </p> <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'name:ntext', 'dep_id', ['label' => 'атрибут', 'value' => $model->dep->name,], 'img:ntext', ], ]) ?> </div>при условии что в модели
/** * @return \yii\db\ActiveQuery */ public function getDep() { return $this->hasOne(Dep::className(), ['id' => 'dep_id']); }
12. Использование PJAX
при поиске в таблицу получаем URL вида http://yii2lesson/lesson/worker/index?WorkerSearch[id]=&WorkerSearch[name]=&WorkerSearch[dep_id]=1&WorkerSearch[img]=
что не красиво.
в модели пропишем
public function formName()
{
return '';
}
получим http://yii2lesson/lesson/worker?id=&name=&dep_id=1&img=
что получше, но можно вообще это убрать
в index добавляем
use yii\widgets\Pjax;
и оборачиваем
<?php Pjax::begin(['enablePushState' => false]) ?> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'id', 'name:ntext', [ 'attribute' => 'dep_id', 'format' => 'raw', 'label' => 'раса', 'filter' => ArrayHelper::map(Dep::find()->all(), 'id', 'name'), 'value' => 'dep.name' ], 'img:ntext', ['class' => 'yii\grid\ActionColumn'], ], ]); ?> <?php Pjax::end() ?>
при желании
'enablePushState' => falseможно убрать
13. Связь многие-ко-многим
переходим в папку с проектом
cd F:\OpenServer\domains\yii2lesson
ставим расширение
composer require --prefer-dist voskobovich/yii2-many-many-behavior "*"
в модели
use yii\helpers\Html;
создаем поведение
public function behaviors()
{
return [
[
'class' => \voskobovich\behaviors\ManyToManyBehavior::className(),
'relations' => [
'perks_list' => 'perks',
],
],
];
}
функцию
public function getPerks()
{
return $this->hasMany(Perk::className(), ['id' => 'perk_id'])
->viaTable('worker_has_perk', ['worker_id' => 'id']);
}
правила
public function rules()
{
return [
[['name', 'dep_id'], 'required'],
[['name', 'img'], 'string'],
[['dep_id'], 'integer'],
[['perks_list'], 'safe'],
];
}
в форме
<?= $form->field($model, 'perks_list')
->dropDownList(ArrayHelper::map(Perk::find()->all(), 'id', 'name'), ['multiple' => true])
?>
в модели для вывода в index
public function getMyperks()
{
$perks = $this->perks;
for($i = 0; $i <= count($perks); $i++)
{
if (!empty($perks[$i]['name']))
$perk[] = Html::a($perks[$i]['name'], ['/lesson/perk/view', 'id' => $perks[$i]['id'],], ['class' => 'btn btn-link']);
}
return ($perk) ? implode($perk) : '';
}
в index
[
'format' => 'raw',
'label' => 'Навыки',
'value' => function($data)
{
return $data->myperks;
},
],
view
DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'name:ntext',
'dep_id',
['label' => 'атрибут', 'value' => $model->dep->name,],
[
'format' => 'raw',
'label' => 'Навыки',
'value' => $model->myperks ,
],
'img:ntext',
],
])
14. Загрузка изображения
в модели
public function rules()
{
return [
[['name', 'dep_id'], 'required'],
[['name'], 'string'],
[['img'], 'file'],
[['dep_id'], 'integer'],
[['perks_list'], 'safe'],
];
}
если поле обязательное то
[['img'], 'file', 'skipOnEmpty' => false],
функция для пути до файла
public function getImageurl()
{
// return your image url here
return \Yii::$app->request->BaseUrl . '/uploads/' . $this->img;
}
в _form<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'img')->fileInput() ?>
<?php echo ($model->img) ? Html::img('/uploads/' . $model->img, ['width' => 100, 'height' => 100]) : null ?>
ВАЖНО:
в начале поменяйте
<?php $form = ActiveForm::begin(); ?>
на
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
ВАЖНО:
нужно создать папку F:\OpenServer\domains\yii2lesson\web\uploads
контролер
use yii\web\UploadedFile;
public function actionCreate()
{
$model = new Worker();
if ($model->load(Yii::$app->request->post()))
{
$file = UploadedFile::getInstance($model, 'img');
if (isset($file))
{
$filename = uniqid() . '.' . $file->extension;
$path = 'uploads/' . $filename;
if ($file->saveAs($path))
{
$model->img = $filename;
}
}
if ($model->save())
{
return $this->redirect('index');
}
}
else
{
return $this->render('create', [
'model' => $model,
]);
}
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
$oldFile = 'uploads/' . $model->img;
$oldFileName = $model->img;
if ($model->load(Yii::$app->request->post()))
{
$file = UploadedFile::getInstance($model, 'img');
if (isset($file))
{
if(file_exists($oldFile)) @unlink($oldFile);
$filename = uniqid() . '.' . $file->extension;
$path = 'uploads/' . $filename;
if ($file->saveAs($path))
{
$model->img = $filename;
}
}
else $model->img = $oldFileName;
if ($model->save())
{
return $this->redirect(['index']);
}
}
else
{
return $this->render('update', [
'model' => $model,
]);
}
}
public function actionDelete($id)
{
$model = $this->findModel($id);
@unlink('uploads/' . $model->img);
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
index
[
'attribute' => 'img',
'format' => 'html',
'value' => function($data)
{
return Html::img($data->imageurl, ['width' => '100']);
},
],
F:\OpenServer\domains\yii2lesson\modules\lesson\views\worker\view.php
[
'attribute' => 'img',
'value' => $model->imageurl,
'format' => ['image', ['width' => '100', 'height' => '100']],
],
Должны получить следующее
ИСХОДНИКИ
Комментарии
Отправить комментарий