(This question is not about databases. I know databases are often regarded when it comes to multi-tenancy. But this is not my question.)
I create an application that will be used by different customers. They can see and do mostly the same things. However, some customers have some extra buttons here and there, some functions are disabled or something else is different.
I want to avoid lots of if/else or switch statements. So I thought I could have a general module and special modules for each customer that override or overwrite different things as needed. Look at the following theoretical structure (all files are the normal Yii files):
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
...
I think this is a sound file structure. At least it is clear and comprehensible. Now I'd like to realize somehow: if a customer requests anything the application will look first if there are files for the specific customer and uses them, or uses the files in the general modul (fallback). My question is: how can I do that?
If it is possible, how? Or is it only partially possible, e.g. only with controllers and views? I suppose different approaches might be needed for view/controller/model files. I suppose that class autoloading could be adapted. And I would think to utilize routing (though the customer must be authenticated, so it can use only his or her own customer):
http://example.com/customerA/invoice/view?id=1234
Can all this be done with the configuration or with dependency injection? Do I need modules or is the file organization sufficient?
(Thoughts: Overriding controllers could be simple. But I think that view files can be overriden only if the controller gets overridden to set another view path.)
Does anyone have ideas to solve this? I would be glad if this works with controllers and views. But models would be also nice. Or does anyone have other suggestions or alternative approaches? Let me know even if you only know parts of the solution.
I assume a satisfying answer may evolves with the time. But it would be helpful for others to find a good solution. So let's work on that ;-) ... Or is another framework more suitable for this task? :-(