Yii 2 работа с таблицами

По шагам.

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:26

6. Подключаем базу
 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']],
            ],

Должны получить следующее








ИСХОДНИКИ

Комментарии

Популярные сообщения из этого блога

Пишем логи на C# (.NET). Легкий способ.

Учебник yii2