Форум программистов, компьютерный форум, киберфорум
and_y87
Войти
Регистрация
Восстановить пароль
Оценить эту запись

Yii2 мой flow на старте разработки.

Запись от and_y87 размещена 03.07.2023 в 20:42
Обновил(-а) and_y87 15.08.2023 в 00:54
Метки yii2

Мне памятка, для себя, что бы не забыть, что за чем делаю)

получается классная структура проекта в итоге

database
Заранее создать 2 базы данных:
  • local_ ...
  • test_ ...

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

Код:
# === 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

Код:
# 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
    Код:
    {
      "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`

Код:
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
Код:
php yii user/create-admin
username :  admin
password :  123123123
Миниатюры
Нажмите на изображение для увеличения
Название: yii2_structure.jpg
Просмотров: 160
Размер:	409.0 Кб
ID:	8143  
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru