I'd like to build a mid-sized website which also includes a mobile website and an API.
As I already have some experience with Symfony I'd like to build the project on top of it.
However, I have no idea how to structure my project. Maybe there are some guidelines how to approach this problem?
Is it a good idea to build a each component as an individual Bundle? E.g. CoreBundle, APIBundle, WebsiteBundle and MobileWebsiteBundle, whereas CoreBundle would contain all Models and Validation and the other Bundles Controllers and Views?
Or is there a completely other way?
You don't need to put all of your code into the bundles. In fact the more code you put there, the more you're coupling it to the framework.
Consider extracting some of the non-Symfony related code into separate namespaces and treat bundles more like a glue between your PHP code and Symfony framework.
For example:
Acme
Bundles
ApiBundle
WebsiteBundle
Entity
Tools
Twig
If you decide to put entities outside of the bundle you'll have to configure a new mapping in the app/config/config.yml:
doctrine:
orm:
mappings:
Bossa:
type: annotation
is_bundle: false
dir: %kernel.root_dir%/../src/Acme/Entity
prefix: Acme\Entity\
alias: Acme
Related
I've a need to link 2 applications to the same database and same entities in Symfony 4, after some reading around it looks like this can be done with bundles. I've not actually worked with bundles before as i cam into symfony at version 4 where it wasn't really needed.
I've not been able to find any documentation for it, i see symfony's here https://symfony.com/doc/current/bundles.html but this just explains how to create the structure, it doesn't explain how to then use the bundle across the two apps.
Please could someone point out where i would find this information, or perhaps an example? My current setup is as follows:
api -> main app with symfony 4
admin -> my second app which will run an admin interface but is separate from the main app, this is the one that needs to share entities with api app.
I have so far created the directories in the "admin" one like:
src/MyOrg/MyOrgBundle/MyOrdBundle.php
I have then loaded this in the config/bundles.php -> this is where i am now a bit lost. The main thing is, i can't figure out how to load my bundle into both applications from a shared location, i don't really want to duplicate the files in both apps if i can get away with it.
UPDATE
I have just been playing around with config/doctrine.yaml and changed the following to test:
mappings:
App:
is_bundle: false
type: annotation
#dir: '%kernel.project_dir%/src/Entity'
dir: '%kernel.project_dir%/../share/Entity'
prefix: 'App\Entity'
alias: App
When i run php bin/console make:entity and put TestShare for example, it produces this error:
[ERROR] Only annotation or attribute mapping is supported by
make:entity, but the App\Entity\TestingShare
class uses a different format. If you would like this command to generate the properties & getter/setter methods,
add your mapping configuration, and then re-run this command with the --regenerate flag.
And it creates the entity in src/Entity instead of ../share/Entity - but i just told it where to put them in the config?
When creating a new SF2 project, the project contains an AppBundle by default. Should this be removed like the AcmeDemoBundle?
Symfony best practice
For most projects, you should store everything inside the AppBundle.
http://symfony.com/doc/current/best_practices/business-logic.html
Multiple bundles
I tend to create multiple bundles, e.g. I have these bundles in src/:
MyProjectEntityBundle
MyProjectBackendBundle
MyProjectHomePageBundle
And for reusable components I create a symfony bundle that I put into a git repository and load it via composer using satis. So for example I have some bundles in vendor/:
VendorCmsUtilBundle
VendorImageThumbnailBundle
"Domain Driven Design (DDD)"
I have yet to try this approach (I will soon):
http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/
As #Marcel Burkhard pointed out, the AppBundle is where you should put all your application logic according to Symfony best practices. Of course you can throw it away and build your own, but it's definitely not like the Acme Demo bundle.
I disagree with the strategy of splitting Entities and Frontend / Backend in different bundles.
I agree with the strategy of creating your own "utility" bundle(s) so that you can reuse your code in different projects via composer.
I started converting a legacy app over to symfony, my first experience with a php framework was zend, learning zend 1.* to a point where I felt comfortable took me over a year, now I've challenged myself to learn symfony since I find zend 2.* overly complicated.
With zend I was used to just creating a controller class and the view to create a page. With symfony I have to create the route entry, then the controller class and finally the view.
My routes.yml is over 100 lines long with all the requirements, methods and whatnot, and I am about a third into the project.
How can I keep this file organized? Right now it looks very chaotic.
Your site should be split into bundles that represent the section of the site that it concerns (from the site I am currently working on)
AddressingBundle
ChartBundle
ContactBundle
CoreBundle // A bundle that contains all merging items (model, types, etc)
CustomerBundle
PaymentBundle
PolicyBundle
.. etc ...
NOTE: I use YAML for routing. Annotation are available that require no extra files but (possible) means lack of reusability of routes
Within each of those bundles is a set of routing files that can be included or not. Each bundle has a routing file located at Resources/config/routing.yml that links to a selection of files located in Resources/config/routing/.
Then for the main app/config/routing.yml file I can then link to the outer (Resources/config/routing.yml) or internal (Resources/config/routing/something.yml) as needs be. Also it enables you to use the same routes multiples times using different paths depending on prefixes.
UPDATE:
The idea of bundles is to separate concerns. So for me I have (which I have massive stolen from the make up of Sylius) the CustomerBundle that only has a single entity (Customer), then I have the AddressingBundle with a single entity (Address). These can work alone but are attached using the data in CoreBundle. This way if I need to edit the Customer section I just edit CustomerBundle and make sure it interacts in the same way. Technically there is not public and private bundles (due to them all being below root), there are only routes that you make public via your routing and security.
Currently I'm having one global assets.yml file in my project, where I define my assets and I use them throughout the whole application. I have several bundles and all their assets are defined in this global assets.yml which is not clear and not good.
I'd like to define one assets.yml with corresponding assets per each bundle. They would lie in the bundle configuration.
I don't know how to make them accessible for the entire application. Should I use import somehow or does the framework load files (which name follow certain convention)? I'd appreciate hints how can I achieve the above.
edit: I should explain a bit more... In my config.yml I import assets.yml as a resource:
imports:
- { resource: assets.yml }
and the assets.yml looks like the following:
assetic:
use_controller: false
filters:
cssrewrite: ~
yui_js:
jar: %kernel.root_dir%/Resources/java/yui-compressor.jar
#apply_to: "\.js$"
yui_css:
jar: %kernel.root_dir%/Resources/java/yui-compressor.jar
#apply_to: "\.css$"
assets:
jquery:
inputs:
- '%kernel.root_dir%/Resources/public/js/jquery-1.8.0.js'
- '%kernel.root_dir%/Resources/public/js/jquery.sizes.js'
- '%kernel.root_dir%/Resources/public/js/jquery.form.js'
- '%kernel.root_dir%/Resources/public/js/jquery.validate.js'
- '%kernel.root_dir%/Resources/public/js/jquery.metadata.js'
[...]
Check the official documentation for How to expose a Semantic Configuration for a Bundle
Some refs:
When you create a bundle, you have two choices on how to handle configuration:
Normal Service Configuration (easy):
You can specify your services in a configuration file (e.g. services.yml) that lives in your bundle and then import it from your main application configuration. This is really easy, quick and totally effective. If you make use of parameters, then you still have the flexibility to customize your bundle from your application configuration. See "Importing Configuration with imports" for more details.
Exposing Semantic Configuration (advanced):
This is the way configuration is done with the core bundles (as described above). The basic idea is that, instead of having the user override individual parameters, you let the user configure just a few, specifically created options. As the bundle developer, you then parse through that configuration and load services inside an "Extension" class. With this method, you won't need to import any configuration resources from your main application configuration: the Extension class can handle all of this.
So the main idea is to create Extension class in each bundle and load bundle specific configuration files.
You can also check core symfony or third-party bundles for some examples.
I am migrating from symfony1 to symfony2, I have hard time implementing propel behaviors. Where do I actually have the propel.ini in symfony2?
Well in sf1.4, it was inside root config directory. How about symfony2?
The Propel ORM Symfony2 page says this:
You can add a app/config/propel.ini file in your project to specify some configuration parameters. ... However, the recommended way to configure Propel is to rely on build properties.
You can define build properties by creating a propel.ini file in app/config like below, but you can also follow the Symfony2 convention by adding build properties in app/config/config.yml
So I believe you can come close to the Symfony1 behaviour by creating app/config/propel.ini, but the more idiomatic way is to use app/config/config.yml as that page illustrates.
Caveat: I haven't used Propel with Symfony2, so this answer is solely based on the manual.