Yii2的使用

时间:2022-04-23 14:38:18

yii2的下载安装

使用下载好的文件配置高级模板,在配置文件配置好数据库和gii

在common模板配置db:

Yii2的使用

在backend模板配置gii:

Yii2的使用

配置nginx服务器访问backend和frontend:

server {
root C:/Users/liudaoqiang/project/manhua_yii2/frontend/web/;
index index.php index.html;
server_name dev.manhua_yii2_frontend.com;
# set $yii_bootstrap "index.html";
set $yii_bootstrap "index.php";

charset utf-8;

location / {
index $yii_bootstrap;
try_files $uri $uri/ $yii_bootstrap?$args;
if (!-e $request_filename) {
rewrite (.*) /index.php/$1;
}
}

location ~ ^/(protected|framework|nbproject|themes/\w+/views) {
deny all;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}

location ~ .*\.(js|css)?$ {
expires 7d;
}

#avoid processing of calls to unexisting static files by yii
location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
try_files $uri =404;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {

fastcgi_split_path_info ^(.+\.php)(.*)$;

#let yii catch the calls to unexising PHP files
set $fsn /$yii_bootstrap;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}

#fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_404;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;

#PATH_INFO and PATH_TRANSLATED can be omitted, but RFC 3875 specifies them for CGI
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fsn;

}

location ~ /\.ht {
deny all;
}
}

server {
root C:/Users/liudaoqiang/project/manhua_yii2/backend/web/;
index index.php index.html;
server_name dev.manhua_yii2_backend.com;
# set $yii_bootstrap "index.html";
set $yii_bootstrap "index.php";

charset utf-8;

location / {
index $yii_bootstrap;
try_files $uri $uri/ $yii_bootstrap?$args;
if (!-e $request_filename) {
rewrite (.*) /index.php/$1;
}
}

location ~ ^/(protected|framework|nbproject|themes/\w+/views) {
deny all;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}

location ~ .*\.(js|css)?$ {
expires 7d;
}

#avoid processing of calls to unexisting static files by yii
location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
try_files $uri =404;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {

fastcgi_split_path_info ^(.+\.php)(.*)$;

#let yii catch the calls to unexising PHP files
set $fsn /$yii_bootstrap;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}

#fastcgi_next_upstream error timeout invalid_header http_500 http_503 http_404;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;

#PATH_INFO and PATH_TRANSLATED can be omitted, but RFC 3875 specifies them for CGI
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fsn;

}

location ~ /\.ht {
deny all;
}
}

配置hosts文件:

127.0.0.1 dev.manhua_yii2_backend.com
127.0.0.1 dev.manhua_yii2_frontend.com

访问dev.manhua_yii2_backend.com和dev.manhua_yii2_frontend.com

2. Yii2的登录

首先应该有后台用户相关的数据表:

发现在console/migrations中有一个关于创建user数据表的迁移文件,对该文件进行修改,并插入一个默认的可登录用户:

Yii2的使用

指定php yii migrate生成数据表

这样创建了user数据表并插入了一个username为admin, password为123456的后台管理员

访问site/login可以登录成功,访问site/login可以登出

3. 访问后台的任何页面都必须登录

则执行任何的后台页面访问都要验证是否登录,没有登录则跳转到登录页面;已经登录才执行访问页面的操作:

在backend/components创建AdminController, 并让所有的后台控制器都继承AdminController

Yii2的使用

则访问任何页面都要验证是否登录

4.页面action的权限控制方法之使用Behavior

例:

Yii2的使用

注意:底层原理依然是使用beforeAction的机制来实现的

以下是yii\filter\AccessControl类, 该类中在beforeAction中验证了有否具有相应的权限

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yii\filters;

use Yii;
use yii\base\Action;
use yii\base\ActionFilter;
use yii\di\Instance;
use yii\web\User;
use yii\web\ForbiddenHttpException;

/**
* AccessControl provides simple access control based on a set of rules.
*
* AccessControl is an action filter. It will check its [[rules]] to find
* the first rule that matches the current context variables (such as user IP address, user role).
* The matching rule will dictate whether to allow or deny the access to the requested controller
* action. If no rule matches, the access will be denied.
*
* To use AccessControl, declare it in the `behaviors()` method of your controller class.
* For example, the following declarations will allow authenticated users to access the "create"
* and "update" actions and deny all other users from accessing these two actions.
*
* ```php
* public function behaviors()
* {
* return [
* 'access' => [
* 'class' => \yii\filters\AccessControl::className(),
* 'only' => ['create', 'update'],
* 'rules' => [
* // deny all POST requests
* [
* 'allow' => false,
* 'verbs' => ['POST']
* ],
* // allow authenticated users
* [
* 'allow' => true,
* 'roles' => ['@'],
* ],
* // everything else is denied
* ],
* ],
* ];
* }
* ```
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class AccessControl extends ActionFilter
{
/**
* @var User|array|string the user object representing the authentication status or the ID of the user application component.
* Starting from version 2.0.2, this can also be a configuration array for creating the object.
*/
public $user = 'user';
/**
* @var callable a callback that will be called if the access should be denied
* to the current user. If not set, [[denyAccess()]] will be called.
*
* The signature of the callback should be as follows:
*
* ```php
* function ($rule, $action)
* ```
*
* where `$rule` is the rule that denies the user, and `$action` is the current [[Action|action]] object.
* `$rule` can be `null` if access is denied because none of the rules matched.
*/
public $denyCallback;
/**
* @var array the default configuration of access rules. Individual rule configurations
* specified via [[rules]] will take precedence when the same property of the rule is configured.
*/
public $ruleConfig = ['class' => 'yii\filters\AccessRule'];
/**
* @var array a list of access rule objects or configuration arrays for creating the rule objects.
* If a rule is specified via a configuration array, it will be merged with [[ruleConfig]] first
* before it is used for creating the rule object.
* @see ruleConfig
*/
public $rules = [];

/**
* Initializes the [[rules]] array by instantiating rule objects from configurations.
*/
public function init()
{
parent::init();
$this->user = Instance::ensure($this->user, User::className());
foreach ($this->rules as $i => $rule) {
if (is_array($rule)) {
$this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
}
}
}

/**
* This method is invoked right before an action is to be executed (after all possible filters.)
* You may override this method to do last-minute preparation for the action.
* @param Action $action the action to be executed.
* @return boolean whether the action should continue to be executed.
*/
public function beforeAction($action)
{
$user = $this->user;
$request = Yii::$app->getRequest();
/* @var $rule AccessRule */
foreach ($this->rules as $rule) {
if ($allow = $rule->allows($action, $user, $request)) {
return true;
} elseif ($allow === false) {
if (isset($rule->denyCallback)) {
call_user_func($rule->denyCallback, $rule, $action);
} elseif ($this->denyCallback !== null) {
call_user_func($this->denyCallback, $rule, $action);
} else {
$this->denyAccess($user);
}
return false;
}
}
if ($this->denyCallback !== null) {
call_user_func($this->denyCallback, null, $action);
} else {
$this->denyAccess($user);
}
return false;
}

/**
* Denies the access of the user.
* The default implementation will redirect the user to the login page if he is a guest;
* if the user is already logged, a 403 HTTP exception will be thrown.
* @param User $user the current user
* @throws ForbiddenHttpException if the user is already logged in.
*/
protected function denyAccess($user)
{
if ($user->getIsGuest()) {
$user->loginRequired();
} else {
throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
}
}
}

yii\filter\VerbFilter类依然是使用beforeAction的机制:

代码如下

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

namespace yii\filters;

use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
use yii\web\Controller;
use yii\web\MethodNotAllowedHttpException;

/**
* VerbFilter is an action filter that filters by HTTP request methods.
*
* It allows to define allowed HTTP request methods for each action and will throw
* an HTTP 405 error when the method is not allowed.
*
* To use VerbFilter, declare it in the `behaviors()` method of your controller class.
* For example, the following declarations will define a typical set of allowed
* request methods for REST CRUD actions.
*
* ```php
* public function behaviors()
* {
* return [
* 'verbs' => [
* 'class' => \yii\filters\VerbFilter::className(),
* 'actions' => [
* 'index' => ['get'],
* 'view' => ['get'],
* 'create' => ['get', 'post'],
* 'update' => ['get', 'put', 'post'],
* 'delete' => ['post', 'delete'],
* ],
* ],
* ];
* }
* ```
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class VerbFilter extends Behavior
{
/**
* @var array this property defines the allowed request methods for each action.
* For each action that should only support limited set of request methods
* you add an entry with the action id as array key and an array of
* allowed methods (e.g. GET, HEAD, PUT) as the value.
* If an action is not listed all request methods are considered allowed.
*
* You can use `'*'` to stand for all actions. When an action is explicitly
* specified, it takes precedence over the specification given by `'*'`.
*
* For example,
*
* ```php
* [
* 'create' => ['get', 'post'],
* 'update' => ['get', 'put', 'post'],
* 'delete' => ['post', 'delete'],
* '*' => ['get'],
* ]
* ```
*/
public $actions = [];

/**
* Declares event handlers for the [[owner]]'s events.
* @return array events (array keys) and the corresponding event handler methods (array values).
*/
public function events()
{
return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
}

/**
* @param ActionEvent $event
* @return boolean
* @throws MethodNotAllowedHttpException when the request method is not allowed.
*/
public function beforeAction($event)
{
$action = $event->action->id;
if (isset($this->actions[$action])) {
$verbs = $this->actions[$action];
} elseif (isset($this->actions['*'])) {
$verbs = $this->actions['*'];
} else {
return $event->isValid;
}

$verb = Yii::$app->getRequest()->getMethod();
$allowed = array_map('strtoupper', $verbs);
if (!in_array($verb, $allowed)) {
$event->isValid = false;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
throw new MethodNotAllowedHttpException('Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed) . '.');
}

return $event->isValid;
}
}

5.初始化选择yii2的环境local/dev/test/prod

原理:

运行php init 通过用户的选择环境

查找用户的选择的环境,异常则退出

计算出将要复制的文件配置,跳过配置中需要skip的文件配置

设置文件的属性

代码如下:

#!/usr/bin/env php
<?php
/**
* Yii Application Initialization Tool
*
* In order to run in non-interactive mode:
*
* init --env=Development --overwrite=n
*
* @author Alexander Makarov <sam@rmcreative.ru>
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/

if (!extension_loaded('openssl')) {
die('The OpenSSL PHP extension is required by Yii2.');
}

$params = getParams();
$root = str_replace('\\', '/', __DIR__);
$envs = require("$root/environments/index.php");
$envNames = array_keys($envs);

echo "Yii Application Initialization Tool v1.0\n\n";

$envName = null;
if (empty($params['env']) || $params['env'] === '1') {
echo "Which environment do you want the application to be initialized in?\n\n";
foreach ($envNames as $i => $name) {
echo " [$i] $name\n";
}
echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
$answer = trim(fgets(STDIN));

if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
echo "\n Quit initialization.\n";
exit(0);
}

if (isset($envNames[$answer])) {
$envName = $envNames[$answer];
}
} else {
$envName = $params['env'];
}

if (!in_array($envName, $envNames)) {
$envsList = implode(', ', $envNames);
echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n";
exit(2);
}

$env = $envs[$envName];

if (empty($params['env'])) {
echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] ";
$answer = trim(fgets(STDIN));
if (strncasecmp($answer, 'y', 1)) {
echo "\n Quit initialization.\n";
exit(0);
}
}

echo "\n Start initialization ...\n\n";
$files = getFileList("$root/environments/{$env['path']}");
if (isset($env['skipFiles'])) {
$skipFiles = $env['skipFiles'];
array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; });
$files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists')));
}
$all = false;
foreach ($files as $file) {
if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) {
break;
}
}

$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
foreach ($callbacks as $callback) {
if (!empty($env[$callback])) {
$callback($root, $env[$callback]);
}
}

echo "\n ... initialization completed.\n\n";

function getFileList($root, $basePath = '')
{
$files = [];
$handle = opendir($root);
while (($path = readdir($handle)) !== false) {
if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
continue;
}
$fullPath = "$root/$path";
$relativePath = $basePath === '' ? $path : "$basePath/$path";
if (is_dir($fullPath)) {
$files = array_merge($files, getFileList($fullPath, $relativePath));
} else {
$files[] = $relativePath;
}
}
closedir($handle);
return $files;
}

function copyFile($root, $source, $target, &$all, $params)
{
if (!is_file($root . '/' . $source)) {
echo " skip $target ($source not exist)\n";
return true;
}
if (is_file($root . '/' . $target)) {
if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
echo " unchanged $target\n";
return true;
}
if ($all) {
echo " overwrite $target\n";
} else {
echo " exist $target\n";
echo " ...overwrite? [Yes|No|All|Quit] ";

$answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));
if (!strncasecmp($answer, 'q', 1)) {
return false;
} else {
if (!strncasecmp($answer, 'y', 1)) {
echo " overwrite $target\n";
} else {
if (!strncasecmp($answer, 'a', 1)) {
echo " overwrite $target\n";
$all = true;
} else {
echo " skip $target\n";
return true;
}
}
}
}
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
return true;
}
echo " generate $target\n";
@mkdir(dirname($root . '/' . $target), 0777, true);
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
return true;
}

function getParams()
{
$rawParams = [];
if (isset($_SERVER['argv'])) {
$rawParams = $_SERVER['argv'];
array_shift($rawParams);
}

$params = [];
foreach ($rawParams as $param) {
if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
$name = $matches[1];
$params[$name] = isset($matches[3]) ? $matches[3] : true;
} else {
$params[] = $param;
}
}
return $params;
}

function setWritable($root, $paths)
{
foreach ($paths as $writable) {
if (is_dir("$root/$writable")) {
echo " chmod 0777 $writable\n";
@chmod("$root/$writable", 0777);
} else {
echo "\n Error. Directory $writable does not exist. \n";
}
}
}

function setExecutable($root, $paths)
{
foreach ($paths as $executable) {
echo " chmod 0755 $executable\n";
@chmod("$root/$executable", 0755);
}
}

function setCookieValidationKey($root, $paths)
{
foreach ($paths as $file) {
echo " generate cookie validation key in $file\n";
$file = $root . '/' . $file;
$length = 32;
$bytes = openssl_random_pseudo_bytes($length);
$key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
$content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
file_put_contents($file, $content);
}
}

function createSymlink($root, $links) {
foreach ($links as $link => $target) {
echo " symlink " . $root . "/" . $target . " " . $root . "/" . $link . "\n";
//first removing folders to avoid errors if the folder already exists
@rmdir($root . "/" . $link);
@symlink($root . "/" . $target, $root . "/" . $link);
}
}

6. yii2的扩展插件的下载安装

首先在http://www.yiiframework.com/extensions/搜索想要的插件

开始下载安装,例如下载安装yii2-btn-copy-html-block

在yii2的项目根目录下执行:

php composer.phar require --prefer-dist mackrais/yii2-btn-copy-html-block "dev-master"

提示需要token:

按照提示例如去https://github.com/settings/tokens/new?scopes=repo&description=Composer+on+DESKTOP-9V73O7O+2017-09-05+1144创建token

然后系统后自动下载插件并安装

7.使用Yii2开发web站点feature

步骤:

1.使用git创建新的branch

git branch feature_wms_check

2.使用php yii migrate/create create_table_tablename创建数据库迁移

php yii migrate/create create_table_wms_check

例如:

<?php

use yii\db\Schema;
use jamband\schemadump\Migration;

class m170927_084004_create_table_wms_check extends Migration
{
    const TABLE_NAME = '{{%wms_check}}';
    public function safeUp()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB COMMENT=\'库存盘点表\'';
        }

        $this->createTable(self::TABLE_NAME, [
            'id' => $this->primaryKey() . ' AUTO_INCREMENT  COMMENT \'自增ID\'',
            'wms_check_code' => $this->string(32) . ' COMMENT \'库存盘点编号\'',

            'common_producer_info_id' => $this->integer(8) . ' COMMENT \'加工基地编号\'',
            'common_producer_info_name' => $this->string(50) . ' COMMENT \'加工基地名称\'',

            'common_producer_herb_type' => $this->smallInteger(1) . ' COMMENT \'物料类型1是原料2是成品\'',

            'wms_check_user_id' => $this->integer(8) . ' COMMENT \'库存盘点人ID\'',
            'wms_check_user_name' => $this->string(32) . ' COMMENT \'库存盘点人姓名\'',
            'wms_check_user_phone' => $this->string(20) . ' COMMENT \'库存盘点人电话\'',

            'wms_check_redo_user_id' => $this->integer(8) . ' COMMENT \'库存盘点复核人ID\'',
            'wms_check_redo_user_name' => $this->string(32) . ' COMMENT \'库存盘点复核人姓名\'',
            'wms_check_redo_user_phone' => $this->string(20) . ' COMMENT \'库存盘点复核人电话\'',

            'wms_check_year' => $this->smallInteger(6) . ' COMMENT \'库存盘点年份\'',
            'wms_check_month' => $this->smallInteger(6) . ' COMMENT \'库存盘点月份\'',

            'wms_check_at' => $this->integer(10) . ' COMMENT \'库存盘点日期\'',

            'wms_check_note' => $this->text() . ' COMMENT \'库存盘点备注\'',

            'created_at' => $this->integer(10) . ' COMMENT \'创建时间\'',
            'updated_at' => $this->integer(10) . ' COMMENT \'编辑时间\'',
            'is_del' => $this->boolean()->defaultValue(0) . ' COMMENT \'是否逻辑删除\'',
        ], $tableOptions);

        $this->createIndex('wms_check_code',self::TABLE_NAME,'wms_check_code');
        $this->createIndex('common_producer_info_id',self::TABLE_NAME,'common_producer_info_id');
        $this->createIndex('wms_check_year',self::TABLE_NAME,'wms_check_year');
        $this->createIndex('wms_check_month',self::TABLE_NAME,'wms_check_month');
    }

    public function safeDown()
    {
        $this->dropTable(self::TABLE_NAME);
    }
}

3.使用php yii migrate回车后yes运行数据库迁移脚本

php yii migrate

4.使用gii生成ActiveRecord模型

Yii2的使用

Yii2的使用

生成的模型代码如下:

<?php

namespace common\models;

use Yii;

/**
 * This is the model class for table "{{%wms_check}}".
 *
 * @property integer $id
 * @property string $wms_check_code
 * @property integer $common_producer_info_id
 * @property string $common_producer_info_name
 * @property integer $common_producer_herb_type
 * @property integer $wms_check_user_id
 * @property string $wms_check_user_name
 * @property string $wms_check_user_phone
 * @property integer $wms_check_redo_user_id
 * @property string $wms_check_redo_user_name
 * @property string $wms_check_redo_user_phone
 * @property integer $wms_check_year
 * @property integer $wms_check_month
 * @property integer $wms_check_at
 * @property string $wms_check_note
 * @property integer $created_at
 * @property integer $updated_at
 * @property integer $is_del
 */
class WmsCheck extends \common\models\Base
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%wms_check}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['common_producer_info_id', 'common_producer_herb_type', 'wms_check_user_id', 'wms_check_redo_user_id', 'wms_check_year', 'wms_check_month', 'created_at', 'updated_at', 'is_del'], 'integer'],
            [['wms_check_at', 'wms_check_note'], 'string'],
            [['wms_check_code', 'wms_check_user_name', 'wms_check_redo_user_name'], 'string', 'max' => 32],
            [['common_producer_info_name'], 'string', 'max' => 50],
            [['wms_check_user_phone', 'wms_check_redo_user_phone'], 'string', 'max' => 20],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => '自增ID',
            'wms_check_code' => '库存盘点编号',
            'common_producer_info_id' => '加工基地编号',
            'common_producer_info_name' => '加工基地名称',
            'common_producer_herb_type' => '物料类型1是原料2是成品',
            'wms_check_user_id' => '库存盘点人ID',
            'wms_check_user_name' => '库存盘点人姓名',
            'wms_check_user_phone' => '库存盘点人电话',
            'wms_check_redo_user_id' => '库存盘点复核人ID',
            'wms_check_redo_user_name' => '库存盘点复核人姓名',
            'wms_check_redo_user_phone' => '库存盘点复核人电话',
            'wms_check_year' => '库存盘点年份',
            'wms_check_month' => '库存盘点月份',
            'wms_check_at' => '库存盘点日期',
            'wms_check_note' => '库存盘点备注',
            'created_at' => '创建时间',
            'updated_at' => '编辑时间',
            'is_del' => '是否逻辑删除',
        ];
    }
}

5. 使用gii生成CRUD代码并对代码进行开发

部分代码如下:

backend/controllers/WmsCheckController.php

<?php

namespace backend\controllers;

use Yii;

use yii\base\ErrorException;
use yii\base\Exception;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

use backend\models\WmsCheckSearch;
use core\models\WmsCheck;
use core\models\WmsCheckDetail;
use common\models\Base;

/**
 * WmsCheckController implements the CRUD actions for WmsCheck model.
 */
class WmsCheckController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Lists all WmsCheck models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new WmsCheckSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single WmsCheck model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        $model = $this->findModel($id);
        $detailList = $model->wmsCheckDetails;
        return $this->render('view', [
            'model' => $model,
            'detailList'=>$detailList,
        ]);
    }

    /**
     * Creates a new WmsCheck model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new WmsCheck();
        //获取加工基地ID
        $common_producer_info_id = \core\models\Division::getTopDivisionId(Yii::$app->user->identity->division_id,true);
        //获取该基地的库存详情
        $stock_list = \core\models\WmsInfo::getStockDetailBaseInfoListGroupByMaterial($common_producer_info_id);
        //根据基地ID生成库存盘点清单编号
        $wms_check_code = \common\models\Base::generateCode('KCPD', $common_producer_info_id, $model, 'id');
        $model->wms_check_code = $wms_check_code;
        $model->common_producer_info_id = $common_producer_info_id;
        if ($model->load(Yii::$app->request->post())) {
            $transaction = Yii::$app->db->beginTransaction();
            try{
                //根据基地ID获取基地详情信息
                $common_producer_info_name = \core\models\Division::getDivisionName($model->common_producer_info_id);
                //根据用户ID获取用户的基本信息
                $userCheck = \core\models\User::getUser($model->wms_check_user_id);
                $userRedo = \core\models\User::getUser($model->wms_check_redo_user_id);

                $model->common_producer_info_id = $common_producer_info_id;
                $model->common_producer_info_name = $common_producer_info_name;

                if (empty($userCheck)){
                    $model->wms_check_user_name = '';
                    $model->wms_check_user_phone = '';
                }else{
                    $model->wms_check_user_name = $userCheck->name;
                    $model->wms_check_user_phone = $userCheck->phone;
                }

                if (empty($userRedo)){
                    $model->wms_check_redo_user_name = '';
                    $model->wms_check_redo_user_phone = '';
                }else{
                    $model->wms_check_redo_user_name = $userRedo->name;
                    $model->wms_check_redo_user_phone = $userRedo->phone;
                }

                $model->wms_check_year = intval($model->wms_check_year);
                $model->wms_check_month = intval($model->wms_check_month);

                $model->wms_check_at = strval(strtotime($model->wms_check_at));
                $model->wms_check_note = htmlspecialchars(addslashes($model->wms_check_note));

                $model->created_at = time();
                $model->updated_at = time();
                $model->is_del = 0;
                if(false == $model->save()){
                    throw new ErrorException('保存库存盘点失败');
                }

                foreach ($stock_list as $stock){
                    $_detail = new WmsCheckDetail();
                    $_detail->wms_check_id = $model->id;
                    $_detail->wms_check_code = $model->wms_check_code;
                    $_detail->common_producer_info_id = $model->common_producer_info_id;
                    $_detail->common_producer_info_name = $model->common_producer_info_name;
                    $_detail->common_producer_herb_type = $model->common_producer_herb_type;

                    $_detail->common_producer_herb_info_id = $stock['common_producer_herb_info_id'];
                    $_detail->common_producer_herb_info_name = $stock['common_producer_herb_info_name'];

                    $_detail->common_producer_herb_grade_info_id = $stock['common_producer_herb_grade_info_id'];
                    $_detail->common_producer_herb_grade_info_name = $stock['common_producer_herb_grade_name'];
                    $_detail->common_producer_herb_grade_info_spec_name = $stock['common_producer_herb_grade_info_spec_name'];

                    $_detail->wms_check_detail_unit_price = NULL;

                    $_detail->wms_check_detail_info_package_num = NULL;
                    $_detail->wms_check_detail_info_weight = NULL;
                    $_detail->wms_check_detail_info_sum_price = NULL;

                    $_detail->wms_check_detail_check_package_num = NULL;
                    $_detail->wms_check_detail_check_weight = NULL;
                    $_detail->wms_check_detail_check_sum_price = NULL;

                    $_detail->wms_check_detail_diff_weight = NULL;
                    $_detail->wms_check_detail_diff_sum_price = NULL;
                    $_detail->wms_check_detail_diff_note = NULL;

                    $_detail->created_at = time();
                    $_detail->updated_at = time();
                    $_detail->is_del = 0;

                    if(false == $_detail->save()){
                        throw new ErrorException('保存库存盘点详情失败');
                    }
                }
                $transaction->commit();
                return $this->redirect(['index']);
            }catch (ErrorException $e){

                $transaction->rollBack();
                return $this->redirect(['create'], [
                    'model' => $model,
                    'stock_list'=>$stock_list,
                ]);
            }
        } else {
            return $this->render('create', [
                'model' => $model,
                'stock_list'=>$stock_list,
            ]);
        }
    }

    /**
     * Updates an existing WmsCheck model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);
        if ($model->load(Yii::$app->request->post())) {
            $detail_list_data = Yii::$app->request->post();
            $detail_id_list = $detail_list_data['WmsCheckDetail']['id'];
            $transaction = Yii::$app->db->beginTransaction();
            try {
                $model->updated_at = time();
                if (false == $model->save()){
                    throw new Exception('库存盘点基本信息编辑失败');
                }
                foreach ($detail_id_list as $key => $detail_id) {
                    $_detail = WmsCheckDetail::findOne(['id' => $detail_id]);

                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_unit_price'][$key])){
                        $_detail->wms_check_detail_unit_price = Base::moneyBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_unit_price'][$key]);
                    }

                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_info_package_num'][$key])){
                        $_detail->wms_check_detail_info_package_num = $detail_list_data['WmsCheckDetail']['wms_check_detail_info_package_num'][$key];
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_info_weight'][$key])){
                        $_detail->wms_check_detail_info_weight = Base::weightBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_info_weight'][$key]);
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_info_sum_price'][$key])){
                        $_detail->wms_check_detail_info_sum_price = Base::moneyBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_info_sum_price'][$key]);
                    }

                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_check_package_num'][$key])){
                        $_detail->wms_check_detail_check_package_num = $detail_list_data['WmsCheckDetail']['wms_check_detail_check_package_num'][$key];
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_check_weight'][$key])){
                        $_detail->wms_check_detail_check_weight = Base::weightBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_check_weight'][$key]);
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_check_sum_price'][$key])){
                        $_detail->wms_check_detail_check_sum_price = Base::moneyBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_check_sum_price'][$key]);
                    }

                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_diff_weight'][$key])){
                        $_detail->wms_check_detail_diff_weight = Base::weightBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_diff_weight'][$key]);
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_diff_sum_price'][$key])){
                        $_detail->wms_check_detail_diff_sum_price = Base::moneyBcmul($detail_list_data['WmsCheckDetail']['wms_check_detail_diff_sum_price'][$key]);
                    }
                    if (isset($detail_list_data['WmsCheckDetail']['wms_check_detail_diff_note'][$key])){
                        $_detail->wms_check_detail_diff_note = $detail_list_data['WmsCheckDetail']['wms_check_detail_diff_note'][$key];
                    }

                    $_detail->updated_at = time();
                    if (false == $_detail->save()) {
                        throw new Exception('库存盘点详情信息编辑失败');
                    }
                }
                $transaction->commit();
            }catch (Exception $e){
                $transaction->rollBack();
                $detailList = $model->wmsCheckDetails;
                return $this->render('update', [
                    'model' => $model,
                    'detailList'=>$detailList,
                ]);
            }
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            $detailList = $model->wmsCheckDetails;
            return $this->render('update', [
                'model' => $model,
                'detailList'=>$detailList,
            ]);
        }
    }

    public function actionPrint($id)
    {
        $this->layout = false;
        $model = $this->findModel($id);
        $detailList = $model->wmsCheckDetails;
        $content = $this->render('print', [
            'model' => $model,
            'detailList'=>$detailList,
        ]);

        (new \TCPDF('P', 'mm', array(210, 297), true, 'UTF-8', false))->html('wms-check-sheet.pdf', $content, 10);
    }

    /**
     * Finds the WmsCheck model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return WmsCheck the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = WmsCheck::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

backend/models/WmsCheckSearch.php

<?php

namespace backend\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use core\models\WmsCheck;

/**
 * WmsCheckSearch represents the model behind the search form about `core\models\WmsCheck`.
 */
class WmsCheckSearch extends WmsCheck
{
    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {
        $query = WmsCheck::find();

        // add conditions that should always apply here

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        $this->load($params);

        $division_id = \core\models\Division::getTopDivisionId(Yii::$app->user->identity->division_id,true);
        if (!empty($division_id)) {
            $this->common_producer_info_id = $division_id;
        }

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'common_producer_herb_type'=>$this->common_producer_herb_type,
            'common_producer_info_id' => $this->common_producer_info_id,
            'wms_check_year' => $this->wms_check_year,
            'wms_check_month' => $this->wms_check_month,
            'wms_check_user_id' => $this->wms_check_user_id,
            'wms_check_redo_user_id' => $this->wms_check_redo_user_id,
            'wms_check_at' => $this->wms_check_at,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'is_del' => $this->is_del,
        ]);

        $query->andFilterWhere(['like', 'wms_check_code', $this->wms_check_code])
            ->andFilterWhere(['like', 'common_producer_info_name', $this->common_producer_info_name])
            ->andFilterWhere(['like', 'wms_check_user_name', $this->wms_check_user_name])
            ->andFilterWhere(['like', 'wms_check_user_phone', $this->wms_check_user_phone])
            ->andFilterWhere(['like', 'wms_check_redo_user_name', $this->wms_check_redo_user_name])
            ->andFilterWhere(['like', 'wms_check_redo_user_phone', $this->wms_check_redo_user_phone])
            ->andFilterWhere(['like', 'wms_check_note', $this->wms_check_note]);

        return $dataProvider;
    }
}

  

backend/views/wms-check/index.php

<?php

use yii\helpers\Html;
use kartik\grid\GridView;

$this->registerCssFile("css/css.css", ['depends' => ['dmstr\web\AdminLteAsset']]);
$this->title = Yii::t('app', '库存盘点清单');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="wms-check-index">
    <?php  echo $this->render('_search', ['model' => $searchModel]); ?>
    <div class="header">
        <div class="title">
            列表 <?= !empty($searchModel->common_producer_info_name) ? '(' . $searchModel->common_producer_info_name . ')' : ''; ?></div>
        <ul class="button_list">
            <li>
                <a class="a_color" href="<?= \yii\helpers\Url::to(['create']) ?>">
                    <i class="fa fa-plus" style="margin-right: 5px;"></i>新建</a>
            </li>
            <li>
                <a class="a_color" href="javascript:void(0)" onclick="(document.getElementById('search').style.display=='block')?
                (document.getElementById('search').style.display='none')&&(this.text='筛选'):(document.getElementById('search').style.display='block')&&(this.text='关闭筛选'); ">关闭筛选</a>
            </li>
        </ul>
    </div>
    <div class="clearfix"></div>
    <?= GridView::widget([
        'tableOptions' => ['class' => 'table table-striped'],
        'layout' => "{items}{summary}{pager}",
        'pjax'=>true,
        'striped'=>false,
        'hover'=>true,
        'showPageSummary' => false,
        'dataProvider' => $dataProvider,
        'columns' => [
            'wms_check_code',
            'common_producer_info_name',
             [
                 'label'=>'物料类型',
                 'value'=>function($model){
                     return $model->common_producer_herb_type == 1 ? '原料' : '成品';
                 }
             ],
            [
                'label'=>'年月',
                'value'=>function($model){
                    return $model->wms_check_year.'-'.$model->wms_check_month;
                }
            ],
             'wms_check_user_name',
             'wms_check_user_phone',
            'wms_check_redo_user_name',
            'wms_check_redo_user_phone',
            [
                'label'=>'盘库日期',
                'value'=>function($model){
                    return date('Y-m-d', $model->wms_check_at);
                }
            ],
            [
                'class' => 'kartik\grid\ActionColumn',
                'template' => '<li>{view}</li><li>{print}</li><li>{update}</li>',
                'header'=>'操作',
                'dropdown' => true,
                'dropdownOptions' => ['class' => 'pull-right'],
                'dropdownButton' => ['label' => '菜单','class'=>'btn btn-success'],
                'buttons' => [
                    'view' => function ($url, $model, $key) {
                        return Html::a('查看', ['view', 'id' => $key], ['class' => '']);
                    },
                    'print' => function ($url, $model, $key) {
                        return Html::a('打印', ['print', 'id' => $key], ['class' => '']);
                    },
                    'update' => function ($url, $model, $key) {
                        return Html::a('编辑', ['update', 'id' => $key], ['class' => '']);
                    },
                ]
            ],
        ],
    ]); ?>
</div>

backend/views/wms-check/search.php

<?php

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

/* @var $this yii\web\View */
/* @var $model backend\models\WmsCheckSearch */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="wms-check-search" id="search" style="display: block;">

    <?php $form = ActiveForm::begin([
        'action' => ['index'],
        'method' => 'get',
    ]); ?>
    <div class="row">
        <div class="col-md-3">
            <?= $form->field($model, 'common_producer_info_id', [
                'template' => "{input}",
            ])->label("基地名称")->widget(\kartik\select2\Select2::classname(), [
                'name' => 'common_producer_info_id',
                'hideSearch' => false,
                'data' => \yii\helpers\ArrayHelper::map(core\models\CommonProducerInfo::getCommonProducerInfoList(), 'division_id', 'common_producer_info_name'),
                'options' => ['placeholder' => '请选择基地','disabled'=>true],
                'pluginOptions' => [
                    'maximumInputLength' => 100,
                    'allowClear' => true,
                ]
            ]);
            ?>
        </div>
        <div class="col-md-3">
            <?= $form->field($model, 'common_producer_herb_type', [
                'template' => "{input}",
            ])->label("物料类型")->widget(\kartik\select2\Select2::classname(), [
                'name' => 'common_producer_herb_type',
                'hideSearch' => false,
                'data' => \yii\helpers\ArrayHelper::map(core\models\WmsStockDetailInfo::wmsMaterialTypeOptions(), 'id', 'text'),
                'options' => ['placeholder' => '请选择物料类型'],
                'pluginOptions' => [
                    'maximumInputLength' => 100,
                    'allowClear' => true,
                ]
            ]);
            ?>
        </div>
        <div class="col-md-3">
            <?= $form->field($model, 'wms_check_year',[
                'template' => "{input}",
            ])->label('年份')->widget(\kartik\datetime\DateTimePicker::classname(), [
                'options' => [
                    'placeholder' => '选择年份',
                    'value' =>$model->wms_check_year
                ],
                'readonly' => false,
                'pluginOptions' => [
                    'autoclose' => true,
                    'format' => 'yyyy',
                    'minView' => 4,
                    'maxView' => 4,
                    'viewSelect' => '4',
                    'startView' => '4'
                ]
            ])
            ?>
        </div>
        <div class="col-md-3">
            <?= $form->field($model, 'wms_check_month',[
                'template' => "{input}",
            ])->label('月份')->widget(\kartik\datetime\DateTimePicker::classname(), [
                'options' => [
                    'placeholder' => '选择月份',
                    'value' => $model->wms_check_month
                ],
                'readonly' => false,
                'pluginOptions' => [
                    'autoclose' => true,
                    'format' => 'mm',
                    'minView' => 3,
                    'maxView' => 4,
                    'viewSelect' => '4',
                    'startView' => '3'
                ]
            ])
            ?>
        </div>

        <div class="col-md-3">
            <?= Html::submitButton(Yii::t('app', '搜索'), ['class' => 'btn btn-primary']) ?>
        </div>
    </div>
    <?php ActiveForm::end(); ?>

</div>

backend/views/wms-check/view.php

<?php

use yii\helpers\Html;
use yii\widgets\DetailView;

$this->title = '库存盘点清单';
$this->params['breadcrumbs'][] = ['label' => '库存盘点清单', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
$this->params['action_type'] = "查看";

$this->registerCssFile("css/css.css",['depends' => ['dmstr\web\AdminLteAsset']]);
$this->registerCssFile(Yii::$app->urlManager->baseUrl .'/css/default_view_page.css');

?>
<div class="wms-check-view hg_default-view">
    <table class="table table-bordered" style="table-layout:fixed;">
        <tr style="background-color: #F1F1F1;">
            <td colspan="12" class="type_title title_create">查看
                <ul class="nav pull-right">
                    <?= Html::a('返回', ['index'], ['class' => 'default_title-btn']) ?>
                </ul>
            </td>
        </tr>
        <tr>
            <td colspan="12" class="type_title">基本信息</td>
        </tr>
        <tr>
            <td colspan="1" class="item-label">
                <label class="control-label">申请编号</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->wms_check_code; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">加工基地</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->common_producer_info_name; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">年份</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->wms_check_year; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">月份</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->wms_check_month; ?>
            </td>
        </tr>
        <tr>
            <td colspan="1" class="item-label">
                <label class="control-label">物料类型</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->common_producer_herb_type == 1 ? '原料' : '成品'; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">盘点人</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->wms_check_user_name; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">复核人</label>
            </td>
            <td colspan="2" class="item-value">
                <?= $model->wms_check_redo_user_name; ?>
            </td>
            <td colspan="1" class="item-label">
                <label class="control-label">盘点日期</label>
            </td>
            <td colspan="2" class="item-value">
                <?= date('Y年m月d日', $model->wms_check_at); ?>
            </td>
        </tr>
        <tr>
            <td colspan="1" class="item-label">
                <label class="control-label">备注</label>
            </td>
            <td colspan="11" class="item-value">
                <?= $model->wms_check_note; ?>
            </td>
        </tr>

        <tr><td colspan="12" class="type_title">库存清单</td></tr>
        <tr>
            <td colspan="1" class="item-label"><label class="control-label">存货类别</label></td>
            <td colspan="1" class="item-label"><label class="control-label">存货名称</label></td>
            <td colspan="1" class="item-label"><label class="control-label">等级</label></td>
            <td colspan="1" class="item-label"><label class="control-label">规格</label></td>
            <td colspan="1" class="item-label"><label class="control-label">单价(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">账面重量(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">账面金额(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点重量(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点金额(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点重量差异(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点金额差异(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点差异说明</label></td>
        </tr>
        <?php foreach ($detailList as $detail){ ?>
            <tr>
                <td colspan="1"><?= $detail->common_producer_herb_type == 1 ? '原料':'成品' ?></td>
                <td colspan="1"><?= $detail->common_producer_herb_info_name ?></td>
                <td colspan="1"><?= $detail->common_producer_herb_grade_info_name ?></td>
                <td colspan="1"><?= $detail->common_producer_herb_grade_info_spec_name ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_unit_price) ? '' : \common\models\Base::moneyBcdiv($detail->wms_check_detail_unit_price) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_info_weight) ? '' : \common\models\Base::weightBcdiv($detail->wms_check_detail_info_weight) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_info_sum_price) ? '' : \common\models\Base::moneyBcdiv($detail->wms_check_detail_info_sum_price) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_check_weight) ? '' : \common\models\Base::weightBcdiv($detail->wms_check_detail_check_weight) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_check_sum_price) ? '' : \common\models\Base::moneyBcdiv($detail->wms_check_detail_check_sum_price) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_diff_weight) ? '' : \common\models\Base::weightBcdiv($detail->wms_check_detail_diff_weight) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_diff_sum_price) ? '' : \common\models\Base::moneyBcdiv($detail->wms_check_detail_diff_sum_price) ?></td>
                <td colspan="1"><?= empty($detail->wms_check_detail_diff_note) ? '' : $detail->wms_check_detail_diff_note ?></td>
            </tr>
        <?php } ?>
    </table>
</div>

backend/views/wms-check/create.php

<?php

use yii\helpers\Html;

$this->registerCssFile("css/css.css",['depends' => ['dmstr\web\AdminLteAsset']]);
$this->title = Yii::t('app', '库存盘点清单');
$this->params['breadcrumbs'][] = ['label' => '库存盘点清单', 'url' => ['index']];
$this->params['breadcrumbs'][] = "新建";

?>
<div class="wms-check-create">

    <?= $this->render('_form', [
        'model' => $model,
        'stock_list'=>$stock_list,
    ]) ?>

</div>

backend/views/wms-check/update.php

<?php

use yii\helpers\Html;

$this->registerCssFile("css/css.css",['depends' => ['dmstr\web\AdminLteAsset']]);
$this->title = Yii::t('app', '库存盘点清单');
$this->params['breadcrumbs'][] = ['label' => '库存盘点清单', 'url' => ['index']];
$this->params['breadcrumbs'][] = "编辑";
?>
<div class="wms-check-update">

    <?= $this->render('_form', [
        'model' => $model,
        'detailList'=>$detailList,
    ]) ?>

</div>

  

backend/views/wms-check/_form.php

<?php
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
use kartik\widgets\ActiveForm;
use kartik\widgets\Select2;

$this->registerCssFile(Yii::$app->urlManager->baseUrl .'/css/default_form_page.css');
?>

<div class="wms-check-form default_page-form">
    <?php $form = ActiveForm::begin([
        'options'=>['class' => 'form-horizontal'],
        'fieldConfig' => [
            'template' => '{input}{error}',
            'options' => ['class' => 'form-field'],
        ],
    ]); ?>
    <table class="table table-bordered">
        <tr style="background-color: #F1F1F1;">
            <td colspan="12" class="type_title title_create"><?php echo $model->isNewRecord ? Yii::t('app', '新建') : Yii::t('app', '编辑') ?>
                <ul class="nav pull-right">
                    <?= Html::submitButton('保存', ['class' => 'btn btn-success-nav']) ?>
                    <?= Html::a('返回', ['index'], ['class' => 'divider-vertical']) ?>
                </ul>
            </td>
        </tr>
        <tr>
            <td colspan="12" class="type_title">基本信息</td>
        </tr>
        <tr>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_code">申请编号</label>
            </td>
            <td colspan="2">
                <?php
                echo $form->field($model, 'wms_check_code')->textInput(['readonly' => true])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-common_producer_info_id">加工基地</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'common_producer_info_id')->widget(\kartik\select2\Select2::className(), [
                    'data' => \yii\helpers\ArrayHelper::map(core\models\CommonProducerInfo::getCommonProducerInfoList(),'division_id','common_producer_info_name'),
                    'options' => ['placeholder' => '请选择加工基地', 'disabled'=>true],
                    'hideSearch' => true,
                    'pluginOptions' => ['allowClear' => true, ],
                    'pluginEvents' => [
                        "select2:select" => 'function() {
                            var url = "' . Url::to(["user/get-common-producer-people-info-list"]) . '";
                            var common_producer_info_id = $(this).val();
                            var This = $(this);
                            $.get(url, {"common_producer_info_id":common_producer_info_id}, function (data) {
                                html = \'<option value="">选择盘库人</option>\';
                                $(data.results).each(function(i, item){
                                    tempOption = \'<option value="_userid_">_username_</option>\';
                                    html += tempOption.replace(/_userid_/g, item.id).replace(/_username_/g, item.text);
                                });
                                $("#wmscheck-wms_check_user_id").html(html);
                            }, "json");
                        }',
                    ]
                ])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_at">年份</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'wms_check_year')->widget(\kartik\datetime\DateTimePicker::classname(), [
                    'options' => [
                        'placeholder' => '选择年份',
                        'value' =>$model->wms_check_year
                    ],
                    'readonly' => false,
                    'pluginOptions' => [
                        'autoclose' => true,
                        'format' => 'yyyy',
                        'minView' => 4,
                        'maxView' => 4,
                        'viewSelect' => '4',
                        'startView' => '4'
                    ]
                ])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_at">月份</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'wms_check_month')->widget(\kartik\datetime\DateTimePicker::classname(), [
                    'options' => [
                        'placeholder' => '选择月份',
                        'value' => $model->wms_check_month
                    ],
                    'readonly' => false,
                    'pluginOptions' => [
                        'autoclose' => true,
                        'format' => 'mm',
                        'minView' => 3,
                        'maxView' => 4,
                        'viewSelect' => '4',
                        'startView' => '3'
                    ]
                ])
                ?>
            </td>
        </tr>
        <tr>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_herb_type">物料类型</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'common_producer_herb_type')->widget(Select2::className(), [
                    'data' => [1=>'原料', 2=>'成品'],
                    'options' => [
                        'placeholder' => '请选择物料类型',
                    ],
                    'pluginOptions' => ['allowClear' => true],
                ])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_user_id">盘库人</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'wms_check_user_id')->widget(Select2::className(), [
                    'data' => \core\models\User::getUserOptionsByConversionBaseId(\core\models\Division::getTopDivisionId(Yii::$app->user->identity->division_id,true)),
                    'options' => [
                        'placeholder' => '请选择盘库人',
                    ],
                    'pluginOptions' => ['allowClear' => true],
                ])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_redo_user_id">复核人</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'wms_check_redo_user_id')->widget(Select2::className(), [
                    'data' => \core\models\User::getUserOptionsByConversionBaseId(\core\models\Division::getTopDivisionId(Yii::$app->user->identity->division_id,true)),
                    'options' => [
                        'placeholder' => '请选择复核人',
                    ],
                    'pluginOptions' => ['allowClear' => true],
                ])
                ?>
            </td>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_at">盘库日期</label>
            </td>
            <td colspan="2">
                <?= $form->field($model, 'wms_check_at')->widget(\kartik\datetime\DateTimePicker::classname(), [
                    'options' => [
                        'placeholder' => '盘库日期',
                        'value' => ($model->wms_check_at != null) ? date("Y-m-d", $model->wms_check_at) : ''
                    ],
                    'readonly' => false,
                    'pluginOptions' => [
                        'autoclose' => true,
                        'format' => 'yyyy-mm-dd',
                        'minView' => 4,
                        'maxView' => 4,
                    ]
                ])
                ?>
            </td>
        </tr>
        <tr>
            <td class="item-label">
                <label class="control-label" for="wmscheck-wms_check_note">备注</label>
            </td>
            <td colspan="11" class="note">
                <?= $form->field($model, 'wms_check_note')->textarea(['maxlength' => true]) ?>
            </td>
        </tr>
        <tr>
            <td colspan="12" class="type_title">库存清单</td>
        </tr>

        <tr>
            <td colspan="1" class="item-label"><label class="control-label">存货类别</label></td>
            <td colspan="1" class="item-label"><label class="control-label">存货名称</label></td>
            <td colspan="1" class="item-label"><label class="control-label">等级</label></td>
            <td colspan="1" class="item-label"><label class="control-label">规格</label></td>
            <td colspan="1" class="item-label"><label class="control-label">单价(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">账面重量(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">账面金额(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点重量(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点金额(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点重量差异(KG)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点金额差异(元)</label></td>
            <td colspan="1" class="item-label"><label class="control-label">盘点差异说明</label></td>
        </tr>
        <?php if($model->isNewRecord){ ?>
        <?php foreach ($stock_list as $stock){ ?>
        <tr>
            <td colspan="1"><?= $stock['common_producer_material_type_info_id'] == 1 ? '原料' : '成品' ?></td>
            <td colspan="1"><?= $stock['common_producer_herb_info_name'] ?></td>
            <td colspan="1"><?= $stock['common_producer_herb_grade_name'] ?></td>
            <td colspan="1"><?= $stock['common_producer_herb_grade_info_spec_name'] ?></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
            <td colspan="1"></td>
        </tr>
        <?php } ?>
        <?php } ?>
        <?php if(!$model->isNewRecord && isset($detailList)){ ?>
            <?php foreach ($detailList as $detail){ ?>
                <tr>
                    <td colspan="1" style="display: none;"><input type="hidden" name="WmsCheckDetail[id][]" value="<?= $detail->id ?>"></td>
                    <td colspan="1"><?= $detail->common_producer_herb_type == 1 ? '原料':'成品' ?></td>
                    <td colspan="1"><?= $detail->common_producer_info_name ?></td>
                    <td colspan="1"><?= $detail->common_producer_herb_grade_info_name ?></td>
                    <td colspan="1"><?= $detail->common_producer_herb_grade_info_spec_name ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_unit_price[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0', 'value'=>\common\models\Base::moneyBcdiv($detail->wms_check_detail_unit_price)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_info_weight[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0', 'value'=>\common\models\Base::weightBcdiv($detail->wms_check_detail_info_weight)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_info_sum_price[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0','value'=>\common\models\Base::moneyBcdiv($detail->wms_check_detail_info_sum_price)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_check_weight[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0', 'value'=>\common\models\Base::weightBcdiv($detail->wms_check_detail_check_weight)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_check_sum_price[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0','value'=>\common\models\Base::moneyBcdiv($detail->wms_check_detail_check_sum_price)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_diff_weight[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0', 'value'=>\common\models\Base::weightBcdiv($detail->wms_check_detail_diff_weight)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_diff_sum_price[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0','value'=>\common\models\Base::moneyBcdiv($detail->wms_check_detail_diff_sum_price)]); ?></td>
                    <td colspan="1"><?= $form->field($detail, 'wms_check_detail_diff_note[]')->textInput(['type' => 'number', 'step' => '0.01', 'min' => '0', 'value'=>$detail->wms_check_detail_diff_note]); ?></td>
                </tr>
            <?php } ?>
        <?php } ?>
        <tr>
            <td colspan="12" class="type_title">
                <div class="button-group">
                    <?= Html::submitButton('保存', ['class' => 'btn btn-success btn-size']) ?>
                    <?= Html::a('返回', ['index'], ['class' => 'btn btn-default btn-size']) ?>
                </div>
            </td>
        </tr>
    </table>
    <?php ActiveForm::end(); ?>
</div>