Мне памятка, для себя, что бы не забыть, что за чем делаю)
получается классная структура проекта в итоге
database
Заранее создать 2 базы данных:
install
Перехожу в репу https://github.com/andy87/yii2-bat-installer
Забираю "yii2-installer.bat", копирую контент в NotePad
меняю кодировку на UTF-8 (Кодировка > Преобразовать в UTF-8)
в корневую папку проекта сохраняю файл под именем `yii2_installer.bat` в расширении `bat`
запускаю исполнение `bat` файла, дожидаюсь завершения установки, далее ... удаляю `yii2_installer.bat`
dirictory
переименовываю директорию `yii` в `app`
- добавляю в корень проекта директорию `uploads`
- добавляю в корень проекта директорию `static`
из директории `app` удаляю:- (file) Vagrantfile
- (dir) vagrant
из директории `app` в корень проекта:- переношу все файлы ( кроме `.gitignore`)
- переношу папку `vendor`
В корень проекта добавляю файлы:
.env.example
| Code | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # === DATABASE ===
DB_DRIVER="mysql"
DB_HOST="localhost"
DB_NAME="local_database_name"
DB_USER=""
DB_PASS=""
DB_DSN_LOCAL=${DB_DRIVER}:host=${DB_HOST};dbname=${DB_NAME}
# // TEST
DB_HOST_TEST=${DB_HOST}
DB_NAME_TEST="tests_database_name"
DB_DSN_TESTS=${DB_DRIVER}:host=${DB_HOST_TEST};dbname=${DB_NAME_TEST}
# === MAILER ===
MAILER_FAKE="true"
MAILER_HOST=""
MAILER_USERNAME=""
MAILER_PASSWORD=""
MAILER_PORT="465"
MAILER_DSN="native://default" |
|
.env
Контент аналогичный .enx.example
.gitignore
| Code | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| # phpstorm project files
.idea
# composer vendor dir
/vendor
composer.phar
# ENV file
.env
# yii console commands
/yii_test
/yii_test.bat
# netbeans project files
nbproject
# zend studio for eclipse project files
.buildpath
.project
.settings
# windows thumbnail cache
Thumbs.db
# Mac DS_Store Files
.DS_Store
# phpunit itself is not needed
phpunit.phar
# local phpunit config
/phpunit.xml
# vagrant runtime
/.vagrant
# ignore generated files
/app/frontend/web/index.php
/app/frontend/web/index-test.php
/app/frontend/web/robots.txt
/app/backend/web/index.php
/app/backend/web/index-test.php
/app/backend/web/robots.txt |
|
config
Редактирование файлов конфига
/app/common/config/main.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| <?php
use yii\caching\FileCache;
$root = dirname(__DIR__,3);
return [
'aliases' => [
'@app' => "$root/app",
'@upload' => "$root/upload",
'@static' => "$root/static",
'@npm' => '@vendor/npm-asset',
'@bower' => '@vendor/bower-asset',
],
'vendorPath' => "$root/vendor",
'components' => [
'cache' => [
'class' => FileCache::class,
],
],
]; |
|
/app/common/tests/_bootstrap.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <?php
use Dotenv\Dotenv;
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__.'/../../');
require_once YII_APP_BASE_PATH . '../vendor/autoload.php';
require_once YII_APP_BASE_PATH . '../vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/../config/bootstrap.php';
Dotenv::createImmutable(YII_APP_BASE_PATH . '/../','.env')->load();
// Запуск тестов в окружении `common`
// php vendor/bin/codecept run -- -c common
// php vendor/bin/codecept run unit -- -c common \common\tests\unit\{FilePath}}Test.php |
|
/app/console/config/main.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| <?php
$params = array_merge(
require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php',
require __DIR__ . '/params.php',
require __DIR__ . '/params-local.php'
);
return [
'id' => 'app-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'app\console\controllers',
'aliases' => [
'@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset',
],
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'app\common\fixtures',
],
'migrate' => [
'class' => 'yii\console\controllers\MigrateController',
'migrationPath' => '@app/console/migrations',
],
],
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
],
'params' => $params,
]; |
|
/app/frontend/config/main.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| return [
// ...
'components' => [
'request' => [
'csrfParam' => '...',
'baseUrl' => ''
],
// ...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<_c>/<_a>' => '<_c>/<_a>'
],
]
]
]; |
|
/app/frontend/tests/_bootstrap.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <?php
use Dotenv\Dotenv;
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__ . '/../../');
require_once YII_APP_BASE_PATH . '../vendor/autoload.php';
require_once YII_APP_BASE_PATH . '../vendor/yiisoft/yii2/Yii.php';
require_once YII_APP_BASE_PATH . 'common/config/bootstrap.php';
require_once __DIR__ . '/../config/bootstrap.php';
Dotenv::createImmutable(YII_APP_BASE_PATH . '/../','.env')->load();
// Запуск тестов в окружении `frontend`
// php vendor/bin/codecept run -- -c frontend
// php vendor/bin/codecept run unit -- -c frontend \common\tests\unit\{FilePath}}Test.php |
|
/app/backend/config/main.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| return [
// ...
'components' => [
'request' => [
'csrfParam' => '...',
'baseUrl' => '/admin'
],
// ...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<_c>/<_a>' => '<_c>/<_a>'
],
]
]
]; |
|
/app/backend/tests/_bootstrap.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <?php
use Dotenv\Dotenv;
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', __DIR__ . '/../../');
require_once YII_APP_BASE_PATH . '../vendor/autoload.php';
require_once YII_APP_BASE_PATH . '../vendor/yiisoft/yii2/Yii.php';
require_once YII_APP_BASE_PATH . 'common/config/bootstrap.php';
require_once __DIR__ . '/../config/bootstrap.php';
Dotenv::createImmutable(YII_APP_BASE_PATH . '/../','.env')->load();
// Запуск тестов в окружении `backend`
// php vendor/bin/codecept run -- -c backend
// php vendor/bin/codecept run unit -- -c backend \backend\tests\unit\{FilePath}}Test.php |
|
Создание эндпоинтов
Создание эндпоинтов в директории `app`
В директории `app` создаю файлы:
/app/endpoint.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| <?php
use Dotenv\Dotenv;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\web\Application;
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/common/config/bootstrap.php';
require __DIR__ . '/'.YII_CONTEXT.'/config/bootstrap.php';
Dotenv::createImmutable(__DIR__ . '/../','.env')->load();
$config = ArrayHelper::merge(
require __DIR__ . '/common/config/main.php',
require __DIR__ . '/common/config/main-local.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/main.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/main-local.php'
);
try {
$app = new Application($config);
} catch (InvalidConfigException $e) {
exit('Fatality exception : ' . $e->getMessage());
}
$app->run(); |
|
/app/endpoint-test.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| <?php
/**
* @warning: Убедитесь, что этот файл недоступен при развертывании в рабочей среде
*/
use Dotenv\Dotenv;
use yii\base\InvalidConfigException;
use yii\web\Application;
if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) die('Вам не разрешен доступ к этому файлу.');
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/common/config/bootstrap.php';
require __DIR__ . '/'.YII_CONTEXT.'/config/bootstrap.php';
Dotenv::createImmutable(__DIR__ . '/../','.env')->load();
$config = yii\helpers\ArrayHelper::merge(
require __DIR__ . '/common/config/main.php',
require __DIR__ . '/common/config/main-local.php',
require __DIR__ . '/common/config/test.php',
require __DIR__ . '/common/config/test-local.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/main.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/main-local.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/test.php',
require __DIR__ . '/'.YII_CONTEXT.'/config/test-local.php'
);
try {
$app = new Application($config);
} catch (InvalidConfigException $e) {
exit('Fatality exception : ' . $e->getMessage());
}
$app->run(); |
|
update файлы проекта:- composer.json
| Code | 1
2
3
4
5
| {
"require": {
"php": ">=8.0.0"
}
} |
|
environments
Настройка окружений
/app/environments/dev
/app/environments/dev/yii.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| #!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*/
use Dotenv\Dotenv;
use yii\base\InvalidConfigException;
use yii\console\Application;
try
{
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
defined('PATH_APP') or define('PATH_APP', __DIR__ . '/app/');
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
require PATH_APP. 'common/config/bootstrap.php';
require PATH_APP. 'console/config/bootstrap.php';
Dotenv::createImmutable(__DIR__,'.env')->load();
$config = yii\helpers\ArrayHelper::merge(
require PATH_APP. 'common/config/main.php',
require PATH_APP. 'common/config/main-local.php',
require PATH_APP. 'console/config/main.php',
require PATH_APP. 'console/config/main-local.php'
);
$application = new Application($config);
$exitCode = $application->run();
exit($exitCode);
} catch (InvalidConfigException $e) {
exit('Fatality:' . $e->getMessage());
} |
|
/app/environments/dev/yii_test.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| #!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*/
use Dotenv\Dotenv;
use yii\console\Application;
use yii\helpers\ArrayHelper;
use yii\base\InvalidConfigException;
try
{
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('PATH_APP') or define('PATH_APP', __DIR__ . '/app/');
require __DIR__.'/vendor/autoload.php';
require __DIR__.'/vendor/yiisoft/yii2/Yii.php';
require PATH_APP.'common/config/bootstrap.php';
require PATH_APP.'console/config/bootstrap.php';
Dotenv::createImmutable(__DIR__, '.env')->load();
$config = ArrayHelper::merge(
require PATH_APP.'common/config/main.php',
require PATH_APP. 'common/config/main-local.php',
require PATH_APP. 'common/config/test.php',
require PATH_APP. 'common/config/test-local.php',
require PATH_APP. 'console/config/main.php',
require PATH_APP. 'console/config/main-local.php',
require PATH_APP . 'console/config/test.php',
require PATH_APP. 'console/config/test-local.php'
);
$application = new Application($config);
$exitCode = $application->run();
exit($exitCode);
} catch (InvalidConfigException $e) {
exit('Fatality:' . $e->getMessage());
} |
|
/app/environments/dev/common/config/main-local.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| <?php
use yii\db\ActiveQuery;
use yii\db\Connection;
use yii\symfonymailer\Mailer;
if ( !function_exists('printPre') )
{
function printPre($data, bool $exit = true): void
{
if(!is_array($data) AND !is_object($data)) $data = [$data];
echo '<pre>';
print_r($data);
if ($exit) exit('</pre>');
echo '</pre>';
}
function printPreSql(ActiveQuery $query): void
{
printPre($query->createCommand()->rawSql);
}
}
return [
'components' => [
'db' => [
'class' => Connection::class,
'dsn' => $_ENV['DB_DSN_LOCAL'],
'username' => $_ENV['DB_USER'],
'password' => $_ENV['DB_PASS'],
'charset' => 'utf8',
],
'mailer' => [
'class' => Mailer::class,
'viewPath' => '@common/mail',
'useFileTransport' => $_ENV['MAILER_FAKE'],
'transport' => [
'scheme' => 'smtps',
'host' => $_ENV['MAILER_HOST'],
'username' => $_ENV['MAILER_USERNAME'],
'password' => $_ENV['MAILER_PASSWORD'],
'port' => $_ENV['MAILER_PORT'],
'dsn' => $_ENV['MAILER_DSN'],
],
],
],
]; |
|
/app/environments/dev/common/config/test-local.php
| PHP | 1
2
3
4
5
6
7
8
9
| <?php
return [
'components' => [
'db' => [
'dsn' => $_ENV['DB_DSN_TESTS'],
],
],
]; |
|
/app/environments/dev/frontend/web/index.php
| PHP | 1
2
3
4
5
6
7
| <?php
// frontend index.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'frontend');
require __DIR__.'/../../endpoint.php'; |
|
/app/environments/dev/frontend/web/index-test.php
| PHP | 1
2
3
4
5
6
7
| <?php
// frontend index.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'frontend');
require __DIR__.'/../../endpoint-test.php'; |
|
/app/environments/dev/backend/web/index.php
| PHP | 1
2
3
4
5
6
7
| <?php
// Back-end index.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'backend');
require __DIR__.'/../../endpoint.php'; |
|
/app/environments/dev/backend/web/index-test.php
| PHP | 1
2
3
4
5
6
7
| <?php
// backend index-test.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'backend');
require __DIR__.'/../../endpoint-test.php'; |
|
/app/environments/prod
/app/environments/prod/yii.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| #!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*/
use Dotenv\Dotenv;
use yii\base\InvalidConfigException;
use yii\console\Application;
try
{
defined('YII_DEBUG') or define('YII_DEBUG', false);
defined('YII_ENV') or define('YII_ENV', 'prod');
defined('PATH_APP') or define('PATH_APP', __DIR__ . '/app/');
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
require PATH_APP. 'common/config/bootstrap.php';
require PATH_APP. 'console/config/bootstrap.php';
Dotenv::createImmutable(__DIR__,'.env')->load();
$config = yii\helpers\ArrayHelper::merge(
require PATH_APP. 'common/config/main.php',
require PATH_APP. 'common/config/main-local.php',
require PATH_APP. 'console/config/main.php',
require PATH_APP. 'console/config/main-local.php'
);
$application = new Application($config);
$exitCode = $application->run();
exit($exitCode);
} catch (InvalidConfigException $e) {
exit('Fatality:' . $e->getMessage());
} |
|
/app/environments/prod/frontend/web/index.php
| PHP | 1
2
3
4
5
6
7
| <?php
// frontend index.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'frontend');
require __DIR__.'/../../endpoint.php'; |
|
/app/environments/prod/backend/web/index.php
| PHP | 1
2
3
4
5
6
7
| <?php
// Back-end index.php
defined('YII_CONTEXT') or define('YII_CONTEXT', 'backend');
require __DIR__.'/../../endpoint.php'; |
|
--------------------
/init.php:16
Правка в путях
| PHP | 1
| $root = str_replace('\\', '/', __DIR__); |
|
->
| PHP | 1
| $root = str_replace('\\', '/', __DIR__) . '/app'; |
|
| PHP | 1
| file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source)); |
|
->
| PHP | 1
2
3
| $content = file_get_contents($root . '/' . $source);
if (str_contains($target, 'yii')) $root = "$root/..";
file_put_contents($root . '/' . $target, $content); |
|
Настройка сервера.
Apache(OS)
Создание файлов в корне проекта
.htaccess
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| <IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
</IfModule>
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_HOST} ^/(upload)
RewriteRule ^upload/(.*)$ upload/$1 [L]
# если /svg, то в svg
RewriteCond %{REQUEST_URI} ^/(static)
RewriteRule ^static/(.*)$ static/$1 [L]
# если /admin, то в backend
RewriteCond %{REQUEST_URI} ^/(admin)
RewriteRule ^admin/assets/(.*)$ app/backend/web/assets/$1 [L]
RewriteRule ^admin/images/(.*)$ app/backend/web/images/$1 [L]
RewriteRule ^admin/css/(.*)$ app/backend/web/css/$1 [L]
RewriteRule ^admin/js/(.*)$ app/backend/web/js/$1 [L]
RewriteCond %{REQUEST_URI} !^/backend/web/(assets|js|css|js)/
RewriteCond %{REQUEST_URI} ^/(admin)
RewriteRule ^.*$ app/backend/web/index.php [L]
RewriteCond %{REQUEST_URI} ^/(assets|css|js|images|fonts)
RewriteRule ^assets/(.*)$ app/frontend/web/assets/$1 [L]
RewriteRule ^images/(.*)$ app/frontend/web/images/$1 [L]
RewriteRule ^css/(.*)$ app/frontend/web/css/$1 [L]
RewriteRule ^js/(.*)$ app/frontend/web/js/$1 [L]
RewriteRule ^(.*)$ app/frontend/web/$1 [L]
RewriteCond %{REQUEST_URI} !^/(frontend|backend)/web/(assets|css|js)/
RewriteCond %{REQUEST_URI} !index.php
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ app/frontend/web/index.php
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
</IfModule> |
|
/app/backend/web/.htaccess
| PHP | 1
2
3
4
5
6
7
8
| RewriteEngine on
# если это папка или файл, открываем его
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# в противном случае перенаправляем на index.php
RewriteRule . index.php |
|
/app/frontend/web/.htaccess
| PHP | 1
2
3
4
5
6
7
8
| RewriteEngine on
# если это папка или файл, открываем его
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# в противном случае перенаправляем на index.php
RewriteRule . index.php |
|
Migration
Создание файлов для миграций:
Создание компонентов миграций
/app/console/components/migrations/Migration
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| <?php
namespace console\components\migrations;
use yii\console\ExitCode;
use yii\db\Exception;
/**
*
*/
abstract class Migration extends \yii\db\Migration
{
/** @var string */
public const TABLE_NAME = '';
/** @var array */
public const FOREIGN_KEYS = [];
/** @var bool */
public const DELETE_TABLE = true;
/**
* @param $table
* @param $columns
* @param $options
*
* @return void
*/
public function createTable($table, $columns, $options = null): void
{
// https://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
$tableOptions = ($this->db->driverName === 'mysql')
? 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'
: null;
parent::createTable($table, $columns, $tableOptions);
$this->setupForeignKey();
}
/**
* @return int
*/
public function safeDown(): int
{
try {
$this->dropForeignKeyList();
if (static::DELETE_TABLE) $this->dropTable(self::TABLE_NAME );
} catch ( Exception $e ) {
echo $e->getMessage();
return ExitCode::DATAERR;
}
return ExitCode::OK;
}
/**
* @return void
*/
public function setupForeignKey(): void
{
foreach (static::FOREIGN_KEYS as $fk_data )
call_user_func_array(array($this, 'addForeignKey'), $fk_data);
}
/**
* @return void
*/
public function dropForeignKeyList(): void
{
foreach (static::FOREIGN_KEYS as $fk_data )
$this->dropForeignKey($fk_data[0],$fk_data[1]);
}
} |
|
Далее не обязательные компоненты, которые можно добавить в процессе.
/app/console/components/migrations/MigrationAddColumn.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| <?php
namespace console\components\migrations;
use yii\console\ExitCode;
/**
*
*/
abstract class MigrationAddColumn extends Migration
{
/** @var string */
public string $columnName = '';
/**
* @param $table
* @param $column
* @param $type
*
* @return void
*/
public function addColumn($table, $column, $type): void
{
parent::addColumn($table, $column, $type);
$this->setupForeignKey();
}
/**
* @return int
*/
public function safeDown(): int
{
$this->dropForeignKeyList();
$this->dropColumn(self::TABLE_NAME, $this->columnName );
return ExitCode::OK;
}
} |
|
/app/console/components/migrations/MigrationAlterColumn.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| <?php
namespace console\components\migrations;
use yii\console\ExitCode;
/**
*
*/
abstract class MigrationAlterColumn extends Migration
{
/** @var string */
public string $columnName = '';
/**
* @param $table
* @param $column
* @param $type
*
* @return void
*/
public function alterColumn($table, $column, $type): void
{
parent::alterColumn($table, $column, $type);
$this->setupForeignKey();
}
/**
* @return int
*/
public function safeDown(): int
{
$this->dropForeignKeyList();
return ExitCode::OK;
}
} |
|
/app/console/components/migrations/MigrationRemoveColumn.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| <?php
namespace console\components\migrations;
use yii\console\ExitCode;
use yii\db\ColumnSchemaBuilder;
/**
*
*/
abstract class MigrationRemoveColumn extends Migration
{
/** @var string */
public string $columnName = '';
/**
* @param $table
* @param $column
* @param $type
*
* @return void
*/
public function alterColumn($table, $column, $type): void
{
parent::alterColumn($table, $column, $type);
$this->setupForeignKey();
}
/**
* @return int
*/
public function safeDown(): int
{
$this->dropForeignKeyList();
$this->addColumn(self::TABLE_NAME,$this->columnName, $this->getColumnSchema());
return ExitCode::OK;
}
/**
* @return ColumnSchemaBuilder
*/
abstract public function getColumnSchema(): ColumnSchemaBuilder;
} |
|
update migrate
/app/console/migrations/m123456_123456_init.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| <?php
use yii\console\ExitCode;
use console\components\migration\Migration;
/**
*
*/
class m123456_123456_init extends Migration
{
/** @var string */
public const TABLE_NAME = '{{%user}}';
/**
* @return int
*/
public function safeUp(): int
{
$this->createTable(self::TABLE_NAME, [
'id' => $this->primaryKey(),
'status' => $this->smallInteger()->notNull()->defaultValue(10),
'username' => $this->string()->notNull()->unique(),
'email' => $this->string()->notNull()->unique(),
'auth_key' => $this->string(32)->notNull(),
'password_hash' => $this->string()->notNull(),
'password_reset_token' => $this->string()->unique(),
'verification_token' => $this->string()->defaultValue(null),
'created_at' => $this->dateTime()->notNull(),
'updated_at' => $this->dateTime()->notNull(),
]);
return ExitCode::OK;
}
} |
|
Base Elements
Создание обязательных базовых компонентов
Модель.
/app/common/components/models/BaseModel
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
| <?php
namespace common\components\models;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
/**
* Базовый класс моделей
*/
class BaseModel extends ActiveRecord
{
/**
* Поведения
*
* @return array
*/
public function behaviors(): array
{
return [
[
'class' => TimestampBehavior::class,
'value' => date('Y-m-d H:i:s')
]
];
}
/**
* Получение списка ID.
* Опционально передаётся условие
*
* @param mixed $criteria
*
* @return array
*/
public static function getIdList(mixed $criteria = null): array
{
return static::getColumn('id', $criteria);
}
/**
* Получение массива указанной колонки.
* Опционально передаётся условие
*
* @param string $column
* @param mixed|null $criteria
*
* @return array
*/
public static function getColumn(string $column, mixed $criteria = []): array
{
//Запрос
$query = static::find()->select($column)->where($criteria);
// Результат запроса
return $query->column();
}
/**
* Получение `Map` массива из двух значений.
* Для формирования DropDown списка
*
* @param string $key
* @param string $label
* @param mixed|null $criteria
*
* @return array
*/
public static function getMap(string $key, string $label, array $criteria = []): array
{
// Запрос
$query = self::find()->select("$key,$label")->where($criteria);
// Результат запроса
return $query->asArray()->all();
}
} |
|
Ресурсы
/app/common/components/resources/BaseResources
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| <?php
namespace common\components\resources;
/**
* Базовый класс для ресурсов.
* Раздаёт функционал всем ресурсам
*/
class BaseResources
{
/**
* @var string Ключ по которому в шаблоне будет доступен ресурс
*
*
* @example
*
* use frontend\components\resources\UserIndexResource;
*
* var UserIndexResource $R
*
* if ( $R->model->isNewRecord) {
* ...
*/
public const KEY = 'R';
/**
* Получение ключевого массива для передачи его в качестве параметров в шаблон
*
* public function actionView(int $id)
* {
* $R = new UserViewResource();
* $R->project = $this->serviceProject->findByID($id);
*
* return $this->render(UserViewResource::TEMPLATE, $R->release() )
* }
*
* @return BaseResources[]
*/
public function release(array $params = [] ): array
{
return array_merge($params,[ static::KEY => $this ]);
}
} |
|
Сервисы.
/app/common/components/services/BaseService
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| <?php
namespace common\components\services;
use yii\helpers\ArrayHelper;
use common\components\models\BaseModel;
/**
* Базовый класс для сервисов.
* Раздаёт функционал всем сервисам
*/
class BaseService
{
/** @var BaseModel Модель используемая в сервисе */
public const MODEL_CLASS = BaseModel::class;
/**
* Создание модели runtime в памяти/окружении
*
* @param $attr
* @param ?string $className
*
* @return BaseModel
*/
public function createModel($attr, ?string $className = null): BaseModel
{
/** @var BaseModel $model */
$model = new ( $className ?? static::MODEL_CLASS)();
$model->setAttributes($attr);
return $model;
}
/**
* Создание модели в базе данных
*
* @param $attr
* @param string|null $className
*
* @return BaseModel
*/
public function add($attr, ?string $className = null): BaseModel
{
$model = $this->createModel($attr, $className);
$model->save();
return $model;
}
/**
* Получение ID всех существующих моделей
*
* @param array $criteria
*
* @return array
*/
public function getAllId(array $criteria = []): array
{
return (static::MODEL_CLASS)::getIdList($criteria);
}
/**
* получение dropDown писка
*
* @param string $key
* @param string $value
* @param array $criteria
*
* @return array
*/
public function getDropDown(string $key, string $value, array $criteria = []): array
{
$data = (static::MODEL_CLASS)::getMap($key, $value, $criteria);
return ArrayHelper::map($data,$key, $value);
}
} |
|
__________
Console
Удаляю файл `composer.lock`
console
Выполняю в консоли команду: `composer require vlucas/phpdotenv`
| Code | 1
2
3
4
5
6
7
8
9
| composer install
composer update
init
php yii migrate
php yii_test migrate |
|
transfer
переношу файлы(yii.php, yii.bat, yii_test.php ) из директории `app` в корень проекта.
____________________
генерация файлов для работы с моделями
генерация файлов для работы с моделью `User`
для остальных моделей принцип тот же.
Создание директории для сгенерированных моделей ` app/common/models/items`;
Переходим в раздел `gii`, генерируем модель - Table Name: user
- Model Class Name: UserSource
- Namespace: common\models\items
- Base Class: common\components\models\BaseModel
Создание "боевой" common модели:
/app/common/models/items/User.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <?php
namespace common\models\items;
use \common\models\User as CommonUser;
/**
* "Боевая" common модель `User`.
*/
class User extends UserSource
{
/** @var array */
public const STATUS_LIST = [
CommonUser::STATUS_ACTIVE,
CommonUser::STATUS_INACTIVE,
CommonUser::STATUS_DELETED,
];
} |
|
Создание "консольной" формы для модели пользователь:
/app/console/models/forms/UserForm.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| <?php
namespace console\models\forms;
use common\models\items\User;
/**
* Форма пользователя для создания через CLI
*/
class UserForm extends User
{
/**
* {@inheritdoc}
*/
public function rules(): array
{
return [
[['status'], 'integer'],
[['username', 'email', 'auth_key', 'password_hash'], 'required'],
[['created_at', 'updated_at'], 'safe'],
[['username', 'email', 'password_hash'], 'string', 'max' => 255],
[['auth_key'], 'string', 'max' => 32],
[['username', 'email'], 'unique'],
];
}
} |
|
Создание общего сервиса
/app/common/services/UserService.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| <?php
namespace common\services;
use common\models\items\User;
use common\components\services\BaseService;
/**
* Общий сервис для модели `User`
*
* @method User createModel($attr)
* @method User add($attr)
*/
class UserService extends BaseService
{
public const MODEL_CLASS = User::class;
/**
* @return array
*/
public function getUserStatusList(): array
{
return User::STATUS_LIST;
}
} |
|
Создание консольного сервиса
/app/console/services/UserService.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <?php
namespace console\services;
use console\models\forms\UserForm;
/**
* @method UserForm createModel($attr)
* @method UserForm add($attr)
*/
class UserService extends \common\services\UserService
{
/** @var string */
public const MODEL_CLASS = UserForm::class;
} |
|
Создание консольного контроллера
/app/console/controllers/UserController.php
| PHP | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
| <?php
namespace console\controllers;
use Yii;
use yii\base\Exception;
use yii\console\Controller;
use yii\helpers\BaseConsole;
use common\models\User;
use console\services\UserService;
/**
*
*/
class UserController extends Controller
{
/** @var UserService */
private UserService $service;
/**
* @return void
*/
public function init(): void
{
parent::init();
$this->service = new UserService();
}
/**
* @return void
*
* @throws Exception
*/
public function actionAdd(): void
{
$statusList = $this->service->getUserStatusList();
$username = $this->getUsername();
$password = $this->getPassword();
$email = $this->prompt('Email : ');
$status = $this->prompt('Status ('.implode(',',$statusList).') : ');
$this->create($username, $email, $password, (int) $status);
}
/**
* @return void
*
* @throws Exception
*/
public function actionCreateAdmin(): void
{
$username = $this->getUsername();
$password = $this->getPassword();
$this->create($username, "$username@local.dev", $password, User::STATUS_ACTIVE );
}
/**
* @param string $username
* @param string $email
* @param string $password
* @param int $status
*
* @return void
*
* @throws Exception
*/
private function create(string $username, string $email, string $password, int $status): void
{
echo "User `$username` : ";
$userData = [
'username' => $username,
'email' => $email,
'auth_key' => md5(time()),
'status' => $status,
'password_hash' => Yii::$app->security->generatePasswordHash($password),
];
$user = $this->service->createModel($userData);
$user->save();
if ( $user->hasErrors() )
{
echo $this->ansiFormat('created error:', BaseConsole::FG_RED);
print_r($user->errors);
die;
} else {
echo $this->ansiFormat('created success', BaseConsole::FG_GREEN);
}
}
/**
* @return string
*/
private function getUsername(): string
{
return $this->prompt('username : ');
}
/**
* @return string
*/
private function getPassword(): string
{
return $this->prompt('password : ');
}
/**
* Для устранения notice: Unused element: 'actionName'
*
* @throws Exception
*/
public function __actions()
{
$this->actionAdd();
$this->actionCreateAdmin();
}
} |
|
Создание вспомогательного файла ` __autocomplete.php`
/app/console/config/__autocomplete.php
| PHP | 1
2
3
4
5
6
7
8
9
10
| <?php
use console\controllers\UserController;
/**
* Устранение notice: Unused element: 'NameController'
*/
$controllerList = [
UserController::class
]; |
|
console
| Code | 1
2
3
| php yii user/create-admin
username : admin
password : 123123123 |
|
|