How to implement a deployment-specific pluggable architecture in a single code base - symfony

I know this is somewhat subjective, but Symfony being as it is there must be a feature specifically designed for this purpose.
Here are the main factors of what I need to do:
The system will be deployed separately for multiple customers (probably just a handful. scale isn't a big concern).
Each deployment has a small amount of highly bespoke functionality specific to the customer. This could be anything.
I want to maintain a single, common codebase (including composer.json). The only file I really want outside of our repo is parameters.yml.
My current thinking involves a custom bundle for every customer - hooking into them using custom Symfony events, fired from the common parts of the system. But ...
Symfony bundles aren't designed to be dynamically registered. They're baked into our core system so I can't switch them on and off for individual customers without forking/splitting the codebase. This means not only a bloated Kernel, but also events would be received by all bundles in all deployments.
I can get around that last point by namespacing the events with a configuration parameter. Even if I can live with redundant bundles in the Kernel, this whole approach seems too hard to be correct.
What is the proper way to support a "pluggable" architecture than I can hook into from the core system without splitting my codebase?

I use multiple app-directories. Then you can turn on/off bundles for each client since each client has it's own AppKernel.php and then you can create a separate /web/app.php for each client and point it to the currect app-directory.
You can then use mod-rewrite in Apache to point each client's subdomain or something to the right app.php file

Related

Is possible to mix Symfony2 CMF and the standard distribution?

We're planning a new intranet for our organization. Some part is like a CMS, and there are some custom-made applications.
The Symfony2 CMF distribution looks fine for building the CMS part of the intranet, but other parts like Doctrine, "normal" SQL databases, etc, looks better for the custom-made applications for the intranet.
Because I need common authorization and authentication system for this intranet (against an Active Directory), I supose that I'll get better results building all in only on app. So, can I mix a CMF application with a normal application, and both use the same database (an Oracle DB)?
Yes you can easily mix the CMF with other Bundles. For example the routing allows using both routes from the CMF as well as "static" routes defined in yml files. Also you can easily also add the ORM next to PHPCR ODM. If you use Doctrine DBAL for storage in PHPCR, you can even reuse the same connection configuration with the ORM etc.
In brief yes it is, and I do this in my own Symfony2 project. I combine both SF-SE and SF-CMF bundles.
In fact, with Symfony2 it's very simple (this is just a matter of choosing the most suitable Bundles; SF is a very decoupled framework, which is why I don't plan to migrate to any other solution for the moment), but I'd like to share some of my experience with doing that. Actually the one most important question to think through to make a decision about how to combine both "worlds" is this:
Composer.
After some inquries I found out that since Symfony CMF is (in a way) based on Symfony SE, and not vice versa, it's better to start with the latter, as it contains the most core features (though I did it also in the opposite way, rather not recommended). So just take a SF-SE's composer.json, take a look at bundles from there you need, and then take a look at differences within SF-CMF's composer.json. You should end up with the most suitable set of bundles.
The basic features from these bundles to look-up for are:
MODEL - Doctrine ORM, PHPCR-ODM, or both - if still not sure, don't hesitate to ask a comment, I'll share here my experience furthere.
ROUTING - the primary question here is how flexible routing do you actually need? If not sure, I'd go with standard SF Router, and then possibly replace it e.g. when still on a dev stage.
OUT-OF-THE-BOX CMS FUNCTIONALITY - bundles such as CreateBundle, MenuBundle or MediaBundle may help you building surprisingly fast, but not quite flexible soltions. In general, I ended up without using most of them, and if using, then I mainly take some Interfaces I do implement in my own Bundles (to ensure future compatibility with possible other bundles to be potentially used).
Besides of these above, I created a number of Bridge Design Pattern and Provider Design Pattern solutions to make some bundles working together, to adjust their functionalities, or simply to decouple things.
In programming almost everything is possible. But think about restrictions delivered with CMF (routing for eg.).
Maybe you should consider Standard Symfony with Sonata? I think CMS pages it's only small part of your system and implementation it in standard symfony will take smallest part (and cost) of whole project.

Symfony2 : implement multiple projects sharing same logics

I've read a lot on this topic, but cannot find out a clear answer on how to structure a complex project around symfony2...
My new project will be structured with :
1) one back office website hosted on a subdomain of our partner's website
2) one partner's website
3) one (or more) customer's website
Of course, each of these websites will share logics from "core" bundles (i.e : core entities, core user logic, etc...), but they also need to have custom routing, custom templates, and so on...
I think that I have 2 options :
1) define 1 bundle per website and define routing based on the hostname, but it seems that it is not recommended
2) implement one SF2 instance by website, and copy/deploy core bundles into each instances
What is the best solution ? And is there another solution on how to implement some kind of complex project?
It's difficult to say which is best for your particular situation: I've used both approaches for projects. I actually have one project which uses both approaches simultaneously, consisting of two Symfony applications: One generating the main website, the other generating a separate application containing some other functionality, with separate bundles for the "user" functionality and the "admin" functionality. We used Varnish to dispatch requests to the correct application, based on the URL path.
In my experience I've found that having multiple applications adds a degree of complexity to the overall solution. This makes it more complicated to work with and to hold the "big picture" of the whole system in your head. There's also potentially a cost implication, if you want to run your applications on separate servers. You also need to consider that there's overhead on getting the whole solution set up for local development, which is definitely a concern if you're in a team of more than one.
The flip-side of this is that working on one part of the whole solution (i.e. one app) is often more straightforward: Configuration values/dependencies for the other applications won't need to be set up, you only need to get working the bare minimum for that one standalone app. This approach also affords you a lot of flexibility and the ability to concentrate changes on one particular area of the solution. For example: If you wanted to make some changes to the partner's website, if that was generated by a completely separate application, it becomes straightforward to do this. You know that there won't be knock-on effects to your other applications. This goes for shared code too, providing you version it correctly: With composer, your separate applications can depend on different versions of your shared bundles/libraries if necessary. Another benefit of having separate applications is the ability to scale them independently of each other. If your customer website gets much more traffic than your partner's site, you can set it up on better hardware/virtualised instances, giving you finer grained control over performance/costs.
Sharing code is relatively straightforward with Composer and is not one of the main concerns here, in my opinion: Think carefully about the above factors when making your decision.

An exact description of a Symfony Bundle in a complex web application

I'm new to version 2 of the Symfony framework. I made some projects with v1 but now trying to get my head around the new version and it's features.
I read over the concept of Bundles but it's purpose is not yet very clear to me.
Say you have a big web application, a CRM for example. How would the bundles look like?
Would it be NewsletterBundle (for sending newsletters), ContactManagementBundle (for managing contacts), UserBundle (for editing users and their permissions).
Or would it be less cut-up like, EmailBundle (for handling the entire email traffic), CRMBundle (for putting in all your CRM code), PermissionsBundle, ApiBundle.
I like to think of it like this: a bundle should represent a specific feature or set of like features for a project.
Your first example is a better use of bundles than your second example, because the purpose of each bundle is more defined. While it's possible to use one CRMBundle for everything, you wouldn't really be taking advantage of Symfony's ability to organize your code. Additionally, if you wanted to port over your Newsletter code to a new project, but not all of the CRM code, you'd have an easier time copying over a NewsletterBundle versus copying over the CRMBundle, and then pruning it.
When thinking about a Symfony2 project, sometimes you want to forget everything you know about symfony 1.x, since they take wildly different approaches to solving many problems. For example, in symfony 1 it was common to build a 'frontend' and 'backend' app for a project, and each app would obviously contain logic specific to those parts of the project. So you might have a Newsletter controller in both the frontend and backend apps. In Symfony2, you're better off using only one Newsletter bundle, but with two controllers (perhaps named 'frontend' and 'backend'). Again, an immediate benefit to this is how reusable your code becomes.

How to make two web sites appear as one - What features are important?

I am about to write a tender. The solution might be a PHP based CMS. Later I might want to integrate an ASP.NET framework and make it look like one site.
What features would make this relatively easy.
Would OpenId and similar make a difference?
In the PHP world Joomla is supposed to be more integrative than Druapal. What are the important differences here?
Are there spesific frameworks in ASP.NET, Python or Ruby that are more open to integration than others?
The most important thing is going to be putting as much of the look-and-feel in a format that can be shared by any platforms. That means you should develop a standard set of CSS files and (X)HTML files which can be imported (or directly presented) in any of those platform options. Think about it as writing a dynamic library that can be loaded by different programs.
Using OpenID for authentication, if all of your platform options support it, would be nice, but remember that each platform is going to require additional user metadata be stored for each user (preferences, last login, permissions/roles, etc) which you'll still have to wrangle between them. OpenID only solves the authentication problem, not the authorization or preferences problems.
Lastly, since there are so many options, I would stick to cross-platform solutions. That will leave you the most options going forward. There's no compelling advantage IMHO to using ASP.NET if there's a chance you may one day integrate with other systems or move to another system.
I think that most important thing is to choose the right server. The server needs to have adequate modules. Apache would be good choice as it supports all that you want, including mod_aspnet (which I didn't test, but many people say it works).
If you think asp.net integration is certanly going to come, I would choose Windows as OS as it will certanly be easier.
You could also install reverse proxy that would decide which server to render content based on request - if user request aspx page, proxy will connect to the IIS and windoze page, if it asks for php it can connect to other server. The problem with this approach is shared memory & state, which could be solved with carefull design to support this - like shared database holding all state information and model data....
OpenID doesn't make a difference - there are libs for any framework you choose.

How do you deploy and manage a C# web application to a customer with some minor differences from your base project?

I have a semi-large web application that we run locally and I need to deploy it at another location. The second location will require some slight modifications to the project (especially cosmetic). How do you manage these differences and what do you use to distribute the site and updates to a customer like this?
Edit:
Right now our web app runs in-house and we build with Cruise Control .NET and MSBuild with WDP. What would be a good option for deployment to the customer? We will not be updating their site for them so a solution that is simple for them to deploy and update is desirable.
Branch your code.
Hopefully your code is source controlled (if not, start now!), you should branch from the base to the "Customer X" branch and just make the slight cosmetic modifications in that branch. Then just build and deploy off of that branch for that customer.
Additionally, if the changes are minor enough, you could try to make the changes configurable. That way you could deploy the same site everywhere, and just change the configuration to match what the customer wants. The more complex the differences, the harder it will be to make them configurable though.
After reviewing comments: Its good to note that configuration is practical, but ONLY if the # of changes are minor, otherwise you will pollute your code with configuration logic. (Thanks commenters)
So: Lots of changes --> Branch (more maintainable), few minor changes --> Make configurable (more practical).
We have to do it all the time. We try to generalize and make the differences between versions configurable. The most common reasons for customizations are:
additional database fields: we implemented a dynamic way to store these items in db
UI layout: we have special folders where we put images and css files which are loaded on demand
different mandatory input fields: we store the definition in the configuration and activate them programmatically
special reports: we put the template files in the custom folder in order to be chosen instead of the standard template
Some changes require programming new modules. We code them in a custom library which will be dynamically loaded inside the main application.
We usually make those differences by being data driven. The customer's difference is just a different setting; any other user in the future could as well reuse the same "custom" options later on.
Creating "one-off"s doesn't scale.
Custom patches are a pain for this very reason. We typically just branch in our source control system, and manually apply the changes after updating with a script. Because of the additional overhead, we discourage custom patches as much as possible.

Resources