实现多租户应用程序(结构)

时间:2017-03-03 10:48:00

标签: model-view-controller routing yii2 directory-structure yii2-module

(这个问题不是关于数据库。我知道数据库通常被认为是多租户。但这不是我的问题。)

我创建了一个将由不同客户使用的应用程序。他们可以看到并做大部分相同的事情。但是,有些客户在这里和那里有一些额外的按钮,一些功能被禁用或其他不同的东西。

我想避免使用大量的if / else或switch语句。所以我想我可以为每个客户提供一个通用模块和特殊模块,根据需要覆盖或覆盖不同的东西。查看以下理论结构(所有文件都是正常的Yii文件):

app
    general
        controllers
            OrderController
            InvoiceController
            ShippingController
        views
            order
                index, view, update, create, _form
            invoice
                index, view, update, create, _form
            shipping
                index, view, update, create, _form
            layout
                main
        models
            Order
            Invoice
            Shipping
    customerA
        controllers
            OrderController  // some action is different
    customerB
        views
            invoice
                view         // some buttons should be overridden
            layout
                main.php     // other page structure
    customerC
        views
            order
                index        // table gets some additional columns
        model
            Order            // has some more properties
    customerD
        // this customer exists but has nothing that must be changed
        // it uses all what is in general
    ...
web
common
console
...

我认为这是一个健全的文件结构。至少它是清楚易懂的。现在我想以某种方式实现:如果客户请求任何内容,应用程序将首先查看是否存在特定客户的文件并使用它们,或者使用通用模块中的文件(后备)。我的问题是:我该怎么做?

如果有可能,怎么样?或者只是部分可能,例如只有控制器和视图?我想视图/控制器/模型文件可能需要不同的方法。我想可以调整类自动加载。我会考虑使用路由(虽然客户必须经过身份验证,因此它只能使用他或她自己的客户):

http://example.com/customerA/invoice/view?id=1234

这一切都可以通过配置或依赖注入来完成吗?我是否需要模块或文件组织是否足够?

(思考:覆盖控制器可能很简单。但我认为只有在控制器被覆盖以设置另一个视图路径时才能覆盖视图文件。)

有没有人有想法解决这个问题?如果这适用于控制器和视图,我会很高兴。但模型也不错。或者有没有其他建议或替代方法?即使您只知道部分解决方案,也请告诉我。

我认为一个令人满意的答案可能随着时间的推移而演变。但是找到一个好的解决方案对其他人有帮助。那么让我们来研究一下;-) ......或者是另一个更适合这项任务的框架? : - (

1 个答案:

答案 0 :(得分:0)

您可以按照以下代码使用单独的主题:

  1. 覆盖yii \ base \ Theme
  2. 使用依赖性约束来使用您的自定义 主题组件
  3. 制作一个空的配置条目来制作您的主题 组件被称为
  4. 创建/复制自定义主题文件
  5. read this for theming instructions

    read this for dependency injection instructions(或如何替换其他模型)

    此示例显示如何将“@app/views”替换为“@app/themes/mytheme”。

      

    common \ components \ Theme.php (自定义主题组件)

    namespace common\components;
    use Yii;
    
    class Theme extends \yii\base\Theme 
    {
    
        public function init() {
            // todo: your logic goes here
            $this->pathMap = [
                '@app/views' => [
                    '@app/themes/mytheme',
                ]
            ];
    
            return parent::init();
        }
    
    }
    
      

    common \ extensions \ Bootstrap.php (DI的自定义引导程序)

    namespace common\extensions;
    
    use Yii;
    use yii\base\Application;
    use yii\base\BootstrapInterface;
    use yii\helpers\Url;
    
    class Bootstrap implements BootstrapInterface
    {
        public function bootstrap($app)
        {
            Yii::$container->set(\yii\base\Theme::className(), \common\components\Theme::className());
        }
    }
    
      

    common \ config \ main.php (注册自定义引导程序)

    'bootstrap' => [
        'common\extensions\Bootstrap',
    ],
    
      

    frontend \ config \ main.php (注册虚拟主题配置)

    'components' => [
        'view' => [
            'theme' => [
                'basePath' => '@app/views',
            ],
        ],
    ],