linyaostalker
5 years ago
20 changed files with 3909 additions and 0 deletions
-
255vendor/iron/generators/controller/Generator.php
-
27vendor/iron/generators/controller/default/controller.php
-
20vendor/iron/generators/controller/default/view.php
-
9vendor/iron/generators/controller/form.php
-
555vendor/iron/generators/crud/Generator.php
-
201vendor/iron/generators/crud/default/controller.php
-
160vendor/iron/generators/crud/default/search.php
-
43vendor/iron/generators/crud/default/views/_form.php
-
57vendor/iron/generators/crud/default/views/_search.php
-
27vendor/iron/generators/crud/default/views/create.php
-
41vendor/iron/generators/crud/default/views/index.php
-
38vendor/iron/generators/crud/default/views/update.php
-
49vendor/iron/generators/crud/default/views/view.php
-
17vendor/iron/generators/crud/form.php
-
995vendor/iron/generators/model/Generator.php
-
125vendor/iron/generators/model/default/model.php
-
56vendor/iron/generators/model/default/query.php
-
30vendor/iron/generators/model/form.php
-
246vendor/iron/grid/ActionColumn.php
-
958vendor/iron/widget/Excel.php
@ -0,0 +1,255 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @link http://www.yiiframework.com/ |
||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
|
* @license http://www.yiiframework.com/license/ |
||||
|
*/ |
||||
|
|
||||
|
namespace yii\gii\generators\controller; |
||||
|
|
||||
|
use Yii; |
||||
|
use yii\gii\CodeFile; |
||||
|
use yii\helpers\Html; |
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/** |
||||
|
* This generator will generate a controller and one or a few action view files. |
||||
|
* |
||||
|
* @property array $actionIDs An array of action IDs entered by the user. This property is read-only. |
||||
|
* @property string $controllerFile The controller class file path. This property is read-only. |
||||
|
* @property string $controllerID The controller ID. This property is read-only. |
||||
|
* @property string $controllerNamespace The namespace of the controller class. This property is read-only. |
||||
|
* @property string $controllerSubPath The controller sub path. This property is read-only. |
||||
|
* |
||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
|
* @since 2.0 |
||||
|
*/ |
||||
|
class Generator extends \yii\gii\Generator |
||||
|
{ |
||||
|
/** |
||||
|
* @var string the controller class name |
||||
|
*/ |
||||
|
public $controllerClass; |
||||
|
/** |
||||
|
* @var string the controller's view path |
||||
|
*/ |
||||
|
public $viewPath; |
||||
|
/** |
||||
|
* @var string the base class of the controller |
||||
|
*/ |
||||
|
public $baseClass = 'yii\web\Controller'; |
||||
|
/** |
||||
|
* @var string list of action IDs separated by commas or spaces |
||||
|
*/ |
||||
|
public $actions = 'index'; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getName() |
||||
|
{ |
||||
|
return 'Controller Generator'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getDescription() |
||||
|
{ |
||||
|
return 'This generator helps you to quickly generate a new controller class with |
||||
|
one or several controller actions and their corresponding views.'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function rules() |
||||
|
{ |
||||
|
return array_merge(parent::rules(), [ |
||||
|
[['controllerClass', 'actions', 'baseClass'], 'filter', 'filter' => 'trim'], |
||||
|
[['controllerClass', 'baseClass'], 'required'], |
||||
|
['controllerClass', 'match', 'pattern' => '/^[\w\\\\]*Controller$/', 'message' => 'Only word characters and backslashes are allowed, and the class name must end with "Controller".'], |
||||
|
['controllerClass', 'validateNewClass'], |
||||
|
['baseClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'], |
||||
|
['actions', 'match', 'pattern' => '/^[a-z][a-z0-9\\-,\\s]*$/', 'message' => 'Only a-z, 0-9, dashes (-), spaces and commas are allowed.'], |
||||
|
['viewPath', 'safe'], |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function attributeLabels() |
||||
|
{ |
||||
|
return [ |
||||
|
'baseClass' => 'Base Class', |
||||
|
'controllerClass' => 'Controller Class', |
||||
|
'viewPath' => 'View Path', |
||||
|
'actions' => 'Action IDs', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function requiredTemplates() |
||||
|
{ |
||||
|
return [ |
||||
|
'controller.php', |
||||
|
'view.php', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function stickyAttributes() |
||||
|
{ |
||||
|
return ['baseClass']; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function hints() |
||||
|
{ |
||||
|
return [ |
||||
|
'controllerClass' => 'This is the name of the controller class to be generated. You should |
||||
|
provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>), |
||||
|
and class name should be in CamelCase ending with the word <code>Controller</code>. Make sure the class |
||||
|
is using the same namespace as specified by your application\'s controllerNamespace property.', |
||||
|
'actions' => 'Provide one or multiple action IDs to generate empty action method(s) in the controller. Separate multiple action IDs with commas or spaces. |
||||
|
Action IDs should be in lower case. For example: |
||||
|
<ul> |
||||
|
<li><code>index</code> generates <code>actionIndex()</code></li> |
||||
|
<li><code>create-order</code> generates <code>actionCreateOrder()</code></li> |
||||
|
</ul>', |
||||
|
'viewPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g., |
||||
|
<code>/var/www/basic/controllers/views/order</code>, <code>@app/views/order</code>. If not set, it will default |
||||
|
to <code>@app/views/ControllerID</code>', |
||||
|
'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.', |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function successMessage() |
||||
|
{ |
||||
|
return 'The controller has been generated successfully.' . $this->getLinkToTry(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* This method returns a link to try controller generated |
||||
|
* @see https://github.com/yiisoft/yii2-gii/issues/182 |
||||
|
* @return string |
||||
|
* @since 2.0.6 |
||||
|
*/ |
||||
|
private function getLinkToTry() |
||||
|
{ |
||||
|
if (strpos($this->controllerNamespace, Yii::$app->controllerNamespace) !== 0) { |
||||
|
return ''; |
||||
|
} |
||||
|
|
||||
|
$actions = $this->getActionIDs(); |
||||
|
if (in_array('index', $actions, true)) { |
||||
|
$route = $this->getControllerSubPath() . $this->getControllerID() . '/index'; |
||||
|
} else { |
||||
|
$route = $this->getControllerSubPath() . $this->getControllerID() . '/' . reset($actions); |
||||
|
} |
||||
|
return ' You may ' . Html::a('try it now', Yii::$app->getUrlManager()->createUrl($route), ['target' => '_blank', 'rel' => 'noopener noreferrer']) . '.'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function generate() |
||||
|
{ |
||||
|
$files = []; |
||||
|
|
||||
|
$files[] = new CodeFile( |
||||
|
$this->getControllerFile(), |
||||
|
$this->render('controller.php') |
||||
|
); |
||||
|
|
||||
|
foreach ($this->getActionIDs() as $action) { |
||||
|
$files[] = new CodeFile( |
||||
|
$this->getViewFile($action), |
||||
|
$this->render('view.php', ['action' => $action]) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return $files; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Normalizes [[actions]] into an array of action IDs. |
||||
|
* @return array an array of action IDs entered by the user |
||||
|
*/ |
||||
|
public function getActionIDs() |
||||
|
{ |
||||
|
$actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY)); |
||||
|
sort($actions); |
||||
|
|
||||
|
return $actions; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string the controller class file path |
||||
|
*/ |
||||
|
public function getControllerFile() |
||||
|
{ |
||||
|
return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerClass)) . '.php'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string the controller ID |
||||
|
*/ |
||||
|
public function getControllerID() |
||||
|
{ |
||||
|
$name = StringHelper::basename($this->controllerClass); |
||||
|
return Inflector::camel2id(substr($name, 0, strlen($name) - 10)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* This method will return sub path for controller if it |
||||
|
* is located in subdirectory of application controllers dir |
||||
|
* @see https://github.com/yiisoft/yii2-gii/issues/182 |
||||
|
* @since 2.0.6 |
||||
|
* @return string the controller sub path |
||||
|
*/ |
||||
|
public function getControllerSubPath() |
||||
|
{ |
||||
|
$subPath = ''; |
||||
|
$controllerNamespace = $this->getControllerNamespace(); |
||||
|
if (strpos($controllerNamespace, Yii::$app->controllerNamespace) === 0) { |
||||
|
$subPath = substr($controllerNamespace, strlen(Yii::$app->controllerNamespace)); |
||||
|
$subPath = ($subPath !== '') ? str_replace('\\', '/', substr($subPath, 1)) . '/' : ''; |
||||
|
} |
||||
|
return $subPath; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string $action the action ID |
||||
|
* @return string the action view file path |
||||
|
*/ |
||||
|
public function getViewFile($action) |
||||
|
{ |
||||
|
if (empty($this->viewPath)) { |
||||
|
return Yii::getAlias('@app/views/' . $this->getControllerSubPath() . $this->getControllerID() . "/$action.php"); |
||||
|
} |
||||
|
|
||||
|
return Yii::getAlias(str_replace('\\', '/', $this->viewPath) . "/$action.php"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string the namespace of the controller class |
||||
|
*/ |
||||
|
public function getControllerNamespace() |
||||
|
{ |
||||
|
$name = StringHelper::basename($this->controllerClass); |
||||
|
return ltrim(substr($this->controllerClass, 0, - (strlen($name) + 1)), '\\'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating a controller class file. |
||||
|
*/ |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\controller\Generator */ |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
namespace <?= $generator->getControllerNamespace() ?>;
|
||||
|
|
||||
|
class <?= StringHelper::basename($generator->controllerClass) ?> extends <?= '\\' . trim($generator->baseClass, '\\') . "\n" ?>
|
||||
|
{ |
||||
|
<?php foreach ($generator->getActionIDs() as $action): ?>
|
||||
|
public function action<?= Inflector::id2camel($action) ?>()
|
||||
|
{ |
||||
|
return $this->render('<?= $action ?>'); |
||||
|
} |
||||
|
|
||||
|
<?php endforeach; ?>
|
||||
|
|
||||
|
|
@ -0,0 +1,20 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating an action view file. |
||||
|
*/ |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\controller\Generator */ |
||||
|
/* @var $action string the action ID */ |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
/* @var $this yii\web\View */ |
||||
|
<?= "?>" ?>
|
||||
|
|
||||
|
<h1><?= $generator->getControllerSubPath() . $generator->getControllerID() . '/' . $action ?></h1>
|
||||
|
|
||||
|
<p> |
||||
|
You may change the content of this page by modifying |
||||
|
the file <code><?= '<?=' ?> __FILE__; ?></code>.
|
||||
|
</p> |
@ -0,0 +1,9 @@ |
|||||
|
<?php |
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $form yii\widgets\ActiveForm */ |
||||
|
/* @var $generator yii\gii\generators\controller\Generator */ |
||||
|
|
||||
|
echo $form->field($generator, 'controllerClass'); |
||||
|
echo $form->field($generator, 'actions'); |
||||
|
echo $form->field($generator, 'viewPath'); |
||||
|
echo $form->field($generator, 'baseClass'); |
@ -0,0 +1,555 @@ |
|||||
|
<?php |
||||
|
|
||||
|
/* |
||||
|
* The MIT License |
||||
|
* |
||||
|
* Copyright 2019 Blobt. |
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to deal |
||||
|
* in the Software without restriction, including without limitation the rights |
||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
* copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
* THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
namespace iron\generators\crud; |
||||
|
|
||||
|
use Yii; |
||||
|
use yii\db\ActiveRecord; |
||||
|
use yii\db\BaseActiveRecord; |
||||
|
use yii\db\Schema; |
||||
|
use yii\gii\CodeFile; |
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\VarDumper; |
||||
|
use yii\web\Controller; |
||||
|
|
||||
|
/** |
||||
|
* Description of Generator |
||||
|
* |
||||
|
* @author Blobt |
||||
|
* @email 380255922@qq.com |
||||
|
* @created Oct 6, 2019 |
||||
|
*/ |
||||
|
class Generator extends \yii\gii\Generator { |
||||
|
|
||||
|
public $modelClass; |
||||
|
public $controllerClass; |
||||
|
public $viewPath; |
||||
|
public $baseControllerClass = 'yii\web\Controller'; |
||||
|
public $indexWidgetType = 'grid'; |
||||
|
public $searchModelClass = ''; |
||||
|
|
||||
|
public $enablePjax = false; |
||||
|
public $strictInflector = true; |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getName() { |
||||
|
return 'CRUD Generator'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getDescription() { |
||||
|
return 'This generator generates a controller and views that implement CRUD (Create, Read, Update, Delete) |
||||
|
operations for the specified data model.'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function rules() { |
||||
|
return array_merge(parent::rules(), [ |
||||
|
[['controllerClass', 'modelClass', 'searchModelClass', 'baseControllerClass'], 'filter', 'filter' => 'trim'], |
||||
|
[['modelClass', 'controllerClass', 'baseControllerClass', 'indexWidgetType'], 'required'], |
||||
|
[['searchModelClass'], 'compare', 'compareAttribute' => 'modelClass', 'operator' => '!==', 'message' => 'Search Model Class must not be equal to Model Class.'], |
||||
|
[['modelClass', 'controllerClass', 'baseControllerClass', 'searchModelClass'], 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'], |
||||
|
[['modelClass'], 'validateClass', 'params' => ['extends' => BaseActiveRecord::className()]], |
||||
|
[['baseControllerClass'], 'validateClass', 'params' => ['extends' => Controller::className()]], |
||||
|
[['controllerClass'], 'match', 'pattern' => '/Controller$/', 'message' => 'Controller class name must be suffixed with "Controller".'], |
||||
|
[['controllerClass'], 'match', 'pattern' => '/(^|\\\\)[A-Z][^\\\\]+Controller$/', 'message' => 'Controller class name must start with an uppercase letter.'], |
||||
|
[['controllerClass', 'searchModelClass'], 'validateNewClass'], |
||||
|
[['indexWidgetType'], 'in', 'range' => ['grid', 'list']], |
||||
|
[['modelClass'], 'validateModelClass'], |
||||
|
[['enableI18N', 'enablePjax'], 'boolean'], |
||||
|
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false], |
||||
|
['viewPath', 'safe'], |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function attributeLabels() { |
||||
|
return array_merge(parent::attributeLabels(), [ |
||||
|
'modelClass' => 'Model Class', |
||||
|
'controllerClass' => 'Controller Class', |
||||
|
'viewPath' => 'View Path', |
||||
|
'baseControllerClass' => 'Base Controller Class', |
||||
|
'indexWidgetType' => 'Widget Used in Index Page', |
||||
|
'searchModelClass' => 'Search Model Class', |
||||
|
'enablePjax' => 'Enable Pjax', |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function hints() { |
||||
|
return array_merge(parent::hints(), [ |
||||
|
'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon. |
||||
|
You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.', |
||||
|
'controllerClass' => 'This is the name of the controller class to be generated. You should |
||||
|
provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>), |
||||
|
and class name should be in CamelCase with an uppercase first letter. Make sure the class |
||||
|
is using the same namespace as specified by your application\'s controllerNamespace property.', |
||||
|
'viewPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g., |
||||
|
<code>/var/www/basic/controllers/views/post</code>, <code>@app/views/post</code>. If not set, it will default |
||||
|
to <code>@app/views/ControllerID</code>', |
||||
|
'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from. |
||||
|
You should provide a fully qualified class name, e.g., <code>yii\web\Controller</code>.', |
||||
|
'indexWidgetType' => 'This is the widget type to be used in the index page to display list of the models. |
||||
|
You may choose either <code>GridView</code> or <code>ListView</code>', |
||||
|
'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully |
||||
|
qualified namespaced class name, e.g., <code>app\models\PostSearch</code>.', |
||||
|
'enablePjax' => 'This indicates whether the generator should wrap the <code>GridView</code> or <code>ListView</code> |
||||
|
widget on the index page with <code>yii\widgets\Pjax</code> widget. Set this to <code>true</code> if you want to get |
||||
|
sorting, filtering and pagination without page refreshing.', |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function requiredTemplates() { |
||||
|
return ['controller.php']; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function stickyAttributes() { |
||||
|
return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'indexWidgetType']); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if model class is valid |
||||
|
*/ |
||||
|
public function validateModelClass() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$pk = $class::primaryKey(); |
||||
|
if (empty($pk)) { |
||||
|
$this->addError('modelClass', "The table associated with $class must have primary key(s)."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function generate() { |
||||
|
$controllerFile = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->controllerClass, '\\')) . '.php'); |
||||
|
|
||||
|
$files = [ |
||||
|
new CodeFile($controllerFile, $this->render('controller.php')), |
||||
|
]; |
||||
|
|
||||
|
if (!empty($this->searchModelClass)) { |
||||
|
$searchModel = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->searchModelClass, '\\') . '.php')); |
||||
|
$files[] = new CodeFile($searchModel, $this->render('search.php')); |
||||
|
} |
||||
|
|
||||
|
$viewPath = $this->getViewPath(); |
||||
|
$templatePath = $this->getTemplatePath() . '/views'; |
||||
|
foreach (scandir($templatePath) as $file) { |
||||
|
if (empty($this->searchModelClass) && $file === '_search.php') { |
||||
|
continue; |
||||
|
} |
||||
|
if (is_file($templatePath . '/' . $file) && pathinfo($file, PATHINFO_EXTENSION) === 'php') { |
||||
|
$files[] = new CodeFile("$viewPath/$file", $this->render("views/$file")); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $files; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string the controller ID (without the module ID prefix) |
||||
|
*/ |
||||
|
public function getControllerID() { |
||||
|
$pos = strrpos($this->controllerClass, '\\'); |
||||
|
$class = substr(substr($this->controllerClass, $pos + 1), 0, -10); |
||||
|
|
||||
|
return Inflector::camel2id($class, '-', $this->strictInflector); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string the controller view path |
||||
|
*/ |
||||
|
public function getViewPath() { |
||||
|
if (empty($this->viewPath)) { |
||||
|
return Yii::getAlias('@app/views/' . $this->getControllerID()); |
||||
|
} |
||||
|
|
||||
|
return Yii::getAlias(str_replace('\\', '/', $this->viewPath)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function getNameAttribute() { |
||||
|
foreach ($this->getColumnNames() as $name) { |
||||
|
if (!strcasecmp($name, 'name') || !strcasecmp($name, 'title')) { |
||||
|
return $name; |
||||
|
} |
||||
|
} |
||||
|
/* @var $class \yii\db\ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$pk = $class::primaryKey(); |
||||
|
|
||||
|
return $pk[0]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates code for active field |
||||
|
* @param string $attribute |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function generateActiveField($attribute) { |
||||
|
$tableSchema = $this->getTableSchema(); |
||||
|
if ($tableSchema === false || !isset($tableSchema->columns[$attribute])) { |
||||
|
if (preg_match('/^(password|pass|passwd|passcode)$/i', $attribute)) { |
||||
|
return "\$form->field(\$model, '$attribute')->passwordInput()"; |
||||
|
} |
||||
|
|
||||
|
return "\$form->field(\$model, '$attribute')"; |
||||
|
} |
||||
|
$column = $tableSchema->columns[$attribute]; |
||||
|
if ($column->phpType === 'boolean') { |
||||
|
return "\$form->field(\$model, '$attribute')->checkbox()"; |
||||
|
} |
||||
|
|
||||
|
if ($column->type === 'text') { |
||||
|
return "\$form->field(\$model, '$attribute')->textarea(['rows' => 6])"; |
||||
|
} |
||||
|
|
||||
|
if (preg_match('/^(password|pass|passwd|passcode)$/i', $column->name)) { |
||||
|
$input = 'passwordInput'; |
||||
|
} else { |
||||
|
$input = 'textInput'; |
||||
|
} |
||||
|
|
||||
|
if (is_array($column->enumValues) && count($column->enumValues) > 0) { |
||||
|
$dropDownOptions = []; |
||||
|
foreach ($column->enumValues as $enumValue) { |
||||
|
$dropDownOptions[$enumValue] = Inflector::humanize($enumValue); |
||||
|
} |
||||
|
return "\$form->field(\$model, '$attribute')->dropDownList(" |
||||
|
. preg_replace("/\n\s*/", ' ', VarDumper::export($dropDownOptions)) . ", ['prompt' => ''])"; |
||||
|
} |
||||
|
|
||||
|
if ($column->phpType !== 'string' || $column->size === null) { |
||||
|
return "\$form->field(\$model, '$attribute')->$input()"; |
||||
|
} |
||||
|
|
||||
|
return "\$form->field(\$model, '$attribute')->$input(['maxlength' => true])"; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates column format |
||||
|
* @param \yii\db\ColumnSchema $column |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function generateColumnFormat($column) { |
||||
|
if ($column->phpType === 'boolean') { |
||||
|
return 'boolean'; |
||||
|
} |
||||
|
|
||||
|
if ($column->type === 'text') { |
||||
|
return 'ntext'; |
||||
|
} |
||||
|
|
||||
|
if (stripos($column->name, 'time') !== false && $column->phpType === 'integer') { |
||||
|
return 'datetime'; |
||||
|
} |
||||
|
|
||||
|
if (stripos($column->name, 'email') !== false) { |
||||
|
return 'email'; |
||||
|
} |
||||
|
|
||||
|
if (preg_match('/(\b|[_-])url(\b|[_-])/i', $column->name)) { |
||||
|
return 'url'; |
||||
|
} |
||||
|
|
||||
|
return 'text'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates validation rules for the search model. |
||||
|
* @return array the generated validation rules |
||||
|
*/ |
||||
|
public function generateSearchRules() |
||||
|
{ |
||||
|
if (($table = $this->getTableSchema()) === false) { |
||||
|
return ["[['" . implode("', '", $this->getColumnNames()) . "'], 'safe']"]; |
||||
|
} |
||||
|
$types = []; |
||||
|
foreach ($table->columns as $column) { |
||||
|
switch ($column->type) { |
||||
|
case Schema::TYPE_TINYINT: |
||||
|
case Schema::TYPE_SMALLINT: |
||||
|
case Schema::TYPE_INTEGER: |
||||
|
case Schema::TYPE_BIGINT: |
||||
|
$types['integer'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_BOOLEAN: |
||||
|
$types['boolean'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_FLOAT: |
||||
|
case Schema::TYPE_DOUBLE: |
||||
|
case Schema::TYPE_DECIMAL: |
||||
|
case Schema::TYPE_MONEY: |
||||
|
$types['number'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_DATE: |
||||
|
case Schema::TYPE_TIME: |
||||
|
case Schema::TYPE_DATETIME: |
||||
|
case Schema::TYPE_TIMESTAMP: |
||||
|
default: |
||||
|
$types['safe'][] = $column->name; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$rules = []; |
||||
|
foreach ($types as $type => $columns) { |
||||
|
$rules[] = "[['" . implode("', '", $columns) . "'], '$type']"; |
||||
|
} |
||||
|
|
||||
|
return $rules; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return array searchable attributes |
||||
|
*/ |
||||
|
public function getSearchAttributes() |
||||
|
{ |
||||
|
return $this->getColumnNames(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates the attribute labels for the search model. |
||||
|
* @return array the generated attribute labels (name => label) |
||||
|
*/ |
||||
|
public function generateSearchLabels() |
||||
|
{ |
||||
|
/* @var $model \yii\base\Model */ |
||||
|
$model = new $this->modelClass(); |
||||
|
$attributeLabels = $model->attributeLabels(); |
||||
|
$labels = []; |
||||
|
foreach ($this->getColumnNames() as $name) { |
||||
|
if (isset($attributeLabels[$name])) { |
||||
|
$labels[$name] = $attributeLabels[$name]; |
||||
|
} else { |
||||
|
if (!strcasecmp($name, 'id')) { |
||||
|
$labels[$name] = 'ID'; |
||||
|
} else { |
||||
|
$label = Inflector::camel2words($name); |
||||
|
if (!empty($label) && substr_compare($label, ' id', -3, 3, true) === 0) { |
||||
|
$label = substr($label, 0, -3) . ' ID'; |
||||
|
} |
||||
|
$labels[$name] = $label; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $labels; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates search conditions |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function generateSearchConditions() |
||||
|
{ |
||||
|
$columns = []; |
||||
|
if (($table = $this->getTableSchema()) === false) { |
||||
|
$class = $this->modelClass; |
||||
|
/* @var $model \yii\base\Model */ |
||||
|
$model = new $class(); |
||||
|
foreach ($model->attributes() as $attribute) { |
||||
|
$columns[$attribute] = 'unknown'; |
||||
|
} |
||||
|
} else { |
||||
|
foreach ($table->columns as $column) { |
||||
|
$columns[$column->name] = $column->type; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$likeConditions = []; |
||||
|
$hashConditions = []; |
||||
|
foreach ($columns as $column => $type) { |
||||
|
switch ($type) { |
||||
|
case Schema::TYPE_TINYINT: |
||||
|
case Schema::TYPE_SMALLINT: |
||||
|
case Schema::TYPE_INTEGER: |
||||
|
case Schema::TYPE_BIGINT: |
||||
|
case Schema::TYPE_BOOLEAN: |
||||
|
case Schema::TYPE_FLOAT: |
||||
|
case Schema::TYPE_DOUBLE: |
||||
|
case Schema::TYPE_DECIMAL: |
||||
|
case Schema::TYPE_MONEY: |
||||
|
case Schema::TYPE_DATE: |
||||
|
case Schema::TYPE_TIME: |
||||
|
case Schema::TYPE_DATETIME: |
||||
|
case Schema::TYPE_TIMESTAMP: |
||||
|
$hashConditions[] = "'{$column}' => \$this->{$column},"; |
||||
|
break; |
||||
|
default: |
||||
|
$likeKeyword = $this->getClassDbDriverName() === 'pgsql' ? 'ilike' : 'like'; |
||||
|
$likeConditions[] = "->andFilterWhere(['{$likeKeyword}', '{$column}', \$this->{$column}])"; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$conditions = []; |
||||
|
if (!empty($hashConditions)) { |
||||
|
$conditions[] = "\$query->andFilterWhere([\n" |
||||
|
. str_repeat(' ', 12) . implode("\n" . str_repeat(' ', 12), $hashConditions) |
||||
|
. "\n" . str_repeat(' ', 8) . "]);\n"; |
||||
|
} |
||||
|
if (!empty($likeConditions)) { |
||||
|
$conditions[] = "\$query" . implode("\n" . str_repeat(' ', 12), $likeConditions) . ";\n"; |
||||
|
} |
||||
|
|
||||
|
return $conditions; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates URL parameters |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function generateUrlParams() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$pks = $class::primaryKey(); |
||||
|
if (count($pks) === 1) { |
||||
|
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) { |
||||
|
return "'id' => (string)\$model->{$pks[0]}"; |
||||
|
} |
||||
|
|
||||
|
return "'id' => \$model->{$pks[0]}"; |
||||
|
} |
||||
|
|
||||
|
$params = []; |
||||
|
foreach ($pks as $pk) { |
||||
|
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) { |
||||
|
$params[] = "'$pk' => (string)\$model->$pk"; |
||||
|
} else { |
||||
|
$params[] = "'$pk' => \$model->$pk"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return implode(', ', $params); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates action parameters |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function generateActionParams() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$pks = $class::primaryKey(); |
||||
|
if (count($pks) === 1) { |
||||
|
return '$id'; |
||||
|
} |
||||
|
|
||||
|
return '$' . implode(', $', $pks); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates parameter tags for phpdoc |
||||
|
* @return array parameter tags for phpdoc |
||||
|
*/ |
||||
|
public function generateActionParamComments() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$pks = $class::primaryKey(); |
||||
|
if (($table = $this->getTableSchema()) === false) { |
||||
|
$params = []; |
||||
|
foreach ($pks as $pk) { |
||||
|
$params[] = '@param ' . (strtolower(substr($pk, -2)) === 'id' ? 'integer' : 'string') . ' $' . $pk; |
||||
|
} |
||||
|
|
||||
|
return $params; |
||||
|
} |
||||
|
if (count($pks) === 1) { |
||||
|
return ['@param ' . $table->columns[$pks[0]]->phpType . ' $id']; |
||||
|
} |
||||
|
|
||||
|
$params = []; |
||||
|
foreach ($pks as $pk) { |
||||
|
$params[] = '@param ' . $table->columns[$pk]->phpType . ' $' . $pk; |
||||
|
} |
||||
|
|
||||
|
return $params; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns table schema for current model class or false if it is not an active record |
||||
|
* @return bool|\yii\db\TableSchema |
||||
|
*/ |
||||
|
public function getTableSchema() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
if (is_subclass_of($class, 'yii\db\ActiveRecord')) { |
||||
|
return $class::getTableSchema(); |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return array model column names |
||||
|
*/ |
||||
|
public function getColumnNames() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
if (is_subclass_of($class, 'yii\db\ActiveRecord')) { |
||||
|
return $class::getTableSchema()->getColumnNames(); |
||||
|
} |
||||
|
|
||||
|
/* @var $model \yii\base\Model */ |
||||
|
$model = new $class(); |
||||
|
|
||||
|
return $model->attributes(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string|null driver name of modelClass db connection. |
||||
|
* In case db is not instance of \yii\db\Connection null will be returned. |
||||
|
* @since 2.0.6 |
||||
|
*/ |
||||
|
protected function getClassDbDriverName() { |
||||
|
/* @var $class ActiveRecord */ |
||||
|
$class = $this->modelClass; |
||||
|
$db = $class::getDb(); |
||||
|
return $db instanceof \yii\db\Connection ? $db->driverName : null; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,201 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating a CRUD controller class file. |
||||
|
*/ |
||||
|
|
||||
|
use yii\db\ActiveRecordInterface; |
||||
|
use yii\helpers\StringHelper; |
||||
|
use yii\helpers\Inflector; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
$controllerClass = StringHelper::basename($generator->controllerClass); |
||||
|
$modelClass = StringHelper::basename($generator->modelClass); |
||||
|
$searchModelClass = StringHelper::basename($generator->searchModelClass); |
||||
|
if ($modelClass === $searchModelClass) { |
||||
|
$searchModelAlias = $searchModelClass . 'Search'; |
||||
|
} |
||||
|
|
||||
|
/* @var $class ActiveRecordInterface */ |
||||
|
$class = $generator->modelClass; |
||||
|
$pks = $class::primaryKey(); |
||||
|
$urlParams = $generator->generateUrlParams(); |
||||
|
$actionParams = $generator->generateActionParams(); |
||||
|
$actionParamComments = $generator->generateActionParamComments(); |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
namespace <?= StringHelper::dirname(ltrim($generator->controllerClass, '\\')) ?>;
|
||||
|
|
||||
|
use Yii; |
||||
|
use <?= ltrim($generator->modelClass, '\\') ?>;
|
||||
|
<?php if (!empty($generator->searchModelClass)): ?>
|
||||
|
use <?= ltrim($generator->searchModelClass, '\\') . (isset($searchModelAlias) ? " as $searchModelAlias" : "") ?>;
|
||||
|
<?php else: ?>
|
||||
|
use yii\data\ActiveDataProvider; |
||||
|
<?php endif; ?>
|
||||
|
use <?= ltrim($generator->baseControllerClass, '\\') ?>;
|
||||
|
use yii\web\NotFoundHttpException; |
||||
|
use yii\filters\VerbFilter; |
||||
|
|
||||
|
/** |
||||
|
* <?= $controllerClass ?> implements the CRUD actions for <?= $modelClass ?> model.
|
||||
|
*/ |
||||
|
class <?= $controllerClass ?> extends <?= StringHelper::basename($generator->baseControllerClass) . "\n" ?>
|
||||
|
{ |
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function behaviors() |
||||
|
{ |
||||
|
return [ |
||||
|
'verbs' => [ |
||||
|
'class' => VerbFilter::className(), |
||||
|
'actions' => [ |
||||
|
'delete' => ['POST'], |
||||
|
], |
||||
|
], |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Lists all <?= $modelClass ?> models.
|
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function actionIndex() |
||||
|
{ |
||||
|
<?php if (!empty($generator->searchModelClass)): ?>
|
||||
|
$searchModel = new <?= isset($searchModelAlias) ? $searchModelAlias : $searchModelClass ?>();
|
||||
|
$dataProvider = $searchModel->search(Yii::$app->request->queryParams); |
||||
|
|
||||
|
return $this->render('index', [ |
||||
|
'searchModel' => $searchModel, |
||||
|
'dataProvider' => $dataProvider, |
||||
|
'columns' => $searchModel->columns() |
||||
|
]); |
||||
|
<?php else: ?>
|
||||
|
$dataProvider = new ActiveDataProvider([ |
||||
|
'query' => <?= $modelClass ?>::find(),
|
||||
|
]); |
||||
|
|
||||
|
return $this->render('index', [ |
||||
|
'dataProvider' => $dataProvider, |
||||
|
]); |
||||
|
<?php endif; ?>
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Displays a single <?= $modelClass ?> model.
|
||||
|
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
|
||||
|
* @return mixed |
||||
|
* @throws NotFoundHttpException if the model cannot be found |
||||
|
*/ |
||||
|
public function actionView(<?= $actionParams ?>)
|
||||
|
{ |
||||
|
return $this->render('view', [ |
||||
|
'model' => $this->findModel(<?= $actionParams ?>),
|
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Creates a new <?= $modelClass ?> model.
|
||||
|
* If creation is successful, the browser will be redirected to the 'view' page. |
||||
|
* @return mixed |
||||
|
*/ |
||||
|
public function actionCreate() |
||||
|
{ |
||||
|
$model = new <?= $modelClass ?>();
|
||||
|
|
||||
|
if ($model->load(Yii::$app->request->post()) && $model->save()) { |
||||
|
return $this->redirect('index'); |
||||
|
} |
||||
|
|
||||
|
return $this->render('create', [ |
||||
|
'model' => $model, |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Updates an existing <?= $modelClass ?> model.
|
||||
|
* If update is successful, the browser will be redirected to the 'view' page. |
||||
|
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
|
||||
|
* @return mixed |
||||
|
* @throws NotFoundHttpException if the model cannot be found |
||||
|
*/ |
||||
|
public function actionUpdate(<?= $actionParams ?>)
|
||||
|
{ |
||||
|
$model = $this->findModel(<?= $actionParams ?>);
|
||||
|
|
||||
|
if ($model->load(Yii::$app->request->post()) && $model->save()) { |
||||
|
return $this->redirect('index'); |
||||
|
} |
||||
|
|
||||
|
return $this->render('update', [ |
||||
|
'model' => $model, |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Deletes an existing <?= $modelClass ?> model.
|
||||
|
* If deletion is successful, the browser will be redirected to the 'index' page. |
||||
|
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
|
||||
|
* @return mixed |
||||
|
* @throws NotFoundHttpException if the model cannot be found |
||||
|
*/ |
||||
|
public function actionDelete(<?= $actionParams ?>)
|
||||
|
{ |
||||
|
$this->findModel(<?= $actionParams ?>)->delete();
|
||||
|
|
||||
|
return $this->redirect(['index']); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Finds the <?= $modelClass ?> model based on its primary key value.
|
||||
|
* If the model is not found, a 404 HTTP exception will be thrown. |
||||
|
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
|
||||
|
* @return <?= $modelClass ?> the loaded model
|
||||
|
* @throws NotFoundHttpException if the model cannot be found |
||||
|
*/ |
||||
|
protected function findModel(<?= $actionParams ?>)
|
||||
|
{ |
||||
|
<?php |
||||
|
if (count($pks) === 1) { |
||||
|
$condition = '$id'; |
||||
|
} else { |
||||
|
$condition = []; |
||||
|
foreach ($pks as $pk) { |
||||
|
$condition[] = "'$pk' => \$$pk"; |
||||
|
} |
||||
|
$condition = '[' . implode(', ', $condition) . ']'; |
||||
|
} |
||||
|
?>
|
||||
|
if (($model = <?= $modelClass ?>::findOne(<?= $condition ?>)) !== null) {
|
||||
|
return $model; |
||||
|
} |
||||
|
|
||||
|
throw new NotFoundHttpException(<?= $generator->generateString('The requested page does not exist.') ?>);
|
||||
|
} |
||||
|
/** |
||||
|
* @author iron |
||||
|
* 文件导出 |
||||
|
*/ |
||||
|
public function actionExport() |
||||
|
{ |
||||
|
$searchModel = new <?= isset($searchModelAlias) ? $searchModelAlias : $searchModelClass ?>();
|
||||
|
$params = Yii::$app->request->queryParams; |
||||
|
if ($params['page-type'] == 'all') { |
||||
|
$dataProvider = $searchModel->allData($params); |
||||
|
} else { |
||||
|
$dataProvider = $searchModel->search($params); |
||||
|
} |
||||
|
\iron\widget\Excel::export([ |
||||
|
'models' => $dataProvider->getModels(), |
||||
|
'format' => 'Xlsx', |
||||
|
'asAttachment' => true, |
||||
|
'fileName' =><?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>. "-" .date('Y-m-d H/i/s', time()),
|
||||
|
'columns' => $searchModel->columns() |
||||
|
]); |
||||
|
} |
||||
|
} |
@ -0,0 +1,160 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating CRUD search class of the specified model. |
||||
|
*/ |
||||
|
|
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
$modelClass = StringHelper::basename($generator->modelClass); |
||||
|
$searchModelClass = StringHelper::basename($generator->searchModelClass); |
||||
|
if ($modelClass === $searchModelClass) { |
||||
|
$modelAlias = $modelClass . 'Model'; |
||||
|
} |
||||
|
$rules = $generator->generateSearchRules(); |
||||
|
$labels = $generator->generateSearchLabels(); |
||||
|
$searchAttributes = $generator->getSearchAttributes(); |
||||
|
$searchConditions = $generator->generateSearchConditions(); |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
namespace <?= StringHelper::dirname(ltrim($generator->searchModelClass, '\\')) ?>;
|
||||
|
|
||||
|
use yii\base\Model; |
||||
|
use yii\data\ActiveDataProvider; |
||||
|
use yii\helpers\ArrayHelper; |
||||
|
use <?= ltrim($generator->modelClass, '\\') . (isset($modelAlias) ? " as $modelAlias" : "") ?>;
|
||||
|
|
||||
|
/** |
||||
|
* <?= $searchModelClass ?> represents the model behind the search form of `<?= $generator->modelClass ?>`.
|
||||
|
*/ |
||||
|
class <?= $searchModelClass ?> extends <?= isset($modelAlias) ? $modelAlias : $modelClass ?>
|
||||
|
|
||||
|
{ |
||||
|
/** |
||||
|
* @return array |
||||
|
* 增加创建时间查询字段 |
||||
|
*/ |
||||
|
public function attributes() |
||||
|
{ |
||||
|
return ArrayHelper::merge(['created_at_range'], parent::attributes()); |
||||
|
} |
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function rules() |
||||
|
{ |
||||
|
return [ |
||||
|
<?= implode(",\n ", $rules) ?>,
|
||||
|
['created_at_range','safe'], |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function scenarios() |
||||
|
{ |
||||
|
// bypass scenarios() implementation in the parent class
|
||||
|
return Model::scenarios(); |
||||
|
} |
||||
|
/** |
||||
|
* @return array |
||||
|
* 列格式 |
||||
|
*/ |
||||
|
public function columns() |
||||
|
{ |
||||
|
return [ |
||||
|
[ |
||||
|
'class' => 'blobt\grid\CheckboxColumn', |
||||
|
'width' => '2%', |
||||
|
'align' => 'center' |
||||
|
], |
||||
|
<?php |
||||
|
$count = 0; |
||||
|
foreach ($generator->getColumnNames() as $name) { |
||||
|
if (++$count < 6) { |
||||
|
echo " '" . $name . "',\n"; |
||||
|
} else { |
||||
|
echo " //'" . $name . "',\n"; |
||||
|
} |
||||
|
} |
||||
|
?>
|
||||
|
[ |
||||
|
'class' => 'iron\grid\ActionColumn', |
||||
|
'align' => 'center', |
||||
|
], |
||||
|
]; |
||||
|
} |
||||
|
/** |
||||
|
* @param $params |
||||
|
* @return ActiveDataProvider |
||||
|
* 不分页的所有数据 |
||||
|
*/ |
||||
|
public function allData($params) |
||||
|
{ |
||||
|
$query = <?= isset($modelAlias) ? $modelAlias : $modelClass ?>::find();
|
||||
|
$dataProvider = new ActiveDataProvider([ |
||||
|
'query' => $query, |
||||
|
'pagination' => false, |
||||
|
'sort' => false |
||||
|
]); |
||||
|
$this->load($params); |
||||
|
return $this->filter($query, $dataProvider); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Creates data provider instance with search query applied |
||||
|
* |
||||
|
* @param array $params |
||||
|
* |
||||
|
* @return ActiveDataProvider |
||||
|
*/ |
||||
|
public function search($params) |
||||
|
{ |
||||
|
$query = <?= isset($modelAlias) ? $modelAlias : $modelClass ?>::find();
|
||||
|
|
||||
|
// add conditions that should always apply here
|
||||
|
|
||||
|
$dataProvider = new ActiveDataProvider([ |
||||
|
'query' => $query, |
||||
|
'pagination' => [ |
||||
|
'pageSizeLimit' => [1, 200] |
||||
|
], |
||||
|
'sort' => [ |
||||
|
'defaultOrder' => [ |
||||
|
'id' => SORT_DESC, |
||||
|
] |
||||
|
], |
||||
|
]); |
||||
|
|
||||
|
$this->load($params); |
||||
|
return $this->filter($query, $dataProvider); |
||||
|
} |
||||
|
/** |
||||
|
* @param $query |
||||
|
* @param $dataProvider |
||||
|
* @return ActiveDataProvider |
||||
|
* 条件筛选 |
||||
|
*/ |
||||
|
private function filter($query, $dataProvider){ |
||||
|
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
|
||||
|
<?= implode("\n ", $searchConditions) ?>
|
||||
|
if ($this->created_at_range) { |
||||
|
$arr = explode(' ~ ', $this->created_at_range); |
||||
|
$start = strtotime($arr[0]); |
||||
|
$end = strtotime($arr[1]) + 3600 * 24; |
||||
|
$query->andFilterWhere(['between', 'created_at', $start, $end]); |
||||
|
} |
||||
|
return $dataProvider; |
||||
|
} |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
/* @var $model \yii\db\ActiveRecord */ |
||||
|
$model = new $generator->modelClass(); |
||||
|
$safeAttributes = $model->safeAttributes(); |
||||
|
if (empty($safeAttributes)) { |
||||
|
$safeAttributes = $model->attributes(); |
||||
|
} |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
use yii\widgets\ActiveForm; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */ |
||||
|
/* @var $form yii\widgets\ActiveForm */ |
||||
|
?>
|
||||
|
|
||||
|
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-form"> |
||||
|
|
||||
|
<?= "<?php " ?>$form = ActiveForm::begin(); ?>
|
||||
|
|
||||
|
<?php foreach ($generator->getColumnNames() as $attribute) { |
||||
|
if (in_array($attribute, $safeAttributes)) { |
||||
|
echo " <?= " . $generator->generateActiveField($attribute) . " ?>\n\n"; |
||||
|
} |
||||
|
} ?>
|
||||
|
<div class="form-group"> |
||||
|
<?= "<?= " ?>Html::submitButton(<?= $generator->generateString('保存') ?>, ['class' => 'btn btn-success']) ?>
|
||||
|
<?= "<?= " ?>Html::a(<?= $generator->generateString('返回') ?>, ['index'], ['class' => 'btn btn-info']) ?>
|
||||
|
</div> |
||||
|
|
||||
|
<?= "<?php " ?>ActiveForm::end(); ?>
|
||||
|
|
||||
|
</div> |
@ -0,0 +1,57 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
use blobt\widgets\DateRangePicker; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
use yii\widgets\ActiveForm; |
||||
|
use \blobt\widgets\DateRangePicker; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $model <?= ltrim($generator->searchModelClass, '\\') ?> */ |
||||
|
/* @var $form yii\widgets\ActiveForm */ |
||||
|
?>
|
||||
|
|
||||
|
<?= "<?php " ?>$form = ActiveForm::begin([
|
||||
|
'action' => ['index'], |
||||
|
'method' => 'get', |
||||
|
'validateOnType' => true, |
||||
|
]); |
||||
|
?>
|
||||
|
<div class="col-sm-12"> |
||||
|
<div class="dataTables_filter"> |
||||
|
<?="<?= "?>$form->field($model, 'id', [
|
||||
|
"template" => "{input}{error}", |
||||
|
"inputOptions" => [ |
||||
|
"placeholder" => "检索ID", |
||||
|
"class" => "form-control", |
||||
|
], |
||||
|
"errorOptions" => [ |
||||
|
"class" => "error-tips" |
||||
|
] |
||||
|
]) |
||||
|
?>
|
||||
|
<?="<?= "?>$form->field($model, "created_at_range", [
|
||||
|
"template" => "{input}{error}", |
||||
|
"inputOptions" => [ |
||||
|
"placeholder" => "创建时间", |
||||
|
], |
||||
|
"errorOptions" => [ |
||||
|
"class" => "error-tips" |
||||
|
] |
||||
|
])->widget(DateRangePicker::className()); |
||||
|
?>
|
||||
|
<div class="form-group"> |
||||
|
<?= "<?= " ?>Html::submitButton('<i class="fa fa-filter"></i>', ['class' => 'btn btn-default']) ?>
|
||||
|
<?= "<?= " ?>Html::resetButton('<i class="fa fa-eraser"></i>', ['class' => 'btn btn-default']) ?>
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<?= "<?php " ?>ActiveForm::end(); ?>
|
@ -0,0 +1,27 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */ |
||||
|
|
||||
|
$this->title = <?= $generator->generateString('创建 ' . Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>;
|
||||
|
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
|
||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||
|
?>
|
||||
|
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-create"> |
||||
|
|
||||
|
<?= "<?= " ?>$this->render('_form', [
|
||||
|
'model' => $model, |
||||
|
]) ?>
|
||||
|
|
||||
|
</div> |
@ -0,0 +1,41 @@ |
|||||
|
<?php |
||||
|
/* blobt */ |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
$urlParams = $generator->generateUrlParams(); |
||||
|
$nameAttribute = $generator->getNameAttribute(); |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
use blobt\grid\GridView; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
<?= !empty($generator->searchModelClass) ? "/* @var \$searchModel " . ltrim($generator->searchModelClass, '\\') . " */\n" : '' ?>
|
||||
|
/* @var $dataProvider yii\data\ActiveDataProvider */ |
||||
|
|
||||
|
$this->title = <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>;
|
||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||
|
?>
|
||||
|
<div class="row"> |
||||
|
<div class="col-xs-12"> |
||||
|
<?= "<?= " ?>GridView::widget([
|
||||
|
'dataProvider' => $dataProvider, |
||||
|
'filter' => $this->render("_search", ['model' => $searchModel]), |
||||
|
'batch' => [ |
||||
|
[ |
||||
|
"label" => "删除", |
||||
|
"url" => "<?=$generator->controllerID?>/deletes" |
||||
|
], |
||||
|
], |
||||
|
'columns' => $columns |
||||
|
]); |
||||
|
<?= "?>" ?>
|
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,38 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
$urlParams = $generator->generateUrlParams(); |
||||
|
$modelClassName = Inflector::camel2words(StringHelper::basename($generator->modelClass)); |
||||
|
$nameAttributeTemplate = '$model->' . $generator->getNameAttribute(); |
||||
|
$titleTemplate = $generator->generateString('编辑 ' . $modelClassName . ': {name}', ['name' => '{nameAttribute}']); |
||||
|
if ($generator->enableI18N) { |
||||
|
$title = strtr($titleTemplate, ['\'{nameAttribute}\'' => $nameAttributeTemplate]); |
||||
|
} else { |
||||
|
$title = strtr($titleTemplate, ['{nameAttribute}\'' => '\' . ' . $nameAttributeTemplate]); |
||||
|
} |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */ |
||||
|
|
||||
|
$this->title = <?= $title ?>;
|
||||
|
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
|
||||
|
$this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]];
|
||||
|
$this->params['breadcrumbs'][] = <?= $generator->generateString('Update ') ?>;
|
||||
|
?>
|
||||
|
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update"> |
||||
|
|
||||
|
<?= '<?= ' ?>$this->render('_form', [
|
||||
|
'model' => $model, |
||||
|
]) ?>
|
||||
|
|
||||
|
</div> |
@ -0,0 +1,49 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\helpers\Inflector; |
||||
|
use yii\helpers\StringHelper; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
$urlParams = $generator->generateUrlParams(); |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
use yii\helpers\Html; |
||||
|
use yii\widgets\DetailView; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */ |
||||
|
|
||||
|
$this->title = $model-><?= $generator->getNameAttribute() ?>;
|
||||
|
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
|
||||
|
$this->params['breadcrumbs'][] = $this->title; |
||||
|
\yii\web\YiiAsset::register($this); |
||||
|
?>
|
||||
|
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-view"> |
||||
|
|
||||
|
<p> |
||||
|
<?= "<?= " ?>Html::a(<?= $generator->generateString('返回列表') ?>, ['index'], ['class' => 'btn btn-success']) ?>
|
||||
|
</p> |
||||
|
|
||||
|
<?= "<?= " ?>DetailView::widget([
|
||||
|
'model' => $model, |
||||
|
'attributes' => [ |
||||
|
<?php |
||||
|
if (($tableSchema = $generator->getTableSchema()) === false) { |
||||
|
foreach ($generator->getColumnNames() as $name) { |
||||
|
echo " '" . $name . "',\n"; |
||||
|
} |
||||
|
} else { |
||||
|
foreach ($generator->getTableSchema()->columns as $column) { |
||||
|
$format = $generator->generateColumnFormat($column); |
||||
|
echo " '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n"; |
||||
|
} |
||||
|
} |
||||
|
?>
|
||||
|
], |
||||
|
]) ?>
|
||||
|
|
||||
|
</div> |
@ -0,0 +1,17 @@ |
|||||
|
<?php |
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $form yii\widgets\ActiveForm */ |
||||
|
/* @var $generator yii\gii\generators\crud\Generator */ |
||||
|
|
||||
|
echo $form->field($generator, 'modelClass'); |
||||
|
echo $form->field($generator, 'searchModelClass'); |
||||
|
echo $form->field($generator, 'controllerClass'); |
||||
|
echo $form->field($generator, 'viewPath'); |
||||
|
echo $form->field($generator, 'baseControllerClass'); |
||||
|
echo $form->field($generator, 'indexWidgetType')->dropDownList([ |
||||
|
'grid' => 'GridView', |
||||
|
'list' => 'ListView', |
||||
|
]); |
||||
|
echo $form->field($generator, 'enableI18N')->checkbox(); |
||||
|
echo $form->field($generator, 'enablePjax')->checkbox(); |
||||
|
echo $form->field($generator, 'messageCategory'); |
@ -0,0 +1,995 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* @link http://www.yiiframework.com/ |
||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
|
* @license http://www.yiiframework.com/license/ |
||||
|
*/ |
||||
|
|
||||
|
namespace iron\generators\model; |
||||
|
|
||||
|
use Yii; |
||||
|
use yii\base\NotSupportedException; |
||||
|
use yii\db\ActiveQuery; |
||||
|
use yii\db\ActiveRecord; |
||||
|
use yii\db\Connection; |
||||
|
use yii\db\Schema; |
||||
|
use yii\db\TableSchema; |
||||
|
use yii\gii\CodeFile; |
||||
|
use yii\helpers\Inflector; |
||||
|
|
||||
|
/** |
||||
|
* This generator will generate one or multiple ActiveRecord classes for the specified database table. |
||||
|
* |
||||
|
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
|
* @since 2.0 |
||||
|
*/ |
||||
|
class Generator extends \yii\gii\Generator |
||||
|
{ |
||||
|
const RELATIONS_NONE = 'none'; |
||||
|
const RELATIONS_ALL = 'all'; |
||||
|
const RELATIONS_ALL_INVERSE = 'all-inverse'; |
||||
|
|
||||
|
public $db = 'db'; |
||||
|
public $ns = 'app\models'; |
||||
|
public $tableName; |
||||
|
public $modelClass; |
||||
|
public $baseClass = 'yii\db\ActiveRecord'; |
||||
|
public $generateRelations = self::RELATIONS_ALL; |
||||
|
public $generateRelationsFromCurrentSchema = true; |
||||
|
public $generateLabelsFromComments = false; |
||||
|
public $useTablePrefix = false; |
||||
|
public $standardizeCapitals = false; |
||||
|
public $singularize = false; |
||||
|
public $useSchemaName = true; |
||||
|
public $generateQuery = false; |
||||
|
public $queryNs = 'app\models'; |
||||
|
public $queryClass; |
||||
|
public $queryBaseClass = 'yii\db\ActiveQuery'; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getName() |
||||
|
{ |
||||
|
return 'Model Generator'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function getDescription() |
||||
|
{ |
||||
|
return 'This generator generates an ActiveRecord class for the specified database table.'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function rules() |
||||
|
{ |
||||
|
return array_merge(parent::rules(), [ |
||||
|
[['db', 'ns', 'tableName', 'modelClass', 'baseClass', 'queryNs', 'queryClass', 'queryBaseClass'], 'filter', 'filter' => 'trim'], |
||||
|
[['ns', 'queryNs'], 'filter', 'filter' => function ($value) { return trim($value, '\\'); }], |
||||
|
|
||||
|
[['db', 'ns', 'tableName', 'baseClass', 'queryNs', 'queryBaseClass'], 'required'], |
||||
|
[['db', 'modelClass', 'queryClass'], 'match', 'pattern' => '/^\w+$/', 'message' => 'Only word characters are allowed.'], |
||||
|
[['ns', 'baseClass', 'queryNs', 'queryBaseClass'], 'match', 'pattern' => '/^[\w\\\\]+$/', 'message' => 'Only word characters and backslashes are allowed.'], |
||||
|
[['tableName'], 'match', 'pattern' => '/^([\w ]+\.)?([\w\* ]+)$/', 'message' => 'Only word characters, and optionally spaces, an asterisk and/or a dot are allowed.'], |
||||
|
[['db'], 'validateDb'], |
||||
|
[['ns', 'queryNs'], 'validateNamespace'], |
||||
|
[['tableName'], 'validateTableName'], |
||||
|
[['modelClass'], 'validateModelClass', 'skipOnEmpty' => false], |
||||
|
[['baseClass'], 'validateClass', 'params' => ['extends' => ActiveRecord::className()]], |
||||
|
[['queryBaseClass'], 'validateClass', 'params' => ['extends' => ActiveQuery::className()]], |
||||
|
[['generateRelations'], 'in', 'range' => [self::RELATIONS_NONE, self::RELATIONS_ALL, self::RELATIONS_ALL_INVERSE]], |
||||
|
[['generateLabelsFromComments', 'useTablePrefix', 'useSchemaName', 'generateQuery', 'generateRelationsFromCurrentSchema'], 'boolean'], |
||||
|
[['enableI18N', 'standardizeCapitals', 'singularize'], 'boolean'], |
||||
|
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false], |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function attributeLabels() |
||||
|
{ |
||||
|
return array_merge(parent::attributeLabels(), [ |
||||
|
'ns' => 'Namespace', |
||||
|
'db' => 'Database Connection ID', |
||||
|
'tableName' => 'Table Name', |
||||
|
'standardizeCapitals' => 'Standardize Capitals', |
||||
|
'singularize' => 'Singularize', |
||||
|
'modelClass' => 'Model Class Name', |
||||
|
'baseClass' => 'Base Class', |
||||
|
'generateRelations' => 'Generate Relations', |
||||
|
'generateRelationsFromCurrentSchema' => 'Generate Relations from Current Schema', |
||||
|
'generateLabelsFromComments' => 'Generate Labels from DB Comments', |
||||
|
'generateQuery' => 'Generate ActiveQuery', |
||||
|
'queryNs' => 'ActiveQuery Namespace', |
||||
|
'queryClass' => 'ActiveQuery Class', |
||||
|
'queryBaseClass' => 'ActiveQuery Base Class', |
||||
|
'useSchemaName' => 'Use Schema Name', |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function hints() |
||||
|
{ |
||||
|
return array_merge(parent::hints(), [ |
||||
|
'ns' => 'This is the namespace of the ActiveRecord class to be generated, e.g., <code>app\models</code>', |
||||
|
'db' => 'This is the ID of the DB application component.', |
||||
|
'tableName' => 'This is the name of the DB table that the new ActiveRecord class is associated with, e.g. <code>post</code>. |
||||
|
The table name may consist of the DB schema part if needed, e.g. <code>public.post</code>. |
||||
|
The table name may end with asterisk to match multiple table names, e.g. <code>tbl_*</code> |
||||
|
will match tables who name starts with <code>tbl_</code>. In this case, multiple ActiveRecord classes |
||||
|
will be generated, one for each matching table name; and the class names will be generated from |
||||
|
the matching characters. For example, table <code>tbl_post</code> will generate <code>Post</code> |
||||
|
class.', |
||||
|
'modelClass' => 'This is the name of the ActiveRecord class to be generated. The class name should not contain |
||||
|
the namespace part as it is specified in "Namespace". You do not need to specify the class name |
||||
|
if "Table Name" ends with asterisk, in which case multiple ActiveRecord classes will be generated.', |
||||
|
'standardizeCapitals' => 'This indicates whether the generated class names should have standardized capitals. For example, |
||||
|
table names like <code>SOME_TABLE</code> or <code>Other_Table</code> will have class names <code>SomeTable</code> |
||||
|
and <code>OtherTable</code>, respectively. If not checked, the same tables will have class names <code>SOMETABLE</code> |
||||
|
and <code>OtherTable</code> instead.', |
||||
|
'singularize' => 'This indicates whether the generated class names should be singularized. For example, |
||||
|
table names like <code>some_tables</code> will have class names <code>SomeTable</code>.', |
||||
|
'baseClass' => 'This is the base class of the new ActiveRecord class. It should be a fully qualified namespaced class name.', |
||||
|
'generateRelations' => 'This indicates whether the generator should generate relations based on |
||||
|
foreign key constraints it detects in the database. Note that if your database contains too many tables, |
||||
|
you may want to uncheck this option to accelerate the code generation process.', |
||||
|
'generateRelationsFromCurrentSchema' => 'This indicates whether the generator should generate relations from current schema or from all available schemas.', |
||||
|
'generateLabelsFromComments' => 'This indicates whether the generator should generate attribute labels |
||||
|
by using the comments of the corresponding DB columns.', |
||||
|
'useTablePrefix' => 'This indicates whether the table name returned by the generated ActiveRecord class |
||||
|
should consider the <code>tablePrefix</code> setting of the DB connection. For example, if the |
||||
|
table name is <code>tbl_post</code> and <code>tablePrefix=tbl_</code>, the ActiveRecord class |
||||
|
will return the table name as <code>{{%post}}</code>.', |
||||
|
'useSchemaName' => 'This indicates whether to include the schema name in the ActiveRecord class |
||||
|
when it\'s auto generated. Only non default schema would be used.', |
||||
|
'generateQuery' => 'This indicates whether to generate ActiveQuery for the ActiveRecord class.', |
||||
|
'queryNs' => 'This is the namespace of the ActiveQuery class to be generated, e.g., <code>app\models</code>', |
||||
|
'queryClass' => 'This is the name of the ActiveQuery class to be generated. The class name should not contain |
||||
|
the namespace part as it is specified in "ActiveQuery Namespace". You do not need to specify the class name |
||||
|
if "Table Name" ends with asterisk, in which case multiple ActiveQuery classes will be generated.', |
||||
|
'queryBaseClass' => 'This is the base class of the new ActiveQuery class. It should be a fully qualified namespaced class name.', |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function autoCompleteData() |
||||
|
{ |
||||
|
$db = $this->getDbConnection(); |
||||
|
if ($db !== null) { |
||||
|
return [ |
||||
|
'tableName' => function () use ($db) { |
||||
|
return $db->getSchema()->getTableNames(); |
||||
|
}, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
return []; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function requiredTemplates() |
||||
|
{ |
||||
|
// @todo make 'query.php' to be required before 2.1 release
|
||||
|
return ['model.php'/*, 'query.php'*/]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function stickyAttributes() |
||||
|
{ |
||||
|
return array_merge(parent::stickyAttributes(), ['ns', 'db', 'baseClass', 'generateRelations', 'generateLabelsFromComments', 'queryNs', 'queryBaseClass', 'useTablePrefix', 'generateQuery']); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the `tablePrefix` property of the DB connection as specified |
||||
|
* |
||||
|
* @return string |
||||
|
* @since 2.0.5 |
||||
|
* @see getDbConnection |
||||
|
*/ |
||||
|
public function getTablePrefix() |
||||
|
{ |
||||
|
$db = $this->getDbConnection(); |
||||
|
if ($db !== null) { |
||||
|
return $db->tablePrefix; |
||||
|
} |
||||
|
|
||||
|
return ''; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function generate() |
||||
|
{ |
||||
|
$files = []; |
||||
|
$relations = $this->generateRelations(); |
||||
|
$db = $this->getDbConnection(); |
||||
|
foreach ($this->getTableNames() as $tableName) { |
||||
|
// model :
|
||||
|
$modelClassName = $this->generateClassName($tableName); |
||||
|
$queryClassName = ($this->generateQuery) ? $this->generateQueryClassName($modelClassName) : false; |
||||
|
$tableSchema = $db->getTableSchema($tableName); |
||||
|
$params = [ |
||||
|
'tableName' => $tableName, |
||||
|
'className' => $modelClassName, |
||||
|
'queryClassName' => $queryClassName, |
||||
|
'tableSchema' => $tableSchema, |
||||
|
'properties' => $this->generateProperties($tableSchema), |
||||
|
'labels' => $this->generateLabels($tableSchema), |
||||
|
'rules' => $this->generateRules($tableSchema), |
||||
|
'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [], |
||||
|
]; |
||||
|
$files[] = new CodeFile( |
||||
|
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $modelClassName . '.php', |
||||
|
$this->render('model.php', $params) |
||||
|
); |
||||
|
|
||||
|
// query :
|
||||
|
if ($queryClassName) { |
||||
|
$params['className'] = $queryClassName; |
||||
|
$params['modelClassName'] = $modelClassName; |
||||
|
$files[] = new CodeFile( |
||||
|
Yii::getAlias('@' . str_replace('\\', '/', $this->queryNs)) . '/' . $queryClassName . '.php', |
||||
|
$this->render('query.php', $params) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $files; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates the properties for the specified table. |
||||
|
* @param \yii\db\TableSchema $table the table schema |
||||
|
* @return array the generated properties (property => type) |
||||
|
* @since 2.0.6 |
||||
|
*/ |
||||
|
protected function generateProperties($table) |
||||
|
{ |
||||
|
$properties = []; |
||||
|
foreach ($table->columns as $column) { |
||||
|
$columnPhpType = $column->phpType; |
||||
|
if ($columnPhpType === 'integer') { |
||||
|
$type = 'int'; |
||||
|
} elseif ($columnPhpType === 'boolean') { |
||||
|
$type = 'bool'; |
||||
|
} else { |
||||
|
$type = $columnPhpType; |
||||
|
} |
||||
|
$properties[$column->name] = [ |
||||
|
'type' => $type, |
||||
|
'name' => $column->name, |
||||
|
'comment' => $column->comment, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
return $properties; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates the attribute labels for the specified table. |
||||
|
* @param \yii\db\TableSchema $table the table schema |
||||
|
* @return array the generated attribute labels (name => label) |
||||
|
*/ |
||||
|
public function generateLabels($table) |
||||
|
{ |
||||
|
// $labels = [];
|
||||
|
// foreach ($table->columns as $column) {
|
||||
|
// if ($this->generateLabelsFromComments && !empty($column->comment)) {
|
||||
|
// $labels[$column->name] = $column->comment;
|
||||
|
// } elseif (!strcasecmp($column->name, 'id')) {
|
||||
|
// $labels[$column->name] = 'ID';
|
||||
|
// } else {
|
||||
|
// $label = Inflector::camel2words($column->name);
|
||||
|
// if (!empty($label) && substr_compare($label, ' id', -3, 3, true) === 0) {
|
||||
|
// $label = substr($label, 0, -3) . ' ID';
|
||||
|
// }
|
||||
|
// $labels[$column->name] = $label;
|
||||
|
// }
|
||||
|
// }
|
||||
|
//
|
||||
|
// return $labels;
|
||||
|
|
||||
|
$labels=array(); |
||||
|
|
||||
|
$sql ="SELECT COLUMN_NAME, COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '$table->name'"; |
||||
|
|
||||
|
$res = Yii::$app->getDb()->createCommand($sql)->query(); |
||||
|
|
||||
|
foreach ($res as $column){ |
||||
|
|
||||
|
if (!empty($column['COLUMN_COMMENT'])) |
||||
|
|
||||
|
$labels[$column['COLUMN_NAME']]= $column['COLUMN_COMMENT']; |
||||
|
|
||||
|
else |
||||
|
|
||||
|
$labels[$column['COLUMN_NAME']]= $column['COLUMN_NAME']; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return $labels; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates validation rules for the specified table. |
||||
|
* @param \yii\db\TableSchema $table the table schema |
||||
|
* @return array the generated validation rules |
||||
|
*/ |
||||
|
public function generateRules($table) |
||||
|
{ |
||||
|
$types = []; |
||||
|
$lengths = []; |
||||
|
foreach ($table->columns as $column) { |
||||
|
if($column->name == 'created_at' || $column->name == 'updated_at') { |
||||
|
continue; |
||||
|
} |
||||
|
if ($column->autoIncrement) { |
||||
|
continue; |
||||
|
} |
||||
|
if (!$column->allowNull && $column->defaultValue === null) { |
||||
|
$types['required'][] = $column->name; |
||||
|
} |
||||
|
switch ($column->type) { |
||||
|
case Schema::TYPE_SMALLINT: |
||||
|
case Schema::TYPE_INTEGER: |
||||
|
case Schema::TYPE_BIGINT: |
||||
|
case Schema::TYPE_TINYINT: |
||||
|
$types['integer'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_BOOLEAN: |
||||
|
$types['boolean'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_FLOAT: |
||||
|
case Schema::TYPE_DOUBLE: |
||||
|
case Schema::TYPE_DECIMAL: |
||||
|
case Schema::TYPE_MONEY: |
||||
|
$types['number'][] = $column->name; |
||||
|
break; |
||||
|
case Schema::TYPE_DATE: |
||||
|
case Schema::TYPE_TIME: |
||||
|
case Schema::TYPE_DATETIME: |
||||
|
case Schema::TYPE_TIMESTAMP: |
||||
|
case Schema::TYPE_JSON: |
||||
|
$types['safe'][] = $column->name; |
||||
|
break; |
||||
|
default: // strings
|
||||
|
if ($column->size > 0) { |
||||
|
$lengths[$column->size][] = $column->name; |
||||
|
} else { |
||||
|
$types['string'][] = $column->name; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
$rules = []; |
||||
|
$driverName = $this->getDbDriverName(); |
||||
|
foreach ($types as $type => $columns) { |
||||
|
if ($driverName === 'pgsql' && $type === 'integer') { |
||||
|
$rules[] = "[['" . implode("', '", $columns) . "'], 'default', 'value' => null]"; |
||||
|
} |
||||
|
$rules[] = "[['" . implode("', '", $columns) . "'], '$type']"; |
||||
|
} |
||||
|
foreach ($lengths as $length => $columns) { |
||||
|
$rules[] = "[['" . implode("', '", $columns) . "'], 'string', 'max' => $length]"; |
||||
|
} |
||||
|
|
||||
|
$db = $this->getDbConnection(); |
||||
|
|
||||
|
// Unique indexes rules
|
||||
|
try { |
||||
|
$uniqueIndexes = array_merge($db->getSchema()->findUniqueIndexes($table), [$table->primaryKey]); |
||||
|
$uniqueIndexes = array_unique($uniqueIndexes, SORT_REGULAR); |
||||
|
foreach ($uniqueIndexes as $uniqueColumns) { |
||||
|
// Avoid validating auto incremental columns
|
||||
|
if (!$this->isColumnAutoIncremental($table, $uniqueColumns)) { |
||||
|
$attributesCount = count($uniqueColumns); |
||||
|
|
||||
|
if ($attributesCount === 1) { |
||||
|
$rules[] = "[['" . $uniqueColumns[0] . "'], 'unique']"; |
||||
|
} elseif ($attributesCount > 1) { |
||||
|
$columnsList = implode("', '", $uniqueColumns); |
||||
|
$rules[] = "[['$columnsList'], 'unique', 'targetAttribute' => ['$columnsList']]"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} catch (NotSupportedException $e) { |
||||
|
// doesn't support unique indexes information...do nothing
|
||||
|
} |
||||
|
|
||||
|
// Exist rules for foreign keys
|
||||
|
foreach ($table->foreignKeys as $refs) { |
||||
|
$refTable = $refs[0]; |
||||
|
$refTableSchema = $db->getTableSchema($refTable); |
||||
|
if ($refTableSchema === null) { |
||||
|
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
|
||||
|
continue; |
||||
|
} |
||||
|
$refClassName = $this->generateClassName($refTable); |
||||
|
unset($refs[0]); |
||||
|
$attributes = implode("', '", array_keys($refs)); |
||||
|
$targetAttributes = []; |
||||
|
foreach ($refs as $key => $value) { |
||||
|
$targetAttributes[] = "'$key' => '$value'"; |
||||
|
} |
||||
|
$targetAttributes = implode(', ', $targetAttributes); |
||||
|
$rules[] = "[['$attributes'], 'exist', 'skipOnError' => true, 'targetClass' => $refClassName::className(), 'targetAttribute' => [$targetAttributes]]"; |
||||
|
} |
||||
|
|
||||
|
return $rules; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates relations using a junction table by adding an extra viaTable(). |
||||
|
* @param \yii\db\TableSchema the table being checked |
||||
|
* @param array $fks obtained from the checkJunctionTable() method |
||||
|
* @param array $relations |
||||
|
* @return array modified $relations |
||||
|
*/ |
||||
|
private function generateManyManyRelations($table, $fks, $relations) |
||||
|
{ |
||||
|
$db = $this->getDbConnection(); |
||||
|
|
||||
|
foreach ($fks as $pair) { |
||||
|
list($firstKey, $secondKey) = $pair; |
||||
|
$table0 = $firstKey[0]; |
||||
|
$table1 = $secondKey[0]; |
||||
|
unset($firstKey[0], $secondKey[0]); |
||||
|
$className0 = $this->generateClassName($table0); |
||||
|
$className1 = $this->generateClassName($table1); |
||||
|
$table0Schema = $db->getTableSchema($table0); |
||||
|
$table1Schema = $db->getTableSchema($table1); |
||||
|
|
||||
|
// @see https://github.com/yiisoft/yii2-gii/issues/166
|
||||
|
if ($table0Schema === null || $table1Schema === null) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
$link = $this->generateRelationLink(array_flip($secondKey)); |
||||
|
$viaLink = $this->generateRelationLink($firstKey); |
||||
|
$relationName = $this->generateRelationName($relations, $table0Schema, key($secondKey), true); |
||||
|
$relations[$table0Schema->fullName][$relationName] = [ |
||||
|
"return \$this->hasMany($className1::className(), $link)->viaTable('" |
||||
|
. $this->generateTableName($table->name) . "', $viaLink);", |
||||
|
$className1, |
||||
|
true, |
||||
|
]; |
||||
|
|
||||
|
$link = $this->generateRelationLink(array_flip($firstKey)); |
||||
|
$viaLink = $this->generateRelationLink($secondKey); |
||||
|
$relationName = $this->generateRelationName($relations, $table1Schema, key($firstKey), true); |
||||
|
$relations[$table1Schema->fullName][$relationName] = [ |
||||
|
"return \$this->hasMany($className0::className(), $link)->viaTable('" |
||||
|
. $this->generateTableName($table->name) . "', $viaLink);", |
||||
|
$className0, |
||||
|
true, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
return $relations; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string[] all db schema names or an array with a single empty string |
||||
|
* @throws NotSupportedException |
||||
|
* @since 2.0.5 |
||||
|
*/ |
||||
|
protected function getSchemaNames() |
||||
|
{ |
||||
|
$db = $this->getDbConnection(); |
||||
|
|
||||
|
if ($this->generateRelationsFromCurrentSchema) { |
||||
|
if ($db->schema->defaultSchema !== null) { |
||||
|
return [$db->schema->defaultSchema]; |
||||
|
} |
||||
|
return ['']; |
||||
|
} |
||||
|
|
||||
|
$schema = $db->getSchema(); |
||||
|
if ($schema->hasMethod('getSchemaNames')) { // keep BC to Yii versions < 2.0.4
|
||||
|
try { |
||||
|
$schemaNames = $schema->getSchemaNames(); |
||||
|
} catch (NotSupportedException $e) { |
||||
|
// schema names are not supported by schema
|
||||
|
} |
||||
|
} |
||||
|
if (!isset($schemaNames)) { |
||||
|
if (($pos = strpos($this->tableName, '.')) !== false) { |
||||
|
$schemaNames = [substr($this->tableName, 0, $pos)]; |
||||
|
} else { |
||||
|
$schemaNames = ['']; |
||||
|
} |
||||
|
} |
||||
|
return $schemaNames; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return array the generated relation declarations |
||||
|
*/ |
||||
|
protected function generateRelations() |
||||
|
{ |
||||
|
if ($this->generateRelations === self::RELATIONS_NONE) { |
||||
|
return []; |
||||
|
} |
||||
|
|
||||
|
$db = $this->getDbConnection(); |
||||
|
$relations = []; |
||||
|
$schemaNames = $this->getSchemaNames(); |
||||
|
foreach ($schemaNames as $schemaName) { |
||||
|
foreach ($db->getSchema()->getTableSchemas($schemaName) as $table) { |
||||
|
$className = $this->generateClassName($table->fullName); |
||||
|
foreach ($table->foreignKeys as $refs) { |
||||
|
$refTable = $refs[0]; |
||||
|
$refTableSchema = $db->getTableSchema($refTable); |
||||
|
if ($refTableSchema === null) { |
||||
|
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
|
||||
|
continue; |
||||
|
} |
||||
|
unset($refs[0]); |
||||
|
$fks = array_keys($refs); |
||||
|
$refClassName = $this->generateClassName($refTable); |
||||
|
|
||||
|
// Add relation for this table
|
||||
|
$link = $this->generateRelationLink(array_flip($refs)); |
||||
|
$relationName = $this->generateRelationName($relations, $table, $fks[0], false); |
||||
|
$relations[$table->fullName][$relationName] = [ |
||||
|
"return \$this->hasOne($refClassName::className(), $link);", |
||||
|
$refClassName, |
||||
|
false, |
||||
|
]; |
||||
|
|
||||
|
// Add relation for the referenced table
|
||||
|
$hasMany = $this->isHasManyRelation($table, $fks); |
||||
|
$link = $this->generateRelationLink($refs); |
||||
|
$relationName = $this->generateRelationName($relations, $refTableSchema, $className, $hasMany); |
||||
|
$relations[$refTableSchema->fullName][$relationName] = [ |
||||
|
"return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "($className::className(), $link);", |
||||
|
$className, |
||||
|
$hasMany, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
if (($junctionFks = $this->checkJunctionTable($table)) === false) { |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
$relations = $this->generateManyManyRelations($table, $junctionFks, $relations); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ($this->generateRelations === self::RELATIONS_ALL_INVERSE) { |
||||
|
return $this->addInverseRelations($relations); |
||||
|
} |
||||
|
|
||||
|
return $relations; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Adds inverse relations |
||||
|
* |
||||
|
* @param array $relations relation declarations |
||||
|
* @return array relation declarations extended with inverse relation names |
||||
|
* @since 2.0.5 |
||||
|
*/ |
||||
|
protected function addInverseRelations($relations) |
||||
|
{ |
||||
|
$db = $this->getDbConnection(); |
||||
|
$relationNames = []; |
||||
|
|
||||
|
$schemaNames = $this->getSchemaNames(); |
||||
|
foreach ($schemaNames as $schemaName) { |
||||
|
foreach ($db->schema->getTableSchemas($schemaName) as $table) { |
||||
|
$className = $this->generateClassName($table->fullName); |
||||
|
foreach ($table->foreignKeys as $refs) { |
||||
|
$refTable = $refs[0]; |
||||
|
$refTableSchema = $db->getTableSchema($refTable); |
||||
|
if ($refTableSchema === null) { |
||||
|
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
|
||||
|
continue; |
||||
|
} |
||||
|
unset($refs[0]); |
||||
|
$fks = array_keys($refs); |
||||
|
|
||||
|
$leftRelationName = $this->generateRelationName($relationNames, $table, $fks[0], false); |
||||
|
$relationNames[$table->fullName][$leftRelationName] = true; |
||||
|
$hasMany = $this->isHasManyRelation($table, $fks); |
||||
|
$rightRelationName = $this->generateRelationName( |
||||
|
$relationNames, |
||||
|
$refTableSchema, |
||||
|
$className, |
||||
|
$hasMany |
||||
|
); |
||||
|
$relationNames[$refTableSchema->fullName][$rightRelationName] = true; |
||||
|
|
||||
|
$relations[$table->fullName][$leftRelationName][0] = |
||||
|
rtrim($relations[$table->fullName][$leftRelationName][0], ';') |
||||
|
. "->inverseOf('".lcfirst($rightRelationName)."');"; |
||||
|
$relations[$refTableSchema->fullName][$rightRelationName][0] = |
||||
|
rtrim($relations[$refTableSchema->fullName][$rightRelationName][0], ';') |
||||
|
. "->inverseOf('".lcfirst($leftRelationName)."');"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return $relations; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Determines if relation is of has many type |
||||
|
* |
||||
|
* @param TableSchema $table |
||||
|
* @param array $fks |
||||
|
* @return bool |
||||
|
* @since 2.0.5 |
||||
|
*/ |
||||
|
protected function isHasManyRelation($table, $fks) |
||||
|
{ |
||||
|
$uniqueKeys = [$table->primaryKey]; |
||||
|
try { |
||||
|
$uniqueKeys = array_merge($uniqueKeys, $this->getDbConnection()->getSchema()->findUniqueIndexes($table)); |
||||
|
} catch (NotSupportedException $e) { |
||||
|
// ignore
|
||||
|
} |
||||
|
foreach ($uniqueKeys as $uniqueKey) { |
||||
|
if (count(array_diff(array_merge($uniqueKey, $fks), array_intersect($uniqueKey, $fks))) === 0) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates the link parameter to be used in generating the relation declaration. |
||||
|
* @param array $refs reference constraint |
||||
|
* @return string the generated link parameter. |
||||
|
*/ |
||||
|
protected function generateRelationLink($refs) |
||||
|
{ |
||||
|
$pairs = []; |
||||
|
foreach ($refs as $a => $b) { |
||||
|
$pairs[] = "'$a' => '$b'"; |
||||
|
} |
||||
|
|
||||
|
return '[' . implode(', ', $pairs) . ']'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if the given table is a junction table, that is it has at least one pair of unique foreign keys. |
||||
|
* @param \yii\db\TableSchema the table being checked |
||||
|
* @return array|bool all unique foreign key pairs if the table is a junction table, |
||||
|
* or false if the table is not a junction table. |
||||
|
*/ |
||||
|
protected function checkJunctionTable($table) |
||||
|
{ |
||||
|
if (count($table->foreignKeys) < 2) { |
||||
|
return false; |
||||
|
} |
||||
|
$uniqueKeys = [$table->primaryKey]; |
||||
|
try { |
||||
|
$uniqueKeys = array_merge($uniqueKeys, $this->getDbConnection()->getSchema()->findUniqueIndexes($table)); |
||||
|
} catch (NotSupportedException $e) { |
||||
|
// ignore
|
||||
|
} |
||||
|
$result = []; |
||||
|
// find all foreign key pairs that have all columns in an unique constraint
|
||||
|
$foreignKeys = array_values($table->foreignKeys); |
||||
|
$foreignKeysCount = count($foreignKeys); |
||||
|
|
||||
|
for ($i = 0; $i < $foreignKeysCount; $i++) { |
||||
|
$firstColumns = $foreignKeys[$i]; |
||||
|
unset($firstColumns[0]); |
||||
|
|
||||
|
for ($j = $i + 1; $j < $foreignKeysCount; $j++) { |
||||
|
$secondColumns = $foreignKeys[$j]; |
||||
|
unset($secondColumns[0]); |
||||
|
|
||||
|
$fks = array_merge(array_keys($firstColumns), array_keys($secondColumns)); |
||||
|
foreach ($uniqueKeys as $uniqueKey) { |
||||
|
if (count(array_diff(array_merge($uniqueKey, $fks), array_intersect($uniqueKey, $fks))) === 0) { |
||||
|
// save the foreign key pair
|
||||
|
$result[] = [$foreignKeys[$i], $foreignKeys[$j]]; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return empty($result) ? false : $result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generate a relation name for the specified table and a base name. |
||||
|
* @param array $relations the relations being generated currently. |
||||
|
* @param \yii\db\TableSchema $table the table schema |
||||
|
* @param string $key a base name that the relation name may be generated from |
||||
|
* @param bool $multiple whether this is a has-many relation |
||||
|
* @return string the relation name |
||||
|
*/ |
||||
|
protected function generateRelationName($relations, $table, $key, $multiple) |
||||
|
{ |
||||
|
static $baseModel; |
||||
|
/* @var $baseModel \yii\db\ActiveRecord */ |
||||
|
if ($baseModel === null) { |
||||
|
$baseClass = $this->baseClass; |
||||
|
$baseClassReflector = new \ReflectionClass($baseClass); |
||||
|
if ($baseClassReflector->isAbstract()) { |
||||
|
$baseClassWrapper = |
||||
|
'namespace ' . __NAMESPACE__ . ';'. |
||||
|
'class GiiBaseClassWrapper extends \\' . $baseClass . ' {' . |
||||
|
'public static function tableName(){' . |
||||
|
'return "' . addslashes($table->fullName) . '";' . |
||||
|
'}' . |
||||
|
'};' . |
||||
|
'return new GiiBaseClassWrapper();'; |
||||
|
$baseModel = eval($baseClassWrapper); |
||||
|
} else { |
||||
|
$baseModel = new $baseClass(); |
||||
|
} |
||||
|
$baseModel->setAttributes([]); |
||||
|
} |
||||
|
|
||||
|
if (!empty($key) && strcasecmp($key, 'id')) { |
||||
|
if (substr_compare($key, 'id', -2, 2, true) === 0) { |
||||
|
$key = rtrim(substr($key, 0, -2), '_'); |
||||
|
} elseif (substr_compare($key, 'id', 0, 2, true) === 0) { |
||||
|
$key = ltrim(substr($key, 2, strlen($key)), '_'); |
||||
|
} |
||||
|
} |
||||
|
if ($multiple) { |
||||
|
$key = Inflector::pluralize($key); |
||||
|
} |
||||
|
$name = $rawName = Inflector::id2camel($key, '_'); |
||||
|
$i = 0; |
||||
|
while ($baseModel->hasProperty(lcfirst($name))) { |
||||
|
$name = $rawName . ($i++); |
||||
|
} |
||||
|
while (isset($table->columns[lcfirst($name)])) { |
||||
|
$name = $rawName . ($i++); |
||||
|
} |
||||
|
while (isset($relations[$table->fullName][$name])) { |
||||
|
$name = $rawName . ($i++); |
||||
|
} |
||||
|
|
||||
|
return $name; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Validates the [[db]] attribute. |
||||
|
*/ |
||||
|
public function validateDb() |
||||
|
{ |
||||
|
if (!Yii::$app->has($this->db)) { |
||||
|
$this->addError('db', 'There is no application component named "db".'); |
||||
|
} elseif (!Yii::$app->get($this->db) instanceof Connection) { |
||||
|
$this->addError('db', 'The "db" application component must be a DB connection instance.'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Validates the namespace. |
||||
|
* |
||||
|
* @param string $attribute Namespace variable. |
||||
|
*/ |
||||
|
public function validateNamespace($attribute) |
||||
|
{ |
||||
|
$value = $this->$attribute; |
||||
|
$value = ltrim($value, '\\'); |
||||
|
$path = Yii::getAlias('@' . str_replace('\\', '/', $value), false); |
||||
|
if ($path === false) { |
||||
|
$this->addError($attribute, 'Namespace must be associated with an existing directory.'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Validates the [[modelClass]] attribute. |
||||
|
*/ |
||||
|
public function validateModelClass() |
||||
|
{ |
||||
|
if ($this->isReservedKeyword($this->modelClass)) { |
||||
|
$this->addError('modelClass', 'Class name cannot be a reserved PHP keyword.'); |
||||
|
} |
||||
|
if ((empty($this->tableName) || substr_compare($this->tableName, '*', -1, 1)) && $this->modelClass == '') { |
||||
|
$this->addError('modelClass', 'Model Class cannot be blank if table name does not end with asterisk.'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Validates the [[tableName]] attribute. |
||||
|
*/ |
||||
|
public function validateTableName() |
||||
|
{ |
||||
|
if (strpos($this->tableName, '*') !== false && substr_compare($this->tableName, '*', -1, 1)) { |
||||
|
$this->addError('tableName', 'Asterisk is only allowed as the last character.'); |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
$tables = $this->getTableNames(); |
||||
|
if (empty($tables)) { |
||||
|
$this->addError('tableName', "Table '{$this->tableName}' does not exist."); |
||||
|
} else { |
||||
|
foreach ($tables as $table) { |
||||
|
$class = $this->generateClassName($table); |
||||
|
if ($this->isReservedKeyword($class)) { |
||||
|
$this->addError('tableName', "Table '$table' will generate a class which is a reserved PHP keyword."); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected $tableNames; |
||||
|
protected $classNames; |
||||
|
|
||||
|
/** |
||||
|
* @return array the table names that match the pattern specified by [[tableName]]. |
||||
|
*/ |
||||
|
protected function getTableNames() |
||||
|
{ |
||||
|
if ($this->tableNames !== null) { |
||||
|
return $this->tableNames; |
||||
|
} |
||||
|
$db = $this->getDbConnection(); |
||||
|
if ($db === null) { |
||||
|
return []; |
||||
|
} |
||||
|
$tableNames = []; |
||||
|
if (strpos($this->tableName, '*') !== false) { |
||||
|
if (($pos = strrpos($this->tableName, '.')) !== false) { |
||||
|
$schema = substr($this->tableName, 0, $pos); |
||||
|
$pattern = '/^' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '$/'; |
||||
|
} else { |
||||
|
$schema = ''; |
||||
|
$pattern = '/^' . str_replace('*', '\w+', $this->tableName) . '$/'; |
||||
|
} |
||||
|
|
||||
|
foreach ($db->schema->getTableNames($schema) as $table) { |
||||
|
if (preg_match($pattern, $table)) { |
||||
|
$tableNames[] = $schema === '' ? $table : ($schema . '.' . $table); |
||||
|
} |
||||
|
} |
||||
|
} elseif (($table = $db->getTableSchema($this->tableName, true)) !== null) { |
||||
|
$tableNames[] = $this->tableName; |
||||
|
$this->classNames[$this->tableName] = $this->modelClass; |
||||
|
} |
||||
|
|
||||
|
return $this->tableNames = $tableNames; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates the table name by considering table prefix. |
||||
|
* If [[useTablePrefix]] is false, the table name will be returned without change. |
||||
|
* @param string $tableName the table name (which may contain schema prefix) |
||||
|
* @return string the generated table name |
||||
|
*/ |
||||
|
public function generateTableName($tableName) |
||||
|
{ |
||||
|
if (!$this->useTablePrefix) { |
||||
|
return $tableName; |
||||
|
} |
||||
|
|
||||
|
$db = $this->getDbConnection(); |
||||
|
if (preg_match("/^{$db->tablePrefix}(.*?)$/", $tableName, $matches)) { |
||||
|
$tableName = '{{%' . $matches[1] . '}}'; |
||||
|
} elseif (preg_match("/^(.*?){$db->tablePrefix}$/", $tableName, $matches)) { |
||||
|
$tableName = '{{' . $matches[1] . '%}}'; |
||||
|
} |
||||
|
return $tableName; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates a class name from the specified table name. |
||||
|
* @param string $tableName the table name (which may contain schema prefix) |
||||
|
* @param bool $useSchemaName should schema name be included in the class name, if present |
||||
|
* @return string the generated class name |
||||
|
*/ |
||||
|
protected function generateClassName($tableName, $useSchemaName = null) |
||||
|
{ |
||||
|
if (isset($this->classNames[$tableName])) { |
||||
|
return $this->classNames[$tableName]; |
||||
|
} |
||||
|
|
||||
|
$schemaName = ''; |
||||
|
$fullTableName = $tableName; |
||||
|
if (($pos = strrpos($tableName, '.')) !== false) { |
||||
|
if (($useSchemaName === null && $this->useSchemaName) || $useSchemaName) { |
||||
|
$schemaName = substr($tableName, 0, $pos) . '_'; |
||||
|
} |
||||
|
$tableName = substr($tableName, $pos + 1); |
||||
|
} |
||||
|
|
||||
|
$db = $this->getDbConnection(); |
||||
|
$patterns = []; |
||||
|
$patterns[] = "/^{$db->tablePrefix}(.*?)$/"; |
||||
|
$patterns[] = "/^(.*?){$db->tablePrefix}$/"; |
||||
|
if (strpos($this->tableName, '*') !== false) { |
||||
|
$pattern = $this->tableName; |
||||
|
if (($pos = strrpos($pattern, '.')) !== false) { |
||||
|
$pattern = substr($pattern, $pos + 1); |
||||
|
} |
||||
|
$patterns[] = '/^' . str_replace('*', '(\w+)', $pattern) . '$/'; |
||||
|
} |
||||
|
$className = $tableName; |
||||
|
foreach ($patterns as $pattern) { |
||||
|
if (preg_match($pattern, $tableName, $matches)) { |
||||
|
$className = $matches[1]; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ($this->standardizeCapitals) { |
||||
|
$schemaName = ctype_upper(preg_replace('/[_-]/', '', $schemaName)) ? strtolower($schemaName) : $schemaName; |
||||
|
$className = ctype_upper(preg_replace('/[_-]/', '', $className)) ? strtolower($className) : $className; |
||||
|
$this->classNames[$fullTableName] = Inflector::camelize(Inflector::camel2words($schemaName.$className)); |
||||
|
} else { |
||||
|
$this->classNames[$fullTableName] = Inflector::id2camel($schemaName.$className, '_'); |
||||
|
} |
||||
|
|
||||
|
if ($this->singularize) { |
||||
|
$this->classNames[$fullTableName] = Inflector::singularize($this->classNames[$fullTableName]); |
||||
|
} |
||||
|
|
||||
|
return $this->classNames[$fullTableName]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Generates a query class name from the specified model class name. |
||||
|
* @param string $modelClassName model class name |
||||
|
* @return string generated class name |
||||
|
*/ |
||||
|
protected function generateQueryClassName($modelClassName) |
||||
|
{ |
||||
|
$queryClassName = $this->queryClass; |
||||
|
if (empty($queryClassName) || strpos($this->tableName, '*') !== false) { |
||||
|
$queryClassName = $modelClassName . 'Query'; |
||||
|
} |
||||
|
return $queryClassName; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return Connection the DB connection as specified by [[db]]. |
||||
|
*/ |
||||
|
protected function getDbConnection() |
||||
|
{ |
||||
|
return Yii::$app->get($this->db, false); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @return string|null driver name of db connection. |
||||
|
* In case db is not instance of \yii\db\Connection null will be returned. |
||||
|
* @since 2.0.6 |
||||
|
*/ |
||||
|
protected function getDbDriverName() |
||||
|
{ |
||||
|
/** @var Connection $db */ |
||||
|
$db = $this->getDbConnection(); |
||||
|
return $db instanceof \yii\db\Connection ? $db->driverName : null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Checks if any of the specified columns is auto incremental. |
||||
|
* @param \yii\db\TableSchema $table the table schema |
||||
|
* @param array $columns columns to check for autoIncrement property |
||||
|
* @return bool whether any of the specified columns is auto incremental. |
||||
|
*/ |
||||
|
protected function isColumnAutoIncremental($table, $columns) |
||||
|
{ |
||||
|
foreach ($columns as $column) { |
||||
|
if (isset($table->columns[$column]) && $table->columns[$column]->autoIncrement) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
@ -0,0 +1,125 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating the model class of a specified table. |
||||
|
*/ |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\model\Generator */ |
||||
|
/* @var $tableName string full table name */ |
||||
|
/* @var $className string class name */ |
||||
|
/* @var $queryClassName string query class name */ |
||||
|
/* @var $tableSchema yii\db\TableSchema */ |
||||
|
/* @var $properties array list of properties (property => [type, name. comment]) */ |
||||
|
/* @var $labels string[] list of attribute labels (name => label) */ |
||||
|
/* @var $rules string[] list of validation rules */ |
||||
|
/* @var $relations array list of relations (name => relation declaration) */ |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
namespace <?= $generator->ns ?>;
|
||||
|
|
||||
|
use Yii; |
||||
|
use yii\behaviors\TimestampBehavior; |
||||
|
|
||||
|
/** |
||||
|
* This is the model class for table "<?= $generator->generateTableName($tableName) ?>". |
||||
|
* |
||||
|
<?php foreach ($properties as $property => $data): ?>
|
||||
|
* @property <?= "{$data['type']} \${$property}" . ($data['comment'] ? ' ' . strtr($data['comment'], ["\n" => ' ']) : '') . "\n" ?>
|
||||
|
<?php endforeach; ?>
|
||||
|
<?php if (!empty($relations)): ?>
|
||||
|
* |
||||
|
<?php foreach ($relations as $name => $relation): ?>
|
||||
|
* @property <?= $relation[1] . ($relation[2] ? '[]' : '') . ' $' . lcfirst($name) . "\n" ?>
|
||||
|
<?php endforeach; ?>
|
||||
|
<?php endif; ?>
|
||||
|
*/ |
||||
|
class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') . "\n" ?>
|
||||
|
{ |
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public static function tableName() |
||||
|
{ |
||||
|
return '<?= $generator->generateTableName($tableName) ?>'; |
||||
|
} |
||||
|
<?php if ($generator->db !== 'db'): ?>
|
||||
|
|
||||
|
/** |
||||
|
* @return \yii\db\Connection the database connection used by this AR class. |
||||
|
*/ |
||||
|
public static function getDb() |
||||
|
{ |
||||
|
return Yii::$app->get('<?= $generator->db ?>'); |
||||
|
} |
||||
|
<?php endif; ?>
|
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function rules() |
||||
|
{ |
||||
|
return [<?= empty($rules) ? '' : ("\n " . implode(",\n ", $rules) . ",\n ") ?>];
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function attributeLabels() |
||||
|
{ |
||||
|
return [ |
||||
|
<?php foreach ($labels as $name => $label): ?>
|
||||
|
<?= "'$name' => " . $generator->generateString($label) . ",\n" ?>
|
||||
|
<?php endforeach; ?>
|
||||
|
]; |
||||
|
} |
||||
|
<?php foreach ($relations as $name => $relation): ?>
|
||||
|
|
||||
|
/** |
||||
|
* @return \yii\db\ActiveQuery |
||||
|
*/ |
||||
|
public function get<?= $name ?>()
|
||||
|
{ |
||||
|
<?= $relation[0] . "\n" ?>
|
||||
|
} |
||||
|
<?php endforeach; ?>
|
||||
|
<?php if ($queryClassName): ?>
|
||||
|
<?php |
||||
|
$queryClassFullName = ($generator->ns === $generator->queryNs) ? $queryClassName : '\\' . $generator->queryNs . '\\' . $queryClassName; |
||||
|
echo "\n"; |
||||
|
?>
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
* @return <?= $queryClassFullName ?> the active query used by this AR class.
|
||||
|
*/ |
||||
|
public static function find() |
||||
|
{ |
||||
|
return new <?= $queryClassFullName ?>(get_called_class());
|
||||
|
} |
||||
|
<?php endif; ?>
|
||||
|
|
||||
|
|
||||
|
<?php if (array_key_exists('created_at', $labels) && array_key_exists('updated_at', $labels)): ?>
|
||||
|
/** |
||||
|
* @author linyao |
||||
|
* @email 602604991@qq.com |
||||
|
* @created Nov 8, 2019 |
||||
|
* |
||||
|
* 行为存储创建时间和更新时间 |
||||
|
*/ |
||||
|
public function behaviors() |
||||
|
{ |
||||
|
return [ |
||||
|
[ |
||||
|
'class' => TimestampBehavior::className(), |
||||
|
'createdAtAttribute' => 'created_at', |
||||
|
'updatedAtAttribute' => 'updated_at', |
||||
|
'value' => function() { |
||||
|
return time(); |
||||
|
}, |
||||
|
], |
||||
|
]; |
||||
|
} |
||||
|
<?php endif; ?>
|
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
<?php |
||||
|
/** |
||||
|
* This is the template for generating the ActiveQuery class. |
||||
|
*/ |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $generator yii\gii\generators\model\Generator */ |
||||
|
/* @var $tableName string full table name */ |
||||
|
/* @var $className string class name */ |
||||
|
/* @var $tableSchema yii\db\TableSchema */ |
||||
|
/* @var $labels string[] list of attribute labels (name => label) */ |
||||
|
/* @var $rules string[] list of validation rules */ |
||||
|
/* @var $relations array list of relations (name => relation declaration) */ |
||||
|
/* @var $className string class name */ |
||||
|
/* @var $modelClassName string related model class name */ |
||||
|
|
||||
|
$modelFullClassName = $modelClassName; |
||||
|
if ($generator->ns !== $generator->queryNs) { |
||||
|
$modelFullClassName = '\\' . $generator->ns . '\\' . $modelFullClassName; |
||||
|
} |
||||
|
|
||||
|
echo "<?php\n"; |
||||
|
?>
|
||||
|
|
||||
|
namespace <?= $generator->queryNs ?>;
|
||||
|
|
||||
|
/** |
||||
|
* This is the ActiveQuery class for [[<?= $modelFullClassName ?>]].
|
||||
|
* |
||||
|
* @see <?= $modelFullClassName . "\n" ?>
|
||||
|
*/ |
||||
|
class <?= $className ?> extends <?= '\\' . ltrim($generator->queryBaseClass, '\\') . "\n" ?>
|
||||
|
{ |
||||
|
/*public function active() |
||||
|
{ |
||||
|
return $this->andWhere('[[status]]=1'); |
||||
|
}*/ |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
* @return <?= $modelFullClassName ?>[]|array
|
||||
|
*/ |
||||
|
public function all($db = null) |
||||
|
{ |
||||
|
return parent::all($db); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
* @return <?= $modelFullClassName ?>|array|null
|
||||
|
*/ |
||||
|
public function one($db = null) |
||||
|
{ |
||||
|
return parent::one($db); |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
<?php |
||||
|
|
||||
|
use yii\gii\generators\model\Generator; |
||||
|
|
||||
|
/* @var $this yii\web\View */ |
||||
|
/* @var $form yii\widgets\ActiveForm */ |
||||
|
/* @var $generator yii\gii\generators\model\Generator */ |
||||
|
|
||||
|
echo $form->field($generator, 'tableName')->textInput(['table_prefix' => $generator->getTablePrefix()]); |
||||
|
echo $form->field($generator, 'modelClass'); |
||||
|
echo $form->field($generator, 'standardizeCapitals')->checkbox(); |
||||
|
echo $form->field($generator, 'singularize')->checkbox(); |
||||
|
echo $form->field($generator, 'ns'); |
||||
|
echo $form->field($generator, 'baseClass'); |
||||
|
echo $form->field($generator, 'db'); |
||||
|
echo $form->field($generator, 'useTablePrefix')->checkbox(); |
||||
|
echo $form->field($generator, 'generateRelations')->dropDownList([ |
||||
|
Generator::RELATIONS_NONE => 'No relations', |
||||
|
Generator::RELATIONS_ALL => 'All relations', |
||||
|
Generator::RELATIONS_ALL_INVERSE => 'All relations with inverse', |
||||
|
]); |
||||
|
echo $form->field($generator, 'generateRelationsFromCurrentSchema')->checkbox(); |
||||
|
echo $form->field($generator, 'generateLabelsFromComments')->checkbox(); |
||||
|
echo $form->field($generator, 'generateQuery')->checkbox(); |
||||
|
echo $form->field($generator, 'queryNs'); |
||||
|
echo $form->field($generator, 'queryClass'); |
||||
|
echo $form->field($generator, 'queryBaseClass'); |
||||
|
echo $form->field($generator, 'enableI18N')->checkbox(); |
||||
|
echo $form->field($generator, 'messageCategory'); |
||||
|
echo $form->field($generator, 'useSchemaName')->checkbox(); |
@ -0,0 +1,246 @@ |
|||||
|
<?php |
||||
|
|
||||
|
/* |
||||
|
* The MIT License |
||||
|
* |
||||
|
* Copyright 2019 Blobt. |
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to deal |
||||
|
* in the Software without restriction, including without limitation the rights |
||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
* copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
* THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
namespace iron\grid; |
||||
|
|
||||
|
use Yii; |
||||
|
use yii\helpers\Html; |
||||
|
use yii\helpers\Url; |
||||
|
use blobt\grid\Column; |
||||
|
|
||||
|
class ActionColumn extends Column |
||||
|
{ |
||||
|
|
||||
|
public $config = [ |
||||
|
[ |
||||
|
'name' => 'view', |
||||
|
'icon' => 'menu-hamburger', |
||||
|
'title' => '详情', |
||||
|
], |
||||
|
[ |
||||
|
'name' => 'update', |
||||
|
'icon' => 'edit', |
||||
|
'title' => '修改' |
||||
|
], |
||||
|
[ |
||||
|
'name' => 'delete', |
||||
|
'icon' => 'trash', |
||||
|
'title' => '删除', |
||||
|
'contents' => '确定删除?' |
||||
|
] |
||||
|
]; |
||||
|
/** |
||||
|
* @var string 处理的控制器ID |
||||
|
*/ |
||||
|
public $controller; |
||||
|
|
||||
|
/** |
||||
|
* @var string 按钮模板 |
||||
|
*/ |
||||
|
public $template = ''; |
||||
|
|
||||
|
/** |
||||
|
* @var array 以按钮名为键,以匿名函数为值,通过匿名函数返回html,用来控制按钮的表现形式 |
||||
|
* 匿名函数必须遵循以下申明方式: |
||||
|
* |
||||
|
* ```php |
||||
|
* function ($url, $model, $key) { |
||||
|
* // return the button HTML code
|
||||
|
* } |
||||
|
* ``` |
||||
|
* |
||||
|
* - `$url`: 按钮的跳转路径 |
||||
|
* - `$model`: 每行的模型 |
||||
|
* - `$key`: id值 |
||||
|
* |
||||
|
* 使用案例: |
||||
|
* ```php |
||||
|
* [ |
||||
|
* 'update' => function ($url, $model, $key) { |
||||
|
* return $model->status === 'editable' ? Html::a('Update', $url) : ''; |
||||
|
* }, |
||||
|
* ], |
||||
|
* |
||||
|
*/ |
||||
|
public $buttons = []; |
||||
|
|
||||
|
/** @var array 和上述$buttons功能类似,只是匿名函数返回布尔,只控制是否展示 |
||||
|
* 匿名函数必须遵循以下申明方式: |
||||
|
* |
||||
|
* ```php |
||||
|
* function ($model, $key, $index) { |
||||
|
* return $model->status === 'editable'; |
||||
|
* } |
||||
|
* ``` |
||||
|
* |
||||
|
* 使用案例: |
||||
|
* ```php |
||||
|
* [ |
||||
|
* 'update' => \Yii::$app->user->can('update'), |
||||
|
* ], |
||||
|
* ``` |
||||
|
* @since 2.0.7 |
||||
|
*/ |
||||
|
public $visibleButtons = []; |
||||
|
|
||||
|
/** |
||||
|
* @var callable 匿名函数,用作控制按钮Url |
||||
|
* |
||||
|
* 匿名函数必须遵循以下申明方式: |
||||
|
* ```php |
||||
|
* function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) { |
||||
|
* //return string;
|
||||
|
* } |
||||
|
* ``` |
||||
|
* |
||||
|
* 如果没有设置,默认使用本类的[[createUrl()]]. |
||||
|
*/ |
||||
|
public $urlCreator; |
||||
|
|
||||
|
/** |
||||
|
* @var array 按钮的html属性 |
||||
|
*/ |
||||
|
public $buttonOptions = []; |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
public function init() |
||||
|
{ |
||||
|
parent::init(); |
||||
|
foreach ($this->config as $config) { |
||||
|
if (isset($config['contents'])) { |
||||
|
$options = ['alertify-confirm' => Yii::t('yii', "{$config['contents']}?")]; |
||||
|
} else { |
||||
|
$options = []; |
||||
|
} |
||||
|
if (isset($config['icon'])) { |
||||
|
$icon = $config['icon']; |
||||
|
} else { |
||||
|
$icon = 'th-large'; |
||||
|
} |
||||
|
if (isset($config['title'])) { |
||||
|
$title = $config['title']; |
||||
|
} else { |
||||
|
$title = $config['name']; |
||||
|
} |
||||
|
if (isset($config['hide'])) { |
||||
|
$this->visibleButtons($config['name'], $config['hide']); |
||||
|
} |
||||
|
$this->initButton($config['name'], $icon, $options, $title); |
||||
|
$this->template .= " {{$config['name']}}"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 初始化按钮 |
||||
|
* @param string $name |
||||
|
* @param string $iconName |
||||
|
* @param array $additionalOptions 附加html属性 |
||||
|
*/ |
||||
|
protected function initButton($name, $iconName, $additionalOptions = [], $title = '') |
||||
|
{ |
||||
|
$this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions, $title) { |
||||
|
$title = $title ?: Yii::t('yii', $name); |
||||
|
$options = array_merge([ |
||||
|
'title' => $title, |
||||
|
'aria-label' => $title, |
||||
|
'data-pjax' => '0', |
||||
|
], $additionalOptions, $this->buttonOptions); |
||||
|
$icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]); |
||||
|
return Html::a($icon, $url, $options); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
protected function visibleButtons($name, $config) |
||||
|
{ |
||||
|
$this->visibleButtons[$name] = function ($model, $key, $index) use ($config) { |
||||
|
$attributes = $config['attributes']; |
||||
|
$values = $config['values']; |
||||
|
if (isset($config['rule']) && $config['rule'] == 'or') { |
||||
|
foreach ($attributes as $k => $attribute) { |
||||
|
if ($model->$attribute == $values[$k]) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
}else{ |
||||
|
foreach ($attributes as $k => $attribute) { |
||||
|
if ($model->$attribute != $values[$k]) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通过给定的action和model创建一个URL. |
||||
|
* |
||||
|
* @param string $action 按钮名 |
||||
|
* @param \yii\db\ActiveRecordInterface $model 数据模型 |
||||
|
* @param mixed $key 模型的ID |
||||
|
* @param int $index 行号 |
||||
|
* @return string the created URL |
||||
|
*/ |
||||
|
public function createUrl($action, $model, $key, $index) |
||||
|
{ |
||||
|
if (is_callable($this->urlCreator)) { |
||||
|
return call_user_func($this->urlCreator, $action, $model, $key, $index, $this); |
||||
|
} |
||||
|
|
||||
|
$params = is_array($key) ? $key : ['id' => (string)$key]; |
||||
|
$params[0] = $this->controller ? $this->controller . '/' . $action : $action; |
||||
|
|
||||
|
return Url::toRoute($params); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* {@inheritdoc} |
||||
|
*/ |
||||
|
protected function renderDataCellContent($model, $key, $index) |
||||
|
{ |
||||
|
return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) { |
||||
|
$name = $matches[1]; |
||||
|
|
||||
|
if (isset($this->visibleButtons[$name])) { |
||||
|
$isVisible = $this->visibleButtons[$name] instanceof \Closure ? call_user_func($this->visibleButtons[$name], $model, $key, $index) : $this->visibleButtons[$name]; |
||||
|
} else { |
||||
|
$isVisible = true; |
||||
|
} |
||||
|
|
||||
|
if ($isVisible && isset($this->buttons[$name])) { |
||||
|
$url = $this->createUrl($name, $model, $key, $index); |
||||
|
return call_user_func($this->buttons[$name], $url, $model, $key); |
||||
|
} |
||||
|
|
||||
|
return ''; |
||||
|
}, $this->template); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,958 @@ |
|||||
|
<?php |
||||
|
|
||||
|
namespace iron\widget; |
||||
|
|
||||
|
use yii\helpers\ArrayHelper; |
||||
|
use yii\base\InvalidConfigException; |
||||
|
use yii\base\InvalidParamException; |
||||
|
use yii\i18n\Formatter; |
||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet; |
||||
|
|
||||
|
/** |
||||
|
* Excel Widget for generate Excel File or for load Excel File. |
||||
|
* |
||||
|
* Usage |
||||
|
* ----- |
||||
|
* |
||||
|
* Exporting data into an excel file. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* // export data only one worksheet.
|
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::widget([ |
||||
|
* 'models' => $allModels, |
||||
|
* 'mode' => 'export', //default value as 'export'
|
||||
|
* 'columns' => ['column1','column2','column3'], |
||||
|
* //without header working, because the header will be get label from attribute label.
|
||||
|
* 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* ]); |
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::export([ |
||||
|
* 'models' => $allModels, |
||||
|
* 'columns' => ['column1','column2','column3'], |
||||
|
* //without header working, because the header will be get label from attribute label.
|
||||
|
* 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* ]); |
||||
|
* |
||||
|
* // export data with multiple worksheet.
|
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::widget([ |
||||
|
* 'isMultipleSheet' => true, |
||||
|
* 'models' => [ |
||||
|
* 'sheet1' => $allModels1, |
||||
|
* 'sheet2' => $allModels2, |
||||
|
* 'sheet3' => $allModels3 |
||||
|
* ], |
||||
|
* 'mode' => 'export', //default value as 'export'
|
||||
|
* 'columns' => [ |
||||
|
* 'sheet1' => ['column1','column2','column3'], |
||||
|
* 'sheet2' => ['column1','column2','column3'], |
||||
|
* 'sheet3' => ['column1','column2','column3'] |
||||
|
* ], |
||||
|
* //without header working, because the header will be get label from attribute label.
|
||||
|
* 'headers' => [ |
||||
|
* 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'] |
||||
|
* ], |
||||
|
* ]); |
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::export([ |
||||
|
* 'isMultipleSheet' => true, |
||||
|
* 'models' => [ |
||||
|
* 'sheet1' => $allModels1, |
||||
|
* 'sheet2' => $allModels2, |
||||
|
* 'sheet3' => $allModels3 |
||||
|
* ], |
||||
|
* 'columns' => [ |
||||
|
* 'sheet1' => ['column1','column2','column3'], |
||||
|
* 'sheet2' => ['column1','column2','column3'], |
||||
|
* 'sheet3' => ['column1','column2','column3'] |
||||
|
* ], |
||||
|
* //without header working, because the header will be get label from attribute label.
|
||||
|
* 'headers' => [ |
||||
|
* 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'] |
||||
|
* ], |
||||
|
* ]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* New Feature for exporting data, you can use this if you familiar yii gridview. |
||||
|
* That is same with gridview data column. |
||||
|
* Columns in array mode valid params are 'attribute', 'header', 'format', 'value', and footer (TODO). |
||||
|
* Columns in string mode valid layout are 'attribute:format:header:footer(TODO)'. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::export([ |
||||
|
* 'models' => Post::find()->all(), |
||||
|
* 'columns' => [ |
||||
|
* 'author.name:text:Author Name', |
||||
|
* [ |
||||
|
* 'attribute' => 'content', |
||||
|
* 'header' => 'Content Post', |
||||
|
* 'format' => 'text', |
||||
|
* 'value' => function($model) { |
||||
|
* return ExampleClass::removeText('example', $model->content); |
||||
|
* }, |
||||
|
* ], |
||||
|
* 'like_it:text:Reader like this content', |
||||
|
* 'created_at:datetime', |
||||
|
* [ |
||||
|
* 'attribute' => 'updated_at', |
||||
|
* 'format' => 'date', |
||||
|
* ], |
||||
|
* ], |
||||
|
* 'headers' => [ |
||||
|
* 'created_at' => 'Date Created Content', |
||||
|
* ], |
||||
|
* ]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* |
||||
|
* Import file excel and return into an array. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::import($fileName, $config); // $config is an optional
|
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::widget([ |
||||
|
* 'mode' => 'import', |
||||
|
* 'fileName' => $fileName, |
||||
|
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
|
||||
|
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
|
||||
|
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
|
||||
|
* ]); |
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::import($fileName, [ |
||||
|
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
|
||||
|
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
|
||||
|
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
|
||||
|
* ]); |
||||
|
* |
||||
|
* // import data with multiple file.
|
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::widget([ |
||||
|
* 'mode' => 'import', |
||||
|
* 'fileName' => [ |
||||
|
* 'file1' => $fileName1, |
||||
|
* 'file2' => $fileName2, |
||||
|
* 'file3' => $fileName3, |
||||
|
* ], |
||||
|
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
|
||||
|
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
|
||||
|
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
|
||||
|
* ]); |
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::import([ |
||||
|
* 'file1' => $fileName1, |
||||
|
* 'file2' => $fileName2, |
||||
|
* 'file3' => $fileName3, |
||||
|
* ], [ |
||||
|
* 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
|
||||
|
* 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
|
||||
|
* 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
|
||||
|
* ]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* Result example from the code on the top : |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* // only one sheet or specified sheet.
|
||||
|
* |
||||
|
* Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)); |
||||
|
* |
||||
|
* // data with multiple worksheet
|
||||
|
* |
||||
|
* Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)), |
||||
|
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))); |
||||
|
* |
||||
|
* // data with multiple file and specified sheet or only one worksheet
|
||||
|
* |
||||
|
* Array([file1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)), |
||||
|
* [file2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))); |
||||
|
* |
||||
|
* // data with multiple file and multiple worksheet
|
||||
|
* |
||||
|
* Array([file1] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)), |
||||
|
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))), |
||||
|
* [file2] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)), |
||||
|
* [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2), |
||||
|
* [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)))); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* @property string $mode is an export mode or import mode. valid value are 'export' and 'import' |
||||
|
* @property boolean $isMultipleSheet for set the export excel with multiple sheet. |
||||
|
* @property array $properties for set property on the excel object. |
||||
|
* @property array $models Model object or DataProvider object with much data. |
||||
|
* @property array $columns to get the attributes from the model, this valid value only the exist attribute on the model. |
||||
|
* If this is not set, then all attribute of the model will be set as columns. |
||||
|
* @property array $headers to set the header column on first line. Set this if want to custom header. |
||||
|
* If not set, the header will get attributes label of model attributes. |
||||
|
* @property string|array $fileName is a name for file name to export or import. Multiple file name only use for import mode, not work if you use the export mode. |
||||
|
* @property string $savePath is a directory to save the file or you can blank this to set the file as attachment. |
||||
|
* @property string $format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'. |
||||
|
* @property boolean $setFirstTitle to set the title column on the first line. The columns will have a header on the first line. |
||||
|
* @property boolean $asAttachment to set the file excel to download mode. |
||||
|
* @property boolean $setFirstRecordAsKeys to set the first record on excel file to a keys of array per line. |
||||
|
* If you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel. |
||||
|
* @property boolean $setIndexSheetByName to set the sheet index by sheet name or array result if the sheet not only one |
||||
|
* @property string $getOnlySheet is a sheet name to getting the data. This is only get the sheet with same name. |
||||
|
* @property array|Formatter $formatter the formatter used to format model attribute values into displayable texts. |
||||
|
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]] |
||||
|
* instance. If this property is not set, the "formatter" application component will be used. |
||||
|
* |
||||
|
* @author Moh Khoirul Anam <moh.khoirul.anaam@gmail.com> |
||||
|
* @copyright 2014 |
||||
|
* @since 1 |
||||
|
*/ |
||||
|
class Excel extends \yii\base\Widget |
||||
|
{ |
||||
|
// Border style
|
||||
|
const BORDER_NONE = 'none'; |
||||
|
const BORDER_DASHDOT = 'dashDot'; |
||||
|
const BORDER_DASHDOTDOT = 'dashDotDot'; |
||||
|
const BORDER_DASHED = 'dashed'; |
||||
|
const BORDER_DOTTED = 'dotted'; |
||||
|
const BORDER_DOUBLE = 'double'; |
||||
|
const BORDER_HAIR = 'hair'; |
||||
|
const BORDER_MEDIUM = 'medium'; |
||||
|
const BORDER_MEDIUMDASHDOT = 'mediumDashDot'; |
||||
|
const BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot'; |
||||
|
const BORDER_MEDIUMDASHED = 'mediumDashed'; |
||||
|
const BORDER_SLANTDASHDOT = 'slantDashDot'; |
||||
|
const BORDER_THICK = 'thick'; |
||||
|
const BORDER_THIN = 'thin'; |
||||
|
|
||||
|
// Colors
|
||||
|
const COLOR_BLACK = 'FF000000'; |
||||
|
const COLOR_WHITE = 'FFFFFFFF'; |
||||
|
const COLOR_RED = 'FFFF0000'; |
||||
|
const COLOR_DARKRED = 'FF800000'; |
||||
|
const COLOR_BLUE = 'FF0000FF'; |
||||
|
const COLOR_DARKBLUE = 'FF000080'; |
||||
|
const COLOR_GREEN = 'FF00FF00'; |
||||
|
const COLOR_DARKGREEN = 'FF008000'; |
||||
|
const COLOR_YELLOW = 'FFFFFF00'; |
||||
|
const COLOR_DARKYELLOW = 'FF808000'; |
||||
|
|
||||
|
// Horizontal alignment styles
|
||||
|
const HORIZONTAL_GENERAL = 'general'; |
||||
|
const HORIZONTAL_LEFT = 'left'; |
||||
|
const HORIZONTAL_RIGHT = 'right'; |
||||
|
const HORIZONTAL_CENTER = 'center'; |
||||
|
const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous'; |
||||
|
const HORIZONTAL_JUSTIFY = 'justify'; |
||||
|
const HORIZONTAL_FILL = 'fill'; |
||||
|
const HORIZONTAL_DISTRIBUTED = 'distributed'; // Excel2007 only
|
||||
|
|
||||
|
// Vertical alignment styles
|
||||
|
const VERTICAL_BOTTOM = 'bottom'; |
||||
|
const VERTICAL_TOP = 'top'; |
||||
|
const VERTICAL_CENTER = 'center'; |
||||
|
const VERTICAL_JUSTIFY = 'justify'; |
||||
|
const VERTICAL_DISTRIBUTED = 'distributed'; // Excel2007 only
|
||||
|
|
||||
|
// Read order
|
||||
|
const READORDER_CONTEXT = 0; |
||||
|
const READORDER_LTR = 1; |
||||
|
const READORDER_RTL = 2; |
||||
|
|
||||
|
// Fill types
|
||||
|
const FILL_NONE = 'none'; |
||||
|
const FILL_SOLID = 'solid'; |
||||
|
const FILL_GRADIENT_LINEAR = 'linear'; |
||||
|
const FILL_GRADIENT_PATH = 'path'; |
||||
|
const FILL_PATTERN_DARKDOWN = 'darkDown'; |
||||
|
const FILL_PATTERN_DARKGRAY = 'darkGray'; |
||||
|
const FILL_PATTERN_DARKGRID = 'darkGrid'; |
||||
|
const FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal'; |
||||
|
const FILL_PATTERN_DARKTRELLIS = 'darkTrellis'; |
||||
|
const FILL_PATTERN_DARKUP = 'darkUp'; |
||||
|
const FILL_PATTERN_DARKVERTICAL = 'darkVertical'; |
||||
|
const FILL_PATTERN_GRAY0625 = 'gray0625'; |
||||
|
const FILL_PATTERN_GRAY125 = 'gray125'; |
||||
|
const FILL_PATTERN_LIGHTDOWN = 'lightDown'; |
||||
|
const FILL_PATTERN_LIGHTGRAY = 'lightGray'; |
||||
|
const FILL_PATTERN_LIGHTGRID = 'lightGrid'; |
||||
|
const FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal'; |
||||
|
const FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis'; |
||||
|
const FILL_PATTERN_LIGHTUP = 'lightUp'; |
||||
|
const FILL_PATTERN_LIGHTVERTICAL = 'lightVertical'; |
||||
|
const FILL_PATTERN_MEDIUMGRAY = 'mediumGray'; |
||||
|
|
||||
|
// Pre-defined formats
|
||||
|
const FORMAT_GENERAL = 'General'; |
||||
|
|
||||
|
const FORMAT_TEXT = '@'; |
||||
|
|
||||
|
const FORMAT_NUMBER = '0'; |
||||
|
const FORMAT_NUMBER_00 = '0.00'; |
||||
|
const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00'; |
||||
|
const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-'; |
||||
|
|
||||
|
const FORMAT_PERCENTAGE = '0%'; |
||||
|
const FORMAT_PERCENTAGE_00 = '0.00%'; |
||||
|
|
||||
|
const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd'; |
||||
|
const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd'; |
||||
|
const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy'; |
||||
|
const FORMAT_DATE_DMYSLASH = 'd/m/yy'; |
||||
|
const FORMAT_DATE_DMYMINUS = 'd-m-yy'; |
||||
|
const FORMAT_DATE_DMMINUS = 'd-m'; |
||||
|
const FORMAT_DATE_MYMINUS = 'm-yy'; |
||||
|
const FORMAT_DATE_XLSX14 = 'mm-dd-yy'; |
||||
|
const FORMAT_DATE_XLSX15 = 'd-mmm-yy'; |
||||
|
const FORMAT_DATE_XLSX16 = 'd-mmm'; |
||||
|
const FORMAT_DATE_XLSX17 = 'mmm-yy'; |
||||
|
const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm'; |
||||
|
const FORMAT_DATE_DATETIME = 'd/m/yy h:mm'; |
||||
|
const FORMAT_DATE_TIME1 = 'h:mm AM/PM'; |
||||
|
const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM'; |
||||
|
const FORMAT_DATE_TIME3 = 'h:mm'; |
||||
|
const FORMAT_DATE_TIME4 = 'h:mm:ss'; |
||||
|
const FORMAT_DATE_TIME5 = 'mm:ss'; |
||||
|
const FORMAT_DATE_TIME6 = 'h:mm:ss'; |
||||
|
const FORMAT_DATE_TIME7 = 'i:s.S'; |
||||
|
const FORMAT_DATE_TIME8 = 'h:mm:ss;@'; |
||||
|
const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@'; |
||||
|
|
||||
|
const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-'; |
||||
|
const FORMAT_CURRENCY_USD = '$#,##0_-'; |
||||
|
const FORMAT_CURRENCY_EUR_SIMPLE = '#,##0.00_-"€"'; |
||||
|
const FORMAT_CURRENCY_EUR = '#,##0_-"€"'; |
||||
|
|
||||
|
/** |
||||
|
* @var string mode is an export mode or import mode. valid value are 'export' and 'import'. |
||||
|
*/ |
||||
|
public $mode = 'export'; |
||||
|
/** |
||||
|
* @var boolean for set the export excel with multiple sheet. |
||||
|
*/ |
||||
|
public $isMultipleSheet = false; |
||||
|
/** |
||||
|
* @var array properties for set property on the excel object. |
||||
|
*/ |
||||
|
public $properties; |
||||
|
/** |
||||
|
* @var Model object or DataProvider object with much data. |
||||
|
*/ |
||||
|
public $models; |
||||
|
/** |
||||
|
* @var array columns to get the attributes from the model, this valid value only the exist attribute on the model. |
||||
|
* If this is not set, then all attribute of the model will be set as columns. |
||||
|
*/ |
||||
|
public $columns = []; |
||||
|
/** |
||||
|
* @var array header to set the header column on first line. Set this if want to custom header. |
||||
|
* If not set, the header will get attributes label of model attributes. |
||||
|
*/ |
||||
|
public $headers = []; |
||||
|
/** |
||||
|
* @var string|array name for file name to export or save. |
||||
|
*/ |
||||
|
public $fileName; |
||||
|
/** |
||||
|
* @var string save path is a directory to save the file or you can blank this to set the file as attachment. |
||||
|
*/ |
||||
|
public $savePath; |
||||
|
/** |
||||
|
* @var string format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'. |
||||
|
*/ |
||||
|
public $format; |
||||
|
/** |
||||
|
* @var boolean to set the title column on the first line. |
||||
|
*/ |
||||
|
public $setFirstTitle = true; |
||||
|
/** |
||||
|
* @var boolean to set the file excel to download mode. |
||||
|
*/ |
||||
|
public $asAttachment = false; |
||||
|
/** |
||||
|
* @var boolean to set the first record on excel file to a keys of array per line. |
||||
|
* If you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel. |
||||
|
*/ |
||||
|
public $setFirstRecordAsKeys = true; |
||||
|
/** |
||||
|
* @var boolean to set the sheet index by sheet name or array result if the sheet not only one. |
||||
|
*/ |
||||
|
public $setIndexSheetByName = false; |
||||
|
/** |
||||
|
* @var string sheetname to getting. This is only get the sheet with same name. |
||||
|
*/ |
||||
|
public $getOnlySheet; |
||||
|
/** |
||||
|
* @var boolean to set the import data will return as array. |
||||
|
*/ |
||||
|
public $asArray; |
||||
|
/** |
||||
|
* @var array to unread record by index number. |
||||
|
*/ |
||||
|
public $leaveRecordByIndex = []; |
||||
|
/** |
||||
|
* @var array to read record by index, other will leave. |
||||
|
*/ |
||||
|
public $getOnlyRecordByIndex = []; |
||||
|
/** |
||||
|
* @var array|Formatter the formatter used to format model attribute values into displayable texts. |
||||
|
* This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]] |
||||
|
* instance. If this property is not set, the "formatter" application component will be used. |
||||
|
*/ |
||||
|
public $formatter; |
||||
|
/** |
||||
|
* @var boolean define the column autosize |
||||
|
*/ |
||||
|
public $autoSize = false; |
||||
|
/** |
||||
|
* @var boolean if true, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted. |
||||
|
*/ |
||||
|
public $preCalculationFormula = false; |
||||
|
/** |
||||
|
* @var boolean Because of a bug in the Office2003 compatibility pack, there can be some small issues when opening Xlsx spreadsheets (mostly related to formula calculation) |
||||
|
*/ |
||||
|
public $compatibilityOffice2003 = false; |
||||
|
/** |
||||
|
* @var custom CSV delimiter for import. Works only with CSV files |
||||
|
*/ |
||||
|
public $CSVDelimiter = ";"; |
||||
|
/** |
||||
|
* @var custom CSV encoding for import. Works only with CSV files |
||||
|
*/ |
||||
|
public $CSVEncoding = "UTF-8"; |
||||
|
|
||||
|
/** |
||||
|
* (non-PHPdoc) |
||||
|
* @see \yii\base\Object::init() |
||||
|
*/ |
||||
|
public function init() |
||||
|
{ |
||||
|
parent::init(); |
||||
|
if ($this->formatter == null) { |
||||
|
$this->formatter = \Yii::$app->getFormatter(); |
||||
|
} elseif (is_array($this->formatter)) { |
||||
|
$this->formatter = \Yii::createObject($this->formatter); |
||||
|
} |
||||
|
if (!$this->formatter instanceof Formatter) { |
||||
|
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Setting data from models |
||||
|
*/ |
||||
|
public function executeColumns(&$activeSheet = null, $models, $columns = [], $headers = []) |
||||
|
{ |
||||
|
if ($activeSheet == null) { |
||||
|
$activeSheet = $this->activeSheet; |
||||
|
} |
||||
|
$hasHeader = false; |
||||
|
$row = 1; |
||||
|
$char = 26; |
||||
|
foreach ($models as $model) { |
||||
|
if (empty($columns)) { |
||||
|
$columns = $model->attributes(); |
||||
|
} |
||||
|
if ($this->setFirstTitle && !$hasHeader) { |
||||
|
$isPlus = false; |
||||
|
$colplus = 0; |
||||
|
$colnum = 1; |
||||
|
foreach ($columns as $key=>$column) { |
||||
|
$col = ''; |
||||
|
if ($colnum > $char) { |
||||
|
$colplus += 1; |
||||
|
$colnum = 1; |
||||
|
$isPlus = true; |
||||
|
} |
||||
|
if ($isPlus) { |
||||
|
$col .= chr(64+$colplus); |
||||
|
} |
||||
|
$col .= chr(64+$colnum); |
||||
|
$header = ''; |
||||
|
if (is_array($column)) { |
||||
|
|
||||
|
if (isset($column['header'])) { |
||||
|
$header = $column['header']; |
||||
|
}elseif(isset($column['label'])){ |
||||
|
$header = $column['label']; |
||||
|
} elseif (isset($column['attribute']) && isset($headers[$column['attribute']])) { |
||||
|
$header = $headers[$column['attribute']]; |
||||
|
} elseif (isset($column['attribute'])) { |
||||
|
$header = $model->getAttributeLabel($column['attribute']); |
||||
|
} elseif (isset($column['cellFormat']) && is_array($column['cellFormat'])) { |
||||
|
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']); |
||||
|
} |
||||
|
} else { |
||||
|
if(isset($headers[$column])) { |
||||
|
$header = $headers[$column]; |
||||
|
} else { |
||||
|
$header = $model->getAttributeLabel($column); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
if (isset($column['width'])) { |
||||
|
$activeSheet->getColumnDimension(strtoupper($col))->setWidth($column['width']); |
||||
|
} |
||||
|
$activeSheet->setCellValue($col.$row,$header); |
||||
|
$colnum++; |
||||
|
} |
||||
|
$hasHeader=true; |
||||
|
$row++; |
||||
|
} |
||||
|
$isPlus = false; |
||||
|
$colplus = 0; |
||||
|
$colnum = 1; |
||||
|
foreach ($columns as $key=>$column) { |
||||
|
$col = ''; |
||||
|
if ($colnum > $char) { |
||||
|
$colplus++; |
||||
|
$colnum = 1; |
||||
|
$isPlus = true; |
||||
|
} |
||||
|
if ($isPlus) { |
||||
|
$col .= chr(64+$colplus); |
||||
|
} |
||||
|
$col .= chr(64+$colnum); |
||||
|
if (is_array($column)) { |
||||
|
$column_value = $this->executeGetColumnData($model, $column); |
||||
|
if (isset($column['cellFormat']) && is_array($column['cellFormat'])) { |
||||
|
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']); |
||||
|
} |
||||
|
} else { |
||||
|
$column_value = $this->executeGetColumnData($model, ['attribute' => $column]); |
||||
|
} |
||||
|
$activeSheet->setCellValue($col.$row,$column_value); |
||||
|
$colnum++; |
||||
|
} |
||||
|
$row++; |
||||
|
|
||||
|
if($this->autoSize){ |
||||
|
foreach (range(0, $colnum) as $col) { |
||||
|
$activeSheet->getColumnDimensionByColumn($col)->setAutoSize(true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Setting label or keys on every record if setFirstRecordAsKeys is true. |
||||
|
* @param array $sheetData |
||||
|
* @return multitype:multitype:array |
||||
|
*/ |
||||
|
public function executeArrayLabel($sheetData) |
||||
|
{ |
||||
|
$keys = ArrayHelper::remove($sheetData, '1'); |
||||
|
|
||||
|
$new_data = []; |
||||
|
|
||||
|
foreach ($sheetData as $values) |
||||
|
{ |
||||
|
$new_data[] = array_combine($keys, $values); |
||||
|
} |
||||
|
|
||||
|
return $new_data; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Leave record with same index number. |
||||
|
* @param array $sheetData |
||||
|
* @param array $index |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function executeLeaveRecords($sheetData = [], $index = []) |
||||
|
{ |
||||
|
foreach ($sheetData as $key => $data) |
||||
|
{ |
||||
|
if (in_array($key, $index)) |
||||
|
{ |
||||
|
unset($sheetData[$key]); |
||||
|
} |
||||
|
} |
||||
|
return $sheetData; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Read record with same index number. |
||||
|
* @param array $sheetData |
||||
|
* @param array $index |
||||
|
* @return array |
||||
|
*/ |
||||
|
public function executeGetOnlyRecords($sheetData = [], $index = []) |
||||
|
{ |
||||
|
foreach ($sheetData as $key => $data) |
||||
|
{ |
||||
|
if (!in_array($key, $index)) |
||||
|
{ |
||||
|
unset($sheetData[$key]); |
||||
|
} |
||||
|
} |
||||
|
return $sheetData; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Getting column value. |
||||
|
* @param Model $model |
||||
|
* @param array $params |
||||
|
* @return Ambigous <NULL, string, mixed> |
||||
|
*/ |
||||
|
public function executeGetColumnData($model, $params = []) |
||||
|
{ |
||||
|
$value = null; |
||||
|
if (isset($params['value']) && $params['value'] !== null) { |
||||
|
if (is_string($params['value'])) { |
||||
|
$value = ArrayHelper::getValue($model, $params['value']); |
||||
|
} else { |
||||
|
$value = call_user_func($params['value'], $model, $this); |
||||
|
} |
||||
|
} elseif (isset($params['attribute']) && $params['attribute'] !== null) { |
||||
|
$value = ArrayHelper::getValue($model, $params['attribute']); |
||||
|
} |
||||
|
|
||||
|
if (isset($params['format']) && $params['format'] != null) |
||||
|
$value = $this->formatter()->format($value, $params['format']); |
||||
|
|
||||
|
return $value; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Populating columns for checking the column is string or array. if is string this will be checking have a formatter or header. |
||||
|
* @param array $columns |
||||
|
* @throws InvalidParamException |
||||
|
* @return multitype:multitype:array |
||||
|
*/ |
||||
|
public function populateColumns($columns = []) |
||||
|
{ |
||||
|
$_columns = []; |
||||
|
foreach ($columns as $key => $value) |
||||
|
{ |
||||
|
if (is_string($value)) |
||||
|
{ |
||||
|
$value_log = explode(':', $value); |
||||
|
$_columns[$key] = ['attribute' => $value_log[0]]; |
||||
|
|
||||
|
if (isset($value_log[1]) && $value_log[1] !== null) { |
||||
|
$_columns[$key]['format'] = $value_log[1]; |
||||
|
} |
||||
|
|
||||
|
if (isset($value_log[2]) && $value_log[2] !== null) { |
||||
|
$_columns[$key]['header'] = $value_log[2]; |
||||
|
} |
||||
|
} elseif (is_array($value)) { |
||||
|
if(isset($value['class'])){ |
||||
|
continue; |
||||
|
} |
||||
|
if (!isset($value['attribute']) && !isset($value['value'])) { |
||||
|
throw new \InvalidArgumentException('Attribute or Value must be defined.'); |
||||
|
} |
||||
|
$_columns[$key] = $value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $_columns; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Formatter for i18n. |
||||
|
* @return Formatter |
||||
|
*/ |
||||
|
public function formatter() |
||||
|
{ |
||||
|
if (!isset($this->formatter)) |
||||
|
$this->formatter = \Yii::$app->getFormatter(); |
||||
|
|
||||
|
return $this->formatter; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Setting header to download generated file xls |
||||
|
*/ |
||||
|
public function setHeaders() |
||||
|
{ |
||||
|
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); |
||||
|
header('Content-Disposition: attachment;filename="' . $this->getFileName() .'"'); |
||||
|
header('Cache-Control: max-age=0'); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Getting the file name of exporting xls file |
||||
|
* @return string |
||||
|
*/ |
||||
|
public function getFileName() |
||||
|
{ |
||||
|
$fileName = 'exports.xlsx'; |
||||
|
if (isset($this->fileName)) { |
||||
|
$fileName = $this->fileName; |
||||
|
if (strpos($fileName, '.xlsx') === false) |
||||
|
$fileName .= '.xlsx'; |
||||
|
} |
||||
|
return $fileName; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Setting properties for excel file |
||||
|
* @param PHPExcel $objectExcel |
||||
|
* @param array $properties |
||||
|
*/ |
||||
|
public function properties(&$objectExcel, $properties = []) |
||||
|
{ |
||||
|
foreach ($properties as $key => $value) |
||||
|
{ |
||||
|
$keyname = "set" . ucfirst($key); |
||||
|
$objectExcel->getProperties()->{$keyname}($value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* saving the xls file to download or to path |
||||
|
*/ |
||||
|
public function writeFile($sheet) |
||||
|
{ |
||||
|
if (!isset($this->format)) |
||||
|
$this->format = 'Xlsx'; |
||||
|
$objectwriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($sheet, $this->format); |
||||
|
$path = 'php://output'; |
||||
|
if (isset($this->savePath) && $this->savePath != null) { |
||||
|
$path = $this->savePath . '/' . $this->getFileName(); |
||||
|
} |
||||
|
$objectwriter->setOffice2003Compatibility($this->compatibilityOffice2003); |
||||
|
$objectwriter->setPreCalculateFormulas($this->preCalculationFormula); |
||||
|
$objectwriter->save($path); |
||||
|
if ($path == 'php://output') |
||||
|
exit(); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* reading the xls file |
||||
|
*/ |
||||
|
public function readFile($fileName) |
||||
|
{ |
||||
|
if (!isset($this->format)) |
||||
|
$this->format = \PhpOffice\PhpSpreadsheet\IOFactory::identify($fileName); |
||||
|
$objectreader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($this->format); |
||||
|
if ($this->format == "Csv") { |
||||
|
$objectreader->setDelimiter($this->CSVDelimiter); |
||||
|
$objectreader->setInputEncoding($this->CSVEncoding); |
||||
|
} |
||||
|
$objectPhpExcel = $objectreader->load($fileName); |
||||
|
|
||||
|
$sheetCount = $objectPhpExcel->getSheetCount(); |
||||
|
|
||||
|
$sheetDatas = []; |
||||
|
|
||||
|
if ($sheetCount > 1) { |
||||
|
foreach ($objectPhpExcel->getSheetNames() as $sheetIndex => $sheetName) { |
||||
|
if (isset($this->getOnlySheet) && $this->getOnlySheet != null) { |
||||
|
if(!$objectPhpExcel->getSheetByName($this->getOnlySheet)) { |
||||
|
return $sheetDatas; |
||||
|
} |
||||
|
$objectPhpExcel->setActiveSheetIndexByName($this->getOnlySheet); |
||||
|
$indexed = $this->getOnlySheet; |
||||
|
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true); |
||||
|
if ($this->setFirstRecordAsKeys) { |
||||
|
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]); |
||||
|
} |
||||
|
if (!empty($this->getOnlyRecordByIndex)) { |
||||
|
$sheetDatas[$indexed] = $this->executeGetOnlyRecords($sheetDatas[$indexed], $this->getOnlyRecordByIndex); |
||||
|
} |
||||
|
if (!empty($this->leaveRecordByIndex)) { |
||||
|
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex); |
||||
|
} |
||||
|
return $sheetDatas[$indexed]; |
||||
|
} else { |
||||
|
$objectPhpExcel->setActiveSheetIndexByName($sheetName); |
||||
|
$indexed = $this->setIndexSheetByName==true ? $sheetName : $sheetIndex; |
||||
|
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true); |
||||
|
if ($this->setFirstRecordAsKeys) { |
||||
|
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]); |
||||
|
} |
||||
|
if (!empty($this->getOnlyRecordByIndex) && isset($this->getOnlyRecordByIndex[$indexed]) && is_array($this->getOnlyRecordByIndex[$indexed])) { |
||||
|
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex[$indexed]); |
||||
|
} |
||||
|
if (!empty($this->leaveRecordByIndex) && isset($this->leaveRecordByIndex[$indexed]) && is_array($this->leaveRecordByIndex[$indexed])) { |
||||
|
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex[$indexed]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
$sheetDatas = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true); |
||||
|
if ($this->setFirstRecordAsKeys) { |
||||
|
$sheetDatas = $this->executeArrayLabel($sheetDatas); |
||||
|
} |
||||
|
if (!empty($this->getOnlyRecordByIndex)) { |
||||
|
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex); |
||||
|
} |
||||
|
if (!empty($this->leaveRecordByIndex)) { |
||||
|
$sheetDatas = $this->executeLeaveRecords($sheetDatas, $this->leaveRecordByIndex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return $sheetDatas; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* (non-PHPdoc) |
||||
|
* @see \yii\base\Widget::run() |
||||
|
*/ |
||||
|
public function run() |
||||
|
{ |
||||
|
if ($this->mode == 'export') |
||||
|
{ |
||||
|
$sheet = new Spreadsheet(); |
||||
|
|
||||
|
if (!isset($this->models)) |
||||
|
throw new InvalidConfigException('Config models must be set'); |
||||
|
|
||||
|
if (isset($this->properties)) |
||||
|
{ |
||||
|
$this->properties($sheet, $this->properties); |
||||
|
} |
||||
|
|
||||
|
if ($this->isMultipleSheet) { |
||||
|
$index = 0; |
||||
|
$worksheet = []; |
||||
|
foreach ($this->models as $title => $models) { |
||||
|
$sheet->createSheet($index); |
||||
|
$sheet->getSheet($index)->setTitle($title); |
||||
|
$worksheet[$index] = $sheet->getSheet($index); |
||||
|
$columns = isset($this->columns[$title]) ? $this->columns[$title] : []; |
||||
|
$headers = isset($this->headers[$title]) ? $this->headers[$title] : []; |
||||
|
$this->executeColumns($worksheet[$index], $models, $this->populateColumns($columns), $headers); |
||||
|
$index++; |
||||
|
} |
||||
|
} else { |
||||
|
$worksheet = $sheet->getActiveSheet(); |
||||
|
$this->executeColumns($worksheet, $this->models, isset($this->columns) ? $this->populateColumns($this->columns) : [], isset($this->headers) ? $this->headers : []); |
||||
|
} |
||||
|
|
||||
|
if ($this->asAttachment) { |
||||
|
$this->setHeaders(); |
||||
|
} |
||||
|
$this->writeFile($sheet); |
||||
|
$sheet->disconnectWorksheets(); |
||||
|
unset($sheet); |
||||
|
} |
||||
|
elseif ($this->mode == 'import') |
||||
|
{ |
||||
|
if (is_array($this->fileName)) { |
||||
|
$datas = []; |
||||
|
foreach ($this->fileName as $key => $filename) { |
||||
|
$datas[$key] = $this->readFile($filename); |
||||
|
} |
||||
|
return $datas; |
||||
|
} else { |
||||
|
return $this->readFile($this->fileName); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Exporting data into an excel file. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::export([ |
||||
|
* 'models' => $allModels, |
||||
|
* 'columns' => ['column1','column2','column3'], |
||||
|
* //without header working, because the header will be get label from attribute label.
|
||||
|
* 'header' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'], |
||||
|
* ]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* New Feature for exporting data, you can use this if you familiar yii gridview. |
||||
|
* That is same with gridview data column. |
||||
|
* Columns in array mode valid params are 'attribute', 'header', 'format', 'value', and footer (TODO). |
||||
|
* Columns in string mode valid layout are 'attribute:format:header:footer(TODO)'. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* \moonland\phpexcel\Excel::export([ |
||||
|
* 'models' => Post::find()->all(), |
||||
|
* 'columns' => [ |
||||
|
* 'author.name:text:Author Name', |
||||
|
* [ |
||||
|
* 'attribute' => 'content', |
||||
|
* 'header' => 'Content Post', |
||||
|
* 'format' => 'text', |
||||
|
* 'value' => function($model) { |
||||
|
* return ExampleClass::removeText('example', $model->content); |
||||
|
* }, |
||||
|
* ], |
||||
|
* 'like_it:text:Reader like this content', |
||||
|
* 'created_at:datetime', |
||||
|
* [ |
||||
|
* 'attribute' => 'updated_at', |
||||
|
* 'format' => 'date', |
||||
|
* ], |
||||
|
* ], |
||||
|
* 'headers' => [ |
||||
|
* 'created_at' => 'Date Created Content', |
||||
|
* ], |
||||
|
* ]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* @param array $config |
||||
|
* @return string |
||||
|
*/ |
||||
|
public static function export($config=[]) |
||||
|
{ |
||||
|
$config = ArrayHelper::merge(['mode' => 'export'], $config); |
||||
|
return self::widget($config); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Import file excel and return into an array. |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* $data = \moonland\phpexcel\Excel::import($fileName, ['setFirstRecordAsKeys' => true]); |
||||
|
* |
||||
|
* ~~~ |
||||
|
* |
||||
|
* @param string!array $fileName to load. |
||||
|
* @param array $config is a more configuration. |
||||
|
* @return string |
||||
|
*/ |
||||
|
public static function import($fileName, $config=[]) |
||||
|
{ |
||||
|
$config = ArrayHelper::merge(['mode' => 'import', 'fileName' => $fileName, 'asArray' => true], $config); |
||||
|
return self::widget($config); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param array $config |
||||
|
* @return string |
||||
|
*/ |
||||
|
public static function widget($config = []) |
||||
|
{ |
||||
|
if ((isset($config['mode']) and $config['mode'] == 'import') && !isset($config['asArray'])) { |
||||
|
$config['asArray'] = true; |
||||
|
} |
||||
|
|
||||
|
if (isset($config['asArray']) && $config['asArray']==true) |
||||
|
{ |
||||
|
$config['class'] = get_called_class(); |
||||
|
$widget = \Yii::createObject($config); |
||||
|
return $widget->run(); |
||||
|
} else { |
||||
|
return parent::widget($config); |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue