Symfony2 : Share Bundles between 2 projects - php

Our company decided to move to Symfony2 and now we are trying to re-write our application. I'm still new to Symfony2 and trying to figure out what is the best way to build the app.
our app consists of 2 part each part is on a different server:
A contains all the logic required to get/store/update records in database
B users requests go to, process the request and send another request to A for any database interaction
I'm planning to use Doctrine in A so i created all the required Entities, but i feel i need to share A entities with B since it's easier to create/validate forms using entities.
Am I going into the right direction or I don't have to share the entities?
If I share the entities and B doesn't have any database connection, will that create any problem for me?
If I'm going to do this approach (separate logic and database calls into 2 separate bundles each one on a different server) is there any consequences? where should i build Services ? on A or B or also i would have to share Services too?
Thanks

I did not have the exact problem you described, but I wanted to share/extend some entities between applications in single project. However, I was recommended by good folks on SO to branch entire project.
I suppose you will be using Git so you'll have two branches: A and B. Both will have common files (entities in you case), but will certainly contain different controllers/services as necessary.
Now, since you've mentioned two servers, not only you will have separated code but you will be able to set different deployment scripts both for A and B.
The downside: I believe that some intermediate knowledge of git branching will be necessary.
Is that acceptable for you?

Related

Laravel site using SPA multiple subdomain

I want to build a project with 3 section: API, Admin, and User.
I will build the API using Laravel, Admin and User will using ReactJs (SPA) with this route:
api.example.com (api)
admin.example.com (admin)
example.com (user)
I need a solution about project management.
Is it better to separate those 3 or should I combine it into one
project (laravel)?.
What about teamwork if I combine or not?
Any drawback if I combine or separate those?
Thanks!
Unless you have overlapping functionalities, I would suggest that you separate the three with three different projects.
The benefits are:
One project breakdown will not affect the other
You can have separate developers working on different sections and they won't have to worry about conflicts/commits not pertaining to their code
It will help you create separate documentation for the three, which will be easier for someone new to the project
From a security perspective as well, if one application gets compromised, the others won't be
However these also get influenced by personal experiences, and specific project requirements. Experience is the best teacher.

how to access Symfony's data / business layer from 3rd party apps

I have te following architectural scenario which doesn't depend on me and I can't change:
On one server/machine has several php applications and a postgresdatabase: each application uses its own schema in order to separate applications'data logically. I'm developing a new application - the one represented by the A - using Symfony, which manages and stores data that should be partially accessible by other apps, especially by an old app that's not been developed with symfony nor any other framework. To make it simple you could imagine A app storing movies sent from clients by means of its REST API. I would like B, and C accessing movies' data: B ocasionally should need accessing all the movies with a certain actor acting in it, and C would like to update the owner studio (or vice versa). Of course it would be an A's job, the symfony app that was born exactly for that purpose. SO I thought I have two ways, represented by the arrows:
A's exposes some way an API that B can call. That way I don't have to duplicate business logic and data persistence. Maybe by exposing Doctrine's entities or a controller in some way. Of course I should load at least doctrine, the container, the configuration the httpframework component and when it comes to using C I guess this solution would be unfeasible because I would have two apps using and loading most of the same classes, without any kind of isolation between the two. Another (extreme?) solution I thought is not using Symfony for exposing my A functionalities to the other apps: I could write an API class that connects to the DB and does some logic without any Symfony's support (PDO and friends. No services, no components, nothing.). Luckily what I have to expose is little and that wouldn't be that big problem.
Finally, I would avoid calling A by means of the shell (i.e. app.php console/getMovie) because it consumes tons of resources and I don't think it's that fast. My server is really small and couldn't live up to that
B and the other apps could access A's schema, but that way I maybe should duplicate some business logic and I see it kind of messy. Maybe C app could simply uses an A bundle I could write, explicitly written to expose some A's functionalities 3rd party apps need.
These are the two solutions I've found, but I do appreciate how you think I should design this.
It is possible to share data between schema by using views in a common place (usually public schema).
This has several advantages:
it lets you use your schema structure the way you want.
it exposes the data you want.
it lets you manage the write accesses you want (yes, views may be writeable)
it makes you able to deal with GRANT/REVOKE easily.
it makes the applications able to leverage Postgres` LISTEN/NOTIFY feature to communicate.
There are downsides:
Updating a view means deploying new model files on all the applications using it. It can be a project on its own that the other applications depend on through composer.

SAAS and Multi-tenancy in Symfony2? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I've been using Symfony for close to 2 years now, so far, each project I build is deployed specifically for each client (i.e one client, one codebase, one db).
Lets say I have a Project Management app that I want to deploy for many clients. Assuming the clients will go with whatever features I build into the system, if I deploy a different codebase (therefore, a different db) for each client, here are the problems I foresee:
Pushing bug fixes and upgrades will be painful. I need to push it to every repository that I have deployed. It won't scale well if I have 50 clients using that same app.
Management is painful. How do I build an admin system for myself where I can pull ALL the projects into one HTML table? After all, each client has their own database, right? For me to do anything meaningful with all the records of all my clients, I need a way to look through all their databases at one go, which.. I don't think Symfony allows. (I'm not sure)
User account issues. If a user happens to work for multiple companies, all of them using my Project Management app, that user has to sign up multiple times. (I know this can be circumvented if I use oauth, but I'm trying not to go there if I can)
Here are the solutions I have thought up and tried to a certain extent.
Solution 1
One database and one codebase for ALL my clients. Projects will go under one table, Invoices go under one table, all marked by their own client_id. Users can be assigned to Projects so there is no need to sign up multiple times.
This is not that hard to create. But, what happens if different clients need different columns for their Invoices? My Invoice table will keep expanding (with different fields that different clients want), and each row can potentially contain many null fields. Not to mention, my Invoice entity will grow in file size, and I will have to update the database schema every time a new customization comes in.
Solution 2
One database where each client has their own table prefix. So for Client A, I could use clientA_projects, clientA_invoices, clientA_configuration etc.
This is ideal if each client wants to customize their fields. But, does this mean I need to create new entity and form classes for each new client that comes into the system? It looks like with this solution, I need to update the database schema with every new client I get.
Currently, I am experimenting with schema-less databases (mongo and couch), hoping that without needing to specify the table schema upfront, I can implement Solution 1 without hassle. But I'm still experimenting, and there are ways to go before I dare to deploy a production-ready app, being unfamiliar with the issues of mongo and couch with Symfony.
So, this is where I am stuck at. Being a self-trained programmer, I feel I have a lot of holes in my knowledge that requires filling (as opposed to someone from a CS background). There aren't many places on the web talking about Symfony 2 and multi-tenancy (maybe I'm looking for the wrong thing). If anyone of can point me to a clearer direction, maybe best practices, example projects, I will really appreciate it!
Btw, I plan to execute this in the latest version of Symfony (2.3.2 at this moment).
Thanks in advance guys.
I'm also using Symfony2 for similar amount of time (since one of BETAs) and I advise you to go with solution #1. If you are going SaaS you can't give out code to clients for the reasons you wrote (problems with updates / upgrades mainly). The whole hassle will be on the user management - which user has access to which data, belongs to which group, company and so on. All other things if done properly will be coded the same user-agnostic way. What should you do with different requirements for different companies? Make such features configurable. You can implement this on various levels:
simple entity attributes: have an attributes field in each table and save everything as JSON, YAML or other dynamic-structurable content,
general configuration: have one place where entity base configuration is stored (in the means I wrote above) and allow users to manage new features from there, all changes are propagated to simple entities,
implement something what I call Entity Parameters Pattern - design database tables which would contain parameter types, parameter values and relation to other entities on different levels and then make generic configurable parameter types which can be applied to any place with predefined meaning. For example "preferred_season" being a parameter of type "choice_string" containing configuration "spring,summer,autumn,winter" and when attached to given entity would always render a <select> field with choices and save selected value with relation to both entity and parameter type.
Also the solution #1 has one unbeatable advantage - it could handle more that one company even if you wanted to give out the code at the end. You'd just need to mask the ability to add more. :)
This question is tagged Symfony2 but it really shouldn't. It doesn't matter what framework you're using, you should abstract your application design from code and then use frameworks as a mere tool for doing the job smoothly. I'd like to say that even taking previous sentence into account, I'm absolutely in love with Symfony2. :)
I know this is an older question but can be usefull for others.
I agree with #Tomasz and solution #1 with one database – all tenants in one database. The biggest problem here is proper database design to solve further security issues: access for resources must be controlled by application to prevent unauthorized access between tenants. On the other side we have ease implementation as we are implementing single application with only one database.
Nice article about Symfony2 and moving to SaaS model:
http://www.browserlondon.com/blog/2015/01/moving-to-a-saas-model-with-symfony2/
Also "must read" article about designing database in SaaS platform - patterns that are platform independent:
http://labs.octivi.com/database-design-in-saas-platforms/

Managing multiple web applications with the same code base

I'm looking for the best way (or easiest way) to manage multiple instances of a PHP web application, that share the same code base.
Let me break it down for you:
Our domain is hosting multiple instances of the application, each with their own settings files and database.
http://mydomain.com
|
|------/customer1/
|
|------/customer2/
|
|------/customer3/ + custom features
Let's say that customer 1 & 2 purchased the application (that we host for them), and they have the base model of that application. (ie. not customized)
However, customer 3 wants feature X or Y, so we code that feature for him and add that to the application.
But whenever there is an update to the code base (ie. a security fix in the core classes of the framework) all three customers should get an update of the base code!
What would be the best way of managing this sort of setup? Manually uploading all files using FTP is a pain, and it's not possible to merge code.
Using Git is perhaps a solution, but how would I go around and do it? Create separate repositories per customer? What if we grow to over one-hundred customers?
Any insight are welcome, including why we should or should not use such a setup. (but remember that we'll be the ones hosting the application for our customers)
I remember doing this years ago so you will have to take into account i'm now a little rusty at this.
I built a standalone framework, which combined all includes into ONE .php file. Any frameworks that used that, would do a PULL request and if the md5 of their framework matched the framework on the central server then no update was needed. Otherwise it would download the new framework over https and replace it's own copy. This created an automatic update system that was PULLED to all other apps that used it.
A major problem to this is, if you cause say a syntax error and you upload that to the central server, it will get pulled to all others and break them! You will be best to use a cron job to make the pull request that does NOT use the framework so the broken framework won't break it from doing a pull request to FIX the syntax error in the framework. This at least adds the ability to automatically fix itself as well once you fix the syntax error on the central server. However, having a staging server to test each update really is very important in this case.
That is only the basics of course as if you have say images that the framework uses they will also need to get pulled over, as well as any SQL updates and so forth.
You must regorisly test this before uploading to the central server in order to prevent mass errors! Not ideal! Unit testing, staging server, small and simple updates but more often (large updates have more potential to go wrong, and more to undo if it does go wrong) will all help mitigate the risk.
You will also have to structure the framework VERY VERY VERY VERY VERY well from the beginning to make it as flexible as possible when planning on having many different sites use it. If you design it wrong in the beginning it may be next to impossible to redesign further down the road. For example it may be wise to use PDO for database access, allowing all the applications the ability to use different databases while your classes etc will still no know how to interact with the database (regardless of if it's mysql or oracle), though, i would advise at least sticking to one if you can.
Design wise, you are best to look at other language frameworks and see how they do what they do. You must stick to good design principles, use design patterns only where applicable, and take note of MVC!
Further Reading...
http://en.wikipedia.org/wiki/Software_design_pattern
http://www.ipipan.gda.pl/~marek/objects/TOA/oobasics/oobasics.html
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
http://www.phpframeworks.com/
This is no easy task, so be warned.
You mixed two separate different tasks in one question
Development and support of diverged code
Deploy of code from (any) SCM to live systems
Answer on 1-st question (for any modern) SCM is branching and merge branches (each customer have own branch, into which you merge needed parts from you single development-branch, or /better/ with "branch-per-task" you merge task-branch in all needed targets, avoiding cherry-picking)
Answer on 2-nd question is "Build-tools", which can interact with your SCM (you have to write more details later for more detailed answer)
Make your custom features modular. Use a similar architecture to WordPress/Joomla which have plugins or extensions. This allows your customers to easily have separate feature sets but all share the same base code.

What should a bundle in Symfony2 represent

This might be an obvious thing to you but - even after reading through a lot of manuals and blogs - I'm still not sure what exactly should a bundle in Symfony2 represent in a webpage. And it's hard to guess it from the simple demo applications.
For example: I have a site which is divided into two parts (one is just a 2nd level domain like example.com and another is dom2.example.com). Each of these two parts has some sections of it's own - sometimes the same (like news) sometimes different.
What would the correct representation of this in symfony2? Should I have
a MySite\site1 and MySite\site2 bundle and do the different sections via different controllers, or
bundles Site1\News and Site2\News, or
bundles MySite\Site1News and MySite\Site2News etc.
...or am I getting all wrong at this?
I am also new to Symfony and will follow the results of this question with interest, but for what it's worth, my take on it is:
A bundle is just that: a group of files, assets, PHP classes and methods, tests, etc. The logic of the grouping can be anything you like. In some cases, it's really obvious what the grouping is and why it's been done -- for instance, if I wrote a blog system for Symfony2 and wanted to release it, I'd make it into a bundle. That's the sort of example used most in the documentation.
But you'd also use bundles for anything you wanted to release as one little feature. Say for instance, this bundle which creates default routes for all your controllers. It's not a fully developed plugin/feature like a blog or forum, but it's a bit of code that I can easily import into my project, it stays totally separate from everything else, it's a bundle.
Finally, you'd also use bundles internally to your project, in absolutely any way which makes sense to you.
My take on your specific situation:
Quick and easy:
MySite\MyCode -- gets the job done, and maybe you don't have any logical way to break up the code you're going to write.
If there's some more unique features between the two sites and you want to separate them out for clarity:
MySite\SharedFeatures
MySite\Site1Features
MySite\Site2Features
If you really like everything in its place, or if you have a complex project, maybe:
MySite\MySiteMain (shared features and catch-all miscellany that doesn't deserve its own bundle)
MySite\News
MySite\Site1FeatureSomethingOrOther
MySite\Site2FeatureSomethingOrOther
I definitely think you want to stick to logical groups of code -- so I think your example "bundles Site1\News and Site2\News" and "MySite\Site1News and MySite\Site2News" wouldn't be the best way to go. Site1 and Site2 are implementations, so making a separate bundle for each site's news page would seem to be counterproductive to me; you'd want to make one news component and build it to be used in two different ways.
As for your two-domains question, you can either point both domains at the same code, and test within your code for what domain is being requested, or you can check out two copies of the same code and change the configuration files slightly (this doesn't necessarily violate the idea of DRY because you'd still edit the code in one place, then update both copies.)
The way I understand a bundle is that it is similar to what CMS like e.g. Typo3 or Drupal call a "plugin". So it should be ideally self-contained and written in a way that it can be used on other projects too.
E.g. in your case I'd create a "staticHtmlBundle" that contains all the static pages of your website, divided within by site.com and dom2.site.com.
Then I would create a "newsBundle" that contains all the news-articles, maybe even database-driven with a little admin-section where you can edit them and assign them to different channels (in your case that is site.com, dom2.site.com). A static page from within staticHtmlBundle would call newsBundle and display its data (like e.g. a listView of the news or a detailView and so on).
If you keep everything as abstract and reusable as possible then you could even publish the newsBunde in the Symfony 2 Bundle repository and share it with the community!
The way I perceive Symfony2 bundles is that they are provide a modular system which allows you to not only extend and override the php code, but also any resources they may or may not include.
Having said that, consider you have an API and you would like to transfer an object.
How would you do that?
Of course, you can do that manually, but wouldn't it be nice if Symfony can do it for you?
My way of doing this would include 3 bundles, JMSSerializerBundle and FosRestBundle.
One bundle for the client side - MyCompany/ClientBundle
One bundle for the server side - MyCompany/ServerBundle
One bundle housing all the data transfer objects I would like to be able to transfer - MyCompany/CommonBundle.
Inside my MyCompany/CommonBundle I would have the classes I would use for my data transfer objects along with the serialization rules I would have to provide the JMSSerializerBundle with. They may be in the form of xml, yml or php annotations.
Once you have an object filled up with the data, you can just use return and FosRestBundle would serialize it for you. Serialization would depend on the routing, so you can have the object serialized in XML for one system and in JSON for another. Key point is you have different serialization formats and versioning you can utilise at later point.
On the client side, you can use simple param converter to convert the received JSON or XML to an object right in the controller with no additional hassle. You can also type in some validation rules, so you can verify if the object is populated as you expect it to be.
In my example, the MyCompany/CommonBundle has objects that would be used by multiple applications and would be identical. Having that as a separate bundle helps you avoid code duplication and makes long term maintenance a lot easier.
I hope I managed to explain this. Any questions?
Ask in the comments. Will update the answer accordingly.

Categories