Yii2根据存储在DB中的信息生成路径别名


Yii2 make a path alias from information stored in DB

现在我正在尝试为我的基于Yii2的项目实现主题化。我现在的看法:

  1. 用户从设置列表中选择应用程序主题页面
  2. 使用yii2设置,我将保存所有数据库中的配置数据(非常简单)
  3. 在应用程序中bootstrap.php我正在创建一个名为@theme的新别名。基本上应该引导我们找到应用程序主题的基本路径(用于搜索path、资产管理器等)
  4. 据官方消息文档,这就是我配置视图组件的方式:

    'view' => [
        'theme' => [
            'basePath' => '@theme',
            'baseUrl' => '@theme',
            'pathMap' => [
                '@app/views' => '@theme',
                '@app/widgets' => '@theme/widgets',
                '@app/modules' => '@theme/modules',
            ],
        ],
    ],
    

我的一个问题是第三页。根据yii2设置文档,我应该这样阅读设置:

$theme = Yii::$app->settings->get('name', 'general');
Yii::setAlias('@theme', realpath(dirname(__FILE__)."/../../themes/$theme"));

但很明显,它对我来说不起作用,因为在调用bootstrap.php时yii2设置组件还没有初始化。我一直试图稍后在我的基本控制器的init()方法中初始化它,然后手动调整其他别名,但我觉得这种方式有点"不干净",而且它仍然失败,因为在调用控制器的init方法之前,在Yii2开始发布的资产文件中也使用了@theme别名。

那么,有人想过如何尽可能少地对代码进行"黑客攻击"吗?我知道我可以将配置移到某个文件中,然后在应用程序初始化之前手动读取它,但这仍然不是我想要的方式。也许有某种方法可以在加载db组件之后,但在查看组件配置之前,覆盖某些系统组件来设置别名?或者Yii以不同的顺序加载这些组件?无论如何任何帮助都将不胜感激!

您可以在bootstrap:中尝试Application Event

'Yii::$app->on('yii'base'Application::EVENT_BEFORE_REQUEST, function ($event) {
    $theme = Yii::$app->settings->get('name', 'general');
    Yii::setAlias('@theme', realpath(dirname(__FILE__)."/../../themes/$theme"));
});

配置文件中的OR:

[
    'on beforeRequest' => function ($event) {
        // ...
    },
]

来自Yii 2文档:

EVENT_BEFORE_REQUEST此事件在应用程序之前触发处理请求。实际事件名称为beforeRequest。

触发此事件时,应用程序实例已已配置并初始化。所以这是一个插入您的通过事件机制截取请求处理的自定义代码过程例如,在事件处理程序中,可以动态设置yii''base''Application::$language属性。

以下是最终解决方案:

config/bootstrap.hp:

// Setting a temporary path for components configuration - will be changed later
Yii::setAlias('@theme', realpath(dirname(__FILE__)."/../../themes/"));

config/main.php

'components' => [
        'view' => [
            'theme' => [
                'basePath' => '@theme',
                'baseUrl' => '@theme',
                'pathMap' => [
                    '@app/views' => '@theme',
                    '@app/widgets' => '@theme/widgets',
                    '@app/modules' => '@theme/modules',
                ],
            ],
        ],
],
'on beforeRequest' => function ($event) {
        $theme = Yii::$app->settings->get('theme', 'general');
        Yii::setAlias('@theme', realpath(dirname(__FILE__)."/../../themes/$theme"));
},