Laravel — логика выполнения в config/database.php

#database #laravel #config

#База данных #laravel #конфигурация

Вопрос:

Как вы все знаете, в Laravel config/database.php есть куча arrays и values . Но для определенного условия мне нужно выполнить некоторую логику, и мне удается выполнить простую логику, config/database.php и она работает так, как я хочу (могу сослаться на приведенный ниже код), но мне интересно, хорошо ли это / практично делать так?

Если это непрактично, можете ли вы предложить другой способ получить тот же результат, что и ниже?

 'connections' => [

    'mysql' => (function(){ 
        $config = [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'live_db'),
            'username' => env('DB_USERNAME', 'myuser'),
            'password' => env('DB_PASSWORD', '2309423234'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => 'gn_',
            //'prefix_indexes' => true,
            'strict' => false,
            'engine' => env('DB_ENGINE', null),
        ]; 

        // do some logic here (and it's working!!)
        // but........
        // is it okay to do like this?
        if(env('DB_WITH_SSLMODE', false)){
            $config  = [
                'sslmode' => env('DB_SSLMODE', 'prefer'),
                'options'   => [
                    PDO::MYSQL_ATTR_SSL_CA    => env('DB_OPT_MYSQL_ATTR_SSL_CA', 'C:wamp64bincloudsqlcertificatesserver-ca.pem'),
                    PDO::MYSQL_ATTR_SSL_CERT    => env('DB_OPT_MYSQL_ATTR_SSL_CERT', 'C:wamp64bincloudsqlcertificatesclient-cert.pem'),
                    PDO::MYSQL_ATTR_SSL_KEY    => env('DB_OPT_MYSQL_ATTR_SSL_KEY', 'C:wamp64bincloudsqlcertificatesclient-key.pem'),
                    PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
                ],
            ];
        }

        return $config;
    })(),

],
 

Ответ №1:

Как насчет использования троичного оператора? (почти так же, как это делается по умолчанию в laravel 5.8).

Примечание: Первое решение не удаляет sslmode из массива конфигурации. Если вам нужно это сделать, просто выберите второй вариант!

1) Это должно работать следующим образом:

 'connections' => [
    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => null,
        'sslmode' => env('DB_WITH_SSLMODE') ? env('DB_SSLMODE','prefer') : null,
        'options' => (extension_loaded('pdo_mysql') amp;amp; env('DB_WITH_SSLMODE')) ? [
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'),
            PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'),
            PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
        ] : [],
    ],
],
 

или

2) грязное решение, но с одним условным:

 'connections' => [
    'mysql' => array_merge([
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'prefix_indexes' => true,
        'strict' => true,
        'engine' => null
    ], (extension_loaded('pdo_mysql') amp;amp; env('DB_WITH_SSLMODE')) ? [
        'sslmode' => env('DB_SSLMODE', 'prefer'),
        'options' => [
            PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            PDO::MYSQL_ATTR_SSL_CERT => env('MYSQL_ATTR_SSL_CERT'),
            PDO::MYSQL_ATTR_SSL_KEY => env('MYSQL_ATTR_SSL_KEY'),
            PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
        ]
    ] : [ 'options' => [] ]),
],
 

Затем переместите значения по умолчанию, которые у вас были в env(), в ваш файл .env (обратите внимание, что я удалил префикс DB_OPT_):

 DB_WITH_SSLMODE=true
MYSQL_ATTR_SSL_CA=C:wamp64bincloudsqlcertificatesserver-ca.pem
MYSQL_ATTR_SSL_CERT=C:wamp64bincloudsqlcertificatesclient-cert.pem
MYSQL_ATTR_SSL_KEY=C:wamp64bincloudsqlcertificatesclient-key.pem
MYSQL_ATTR_SSL_VERIFY_SERVER_CERT=false
 

Поэтому, если вы установите DB_WITH_SSLMODE в значение false, будет возвращен пустой массив, и ssl не будет включен.

Примечание: я думаю, что указанный вами sslmode необходим только для соединений PostgreSQL, что не в вашем случае.

Комментарии:

1. о чем 'sslmode' => env('DB_SSLMODE', 'prefer'), это?? куда его поместить?

2. Прочитайте примечание внизу ответа: оно должно быть необходимо только для соединений PostgreSQL. Если вы попробуете эту конфигурацию, она должна работать в любом случае

3. на самом деле мне это нужно … на моем живом сервере, если я удалю sslmode , появится сообщение об ошибке …. поэтому мне нужно sslmode ..

4. в моем live server мне нужно включить SSL … но на моем локальном хостинге мне нужно отключить SSL … поверьте мне, первое решение не работает… я уже пытался… если я хочу отключить SSL, я должен удалить sslmode свойство … если я не удалю его, и если я просто сделаю его пустым значением (например 'sslmode'=>'' ), это вызовет ошибку .. но, тем не менее, грязное (2-е) решение работает… спасибо, что поделились …. я поддержал ваш ответ..

5. Хорошо, позже я подумал, что вам нужно полностью удалить решение. если это так, то второе решение — это правильный путь.

Ответ №2:

Для этого вы можете создать поставщика услуг:

 class SSLServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(Kernel $kernel)
    {

    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $config = Config::get('database.connections.mysql');

        if (env('DB_WITH_SSLMODE', false)) {
            $config  = [
                'sslmode' => env('DB_SSLMODE', 'prefer'),
                'options' => [
                    PDO::MYSQL_ATTR_SSL_CA => env('DB_OPT_MYSQL_ATTR_SSL_CA',
                        'C:wamp64bincloudsqlcertificatesserver-ca.pem'),
                    PDO::MYSQL_ATTR_SSL_CERT => env('DB_OPT_MYSQL_ATTR_SSL_CERT',
                        'C:wamp64bincloudsqlcertificatesclient-cert.pem'),
                    PDO::MYSQL_ATTR_SSL_KEY => env('DB_OPT_MYSQL_ATTR_SSL_KEY',
                        'C:wamp64bincloudsqlcertificatesclient-key.pem'),
                    PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
                ],
            ];
        }

        Config::set('database.connections.mysql', $config);

    }

}
 

и не забудьте зарегистрировать своего поставщика услуг в config/app.php

 AppProvidersSSLServiceProvider::class,
 

Комментарии:

1. новые знания для меня… спасибо … я уверен, что это работает, но я все еще чувствую, что этот ответ не practical….so я не могу отметить ваш ответ… но я поддерживаю этот ответ …. спасибо, что поделились этим…

2. Не используйте никаких вызовов env(), кроме как в файлах конфигурации, потому что, если вы включите кеширование конфигурации ( php artisan optimize/php artisan config:cache ), любой вызов env за пределами папки конфигурации вернет пустое значение.

3. @mdexp ,,, да, это делает sense…it означает , что этот ответ не подходит, если мы используем config:cache … верно?

4. Верно, это также указано в документации

Ответ №3:

На самом деле вы также можете сделать что-то столь же простое, как:

 $database = [
    'connections' => [
        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'live_db'),
            'username' => env('DB_USERNAME', 'myuser'),
            'password' => env('DB_PASSWORD', '2309423234'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => 'gn_',
            //'prefix_indexes' => true,
            'strict' => false,
            'engine' => env('DB_ENGINE', null),
        ]
    ]
];

if(env('DB_WITH_SSLMODE', false)){
    $database['connections']['mysql']  = [
        'sslmode' => env('DB_SSLMODE', 'prefer'),
        'options'   => [
            PDO::MYSQL_ATTR_SSL_CA    => env('DB_OPT_MYSQL_ATTR_SSL_CA', 'C:wamp64bincloudsqlcertificatesserver-ca.pem'),
            PDO::MYSQL_ATTR_SSL_CERT    => env('DB_OPT_MYSQL_ATTR_SSL_CERT', 'C:wamp64bincloudsqlcertificatesclient-cert.pem'),
            PDO::MYSQL_ATTR_SSL_KEY    => env('DB_OPT_MYSQL_ATTR_SSL_KEY', 'C:wamp64bincloudsqlcertificatesclient-key.pem'),
            PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => env('DB_OPT_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', false)
        ]
    ];
}

return $database;