Передать параметр в component 'userDB'

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Передать параметр в component 'userDB'

Сообщение terrarium volition »

Всем доброго дня!

Делаю подключение к БД при помощи анонимной функции в components:

Код: Выделить всё

'components' => [
        ...
        ,
        'userDb' => function () {
            if ($user = Yii::$app->get('user', false)) {
                $username   = Yii::$app->user->identity->username;
            } else {
                $username = 'GuestDB';
            }
 
Переопределяю метод getDB() :

Код: Выделить всё

public static function getDb()
    {
        return Yii::$app->userDb;
    }
Как мне передать значение $unitID в userDB?
Это нужно, чтобы сформировать полное имя DB для подключения.

Код: Выделить всё

return Yii::createObject([
                'class' => 'yii\db\Connection',
                'dsn' => 'mysql:host=localhost;dbname=' . $username,// . $unitID,
                'username' => 'root',
                'password' => '123',
                'charset' => 'utf8',
            ]);
Если делаю так:

Код: Выделить всё

public static function getDb()
    {
	$unitID = 'TestID';
        return Yii::$app->userDb($unitID);
    }
то ругается :
Calling unknown method: yii\web\Application::userDb()
Если пытаются получить $unitID в самом теле components:

Код: Выделить всё

use frontend\models\Unit;

return [
    'components' => [
	...
	,
        'userDb' => function () {
            if ($user = Yii::$app->get('user', false)) {
                $username   = Yii::$app->user->identity->username;
                $unit = Unit::find()->select('id')->one();
                $unitID = $unit['id'];
            } else {
                $username = 'GuestDB';
                $unitID = '0';
            }
то получаю, что components вообще не инициализируется.
Undefined property: yii\web\Application::$userDb
Подскажите, пожалуйста, как правильно реализовать выборку параметра $unitID?
Спасибо.
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Передать параметр в component 'userDB'

Сообщение SiZE »

Это как минимум

Yii::$app->userDb->...
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

SiZE писал(а): 2022.05.16, 11:12 Это как минимум

Yii::$app->userDb->...
Делаю так:

Код: Выделить всё

$user = Yii::$app->user->identity->username;
$unitID = parent::find()->select('id')->where(['username' => $user])->one();
$id = $unitID->id;

return Yii::$app->userDb->id = $id;
Приминаю $id, как взодной параметр:

Код: Выделить всё

'userDb' => function ($unitId) {
...
}
В ответ сообщение, что сервер всю память съел:
PHP Fatal Error – yii\base\ErrorException
Allowed memory size of 1073741824 bytes exhausted (tried to allocate 20480 bytes)
Чего ему нужно, подскажите, пожалуйста?
На ровном месте застрял, выручайте, товарищи. :roll:
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

SiZE писал(а): 2022.05.16, 11:12 Это как минимум

Yii::$app->userDb->...
Пожалуйста, помогите разобраться, уважаемые спецы :(
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Передать параметр в component 'userDB'

Сообщение SiZE »

Код: Выделить всё

// Определяете компонент
'userDb' => [
    'class' => 'yii\db\Connection',
    'dsn' => '',
    'username' => null,
    'password' => null,
    'charset' => 'utf8mb4',
],
// Подписываетесь на событие авторизации, например так
'user' => [
    'on afterLogin' => [ChangeUserDbConnection::class, 'handle']
]

Код: Выделить всё

final class ChangeUserDbConnection
{
    public static function handle($event)
    {
        \Yii::$app->userDb->dsn = 'mysql:host=127.0.0.1;dbname=demo';
        \Yii::$app->userDb->username = 'root';
        \Yii::$app->userDb->password = 'qwe';
    }
}
Последний раз редактировалось SiZE 2022.05.18, 13:43, всего редактировалось 1 раз.
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

SiZE писал(а): 2022.05.18, 10:00

Код: Выделить всё

final class ChangeUserDbConnection
{
    public static function handle($event)
    {
        \Yii::$app->userDb->dsn = 'mysql:host=127.0.0.1;dbname=demo';
        \Yii::$app->userDb->username = 'root';
        \Yii::$app->userDb->password = 'qwe';
    }
}
Я получаюсь нуб здесь полный. С компонентами особо не работал.
Уточните, пожалуйста, где этот класс инициализировать нужно?
Я фрагмент Вашего кода вставил в уже существующий класс Unit, но меня обругали:
yii\base\ErrorException: call_user_func() expects parameter 1 to be a valid callback, class 'Unit' not found in C:\...\...\...\vendor\yiisoft\yii2\base\Component.php:628
:?

Мне нужно унаследоваться от Component и реализовать свой класс с методом handle ?
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

А я как раз из Вашей статьи и взял основу.
С ходу не зашло про инициализацию параметров в getDB.
Ушёл читать вдумчиво.
Там, конечно, лютый велосипед, голова разболелась поначалу :roll:
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

С Вашего позволения забрал себе UserDBLocator, поменял лишь getActiveId():

Код: Выделить всё

private function getfullDBid()
    {
        if ($this->fullDBid === null) {
            $user = Yii::$app->get('user', false);
            if ($user && !$user->getIsGuest()) {
                $userid = $user->getId();
            } else {
                $userId = $this->defaultId;
            }

            $du = Unit::find()->select('id')->where(['username' => \Yii::$app->user->identity->username])->andWhere(['active' => '1'])->one();
            $this->fullDBid = $userid . '_' . $du->id;
        }
        
        return $this->fullDBid;
    }
В итоге, меня опять обругали:
PHP Fatal Error – yii\base\ErrorException
Allowed memory size of 1073741824 bytes exhausted (tried to allocate 20480 bytes)

В ...\vendor\yiisoft\yii2\base\Event.php:
...
$class = get_class($class);
} else {
$class = ltrim($class, '\\');
}

$classes = array_merge(
[$class],
class_parents($class, true),
class_implements($class, true) - Здесь ругается
);

foreach ($classes as $class) {
$eventHandlers = [];
foreach ($wildcardEventHandlers as $classWildcard => $handlers) {
if (StringHelper::matchWildcard($classWildcard, $class, ['escape' => false])) {
$eventHandlers = array_merge($eventHandlers, $handlers);
unset($wildcardEventHandlers[$classWildcard]);
}
Будь проклят тот день, когда я сел за баранку этого пылесоса!
Чего этому силиконовому чуду надо?! :cry:
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

terrarium volition писал(а): 2022.05.18, 23:30 private function getfullDBid()
...
$du = Unit::find()->select('id')->where(['username' => \Yii::$app->user->identity->username])->andWhere(['active' => '1'])->one();
...
[/code]
Вот это место валит работу. Но почему??
Почему я не могу выбрать из таблицы, работая из класса Component? :shock:

Подскажите, пожалуйста, как можно получить данные из БД, работая в классе Component?
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

terrarium volition писал(а): 2022.05.19, 16:07
terrarium volition писал(а): 2022.05.18, 23:30 private function getfullDBid()
...
$du = Unit::find()->select('id')->where(['username' => \Yii::$app->user->identity->username])->andWhere(['active' => '1'])->one();
...
[/code]
Вот это место валит работу. Но почему??
Почему я не могу выбрать из таблицы, работая из класса Component? :shock:

Подскажите, пожалуйста, как можно получить данные из БД, работая в классе Component?
Cделал передачу $fullDBId через Session.

Но вопрос актуален, уважаемые гуру прошу пояснить, что ограничивает работу с БД в классе Сomponent? :|
terrarium volition
Сообщения: 99
Зарегистрирован: 2021.07.15, 21:22

Re: Передать параметр в component 'userDB'

Сообщение terrarium volition »

Так. Теперь непонятно, как использовать getTableSchema при работе с Yii::$app->userDbLocator.

Yii::$app->userDbLocator->getTableSchema, понятное дело, не работает.
Yii::$app->userDbLocator->connection->getTableSchema тоже не работает.

Подскажите, пожалуйста, как мне достучаться до метода через локатор?
Ткните носом, где про это можно почитать, а то достал уже и себя и вас своими вопросами? :(
Ответить