0

(这个问题是不是数据库。我知道数据库通常认为,当涉及到多租户,但是这不是我的问题。)实现多租户应用(结构)

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

我想避免大量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 

可这一切都可以用配置或依赖注入做了什么?我需要模块还是文件组织足够?

(思考:重写控制器可以是简单的,但我认为这种观点文件只能在控制器被重写,以设置另一种看法路径被覆盖。)

没有人有想法解决这个?我会很高兴,如果这与控制器和意见。但模型也会很好。还是有人有其他建议或替代方法?即使您只知道部分解决方案,也请告诉我。

我假设一个令人满意的答案可能随着时间而变化。但是,其他人找到一个好的解决方案会很有帮助。所以我们来研究一下;-)或者是另一个更适合这个任务的框架? :-(

回答

0

你可以通过这样的代码使用单独的主题:

  1. 覆盖警予\基地\主题
  2. 使用依赖injenction使用您的自定义 主题分量
  3. 创建一个空的配置项让你的主题 组件被调用
  4. 制作/复制您的自定义主题文件

read this for theming instructions

read this for dependency injection instructions(或如何更换其他型号)

这个例子展示了如何通过 '@app/themes/mytheme' 替换 '@app/views'。

共同\组件\ 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(); 
    } 

} 

共同\扩展\ 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()); 
    } 
} 

共同\设置\ main.php(注册自定义自举)

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

前端\设置\ main.php(寄存器虚设主题配置)

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