Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where do I put generic library code in Symfony 2?

Tags:

php

symfony

Quick question: Where should I be putting code that has similar characteristics to the Controller Utilities Service Class as described here on this blog post by Benjamin Eberlei (http://www.whitewashing.de/2013/06/27/extending_symfony2__controller_utilities.html)?

For the interim, I've placed it inside: src/ProjectName/Library

Context

I've noted the following:

  • This logic does not belong to a specific bundle, in fact it applies to all bundles one would be creating.
  • This logic usually belongs in an application specific library, as opposed to being part of a bundle as controllers within bundles would either extend or utilise this library code.

I found some answers to questions that are similar in theme, but not exactly what I was after

Based on my research here on SO alone, this question seems to have been trodden to death somewhat, but I think the questions asked previously skirt around what I'm actually after. Regardless, it would seem that I have the following options:

  • Putting these types of extensions in a bundle - not applicable as the type of functionality I'm developing is essentially extending the framework code.
  • Creating a vendor directory for the project where all the library code would go - if this is indeed the best practice, then it would essentially mean that I'd have to make the library available via private repo in composer, but that means that I'd have to maintain a separate codebase.
  • Create some sort of pseudo connector bundle that lives in the src/Company/SomeNamespace - I don't even know if this is at all the way to go, but if it is in keeping with SF best practice, I'll look into it further.

The question, again, for brevity: Where do I put classes which provide generic, global functionlity in Symfony 2?

My thanks in advance.

like image 355
Aries VII Avatar asked Nov 11 '13 17:11

Aries VII


2 Answers

This documentation about composer repositories is a great reference and the documentation about packages that don't support Composer should be what you are looking for.

Also I'd like to note the documentation about VCS which is often used when you need to fork a Bundle and override the original one (I used it quite a few times).

You can do the following - it won't require you to have a packaging system or whatever. You just need to put the package as a zip accessible by your computer using a URL.

{
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "my/package",
                "version": "1.0.0",
                "dist": {
                    "url": "https://github.com/my/package/archive/master.zip",
                    "type": "zip"
                },
                "autoload": {
                    "psr-0": {
                        "My\\Package\\": "src/"
                    }
                }
            }
        }
    ],
    "require": {
        "my/package": "1.0.0"
    }
}

If your package doesn't support PSR-0 then you need to use the option "classmap" otherwise your package supports PSR-0 you need to use the option psr-0.

like image 134
Thomas Potaire Avatar answered Oct 05 '22 17:10

Thomas Potaire


After some messing around, while the accepted answer here holds merit, I've decided to create a "Core" bundle which will house all of my projects cross-bundle / application wide dependencies and resources.

This will allow me to have a central place for all assets, related entities and project specific library code.

Positioned for refactoring

I've internally reasoned with myself that this is a happy middle ground (perhaps temporary) solution which allows me to get on with development rather than the state of analysis paralysis that I'm in at this present time.

Doing things this way, I can have the flex points to refactor later on to the vendor directory solution.

If you are working on a project and are irked by the somewhat unnatural feel of having your entities and library code scattered around different bundles like I had been, this will be a good solution.

It does not change the default behaviour of SF2 and Doctrine 2

I've previously implemented a modification to Symfony 2 Doctrine 2 configuration which allowed me to (rightfully) remove Entities out of the bundle and into a separate, central namespace.

I liked this idea. I used it for a while. The caveat with this approach is that you no longer have the ability to use the Command Line Interface for when you quickly want to create a Doctrine Entity as a Bundle Namespace is required.

I thought it was fine because I needed to change things around anyway, but then I thought:

  • "How about the Form objects? where do I put those? In their own directory under /src like Entity is?
  • How about the service layer? (not DI, but the actual Service Layer - where the application logic lives)"

Halfway through writing up yet another "where do i put XXXX in Symfony 2" type question (which I'm sure those people following PHP and Symfony2 tags are sick of seeing), I've stopped and put it in a bundle I've called assets bundle, and renamed it to Core bundle.

The Core Bundle This way, it's in a bundle as per the CLI's requirement, it's a lot easier to follow and I can semantically share the contents of this bundle because it contains Core code specific to the application:

  • Entities.
  • Generic Forms.
  • Generic HTML, CSS and JavaScript assets.
  • Project Specific library code.
  • My Twig extensions also live here.
  • Finally, the Service Layer classes and their associated factories go here also.
  • If I have any other extensions I want to make to Symfony for this project, I'll be adding them here.

Most importantly, when I get time to actually sit down and work with composer et al, I can refactor this out easily because it all exists in the one place.

So. In a nutshell. To answer my own question: Where do I put generic library code in Symfony 2?

I'd put it in a bundle created specifically to store assets, resources and library code which needs to be accessible to multiple bundles using the following recommendations:

  • Create a Core bundle.
  • Put generic library code here.
  • Put all entities here.
  • Put generic assets (main.css, reset.css etc) here.
  • Put generic forms here.
  • Put all service layer classes here.

Package and install via composer

Do your research on how to format your file structure to be PSR-0 compliant then, when you're to start using composer:

  • Format it to be PSR-0 standards compliant
  • Package it up into a zip file and install it via composer (as per @Thomas Potaires editted instructions)

The Application / Project - Bundles that build the application but rely on the Core Bundle.


Core Bundle - Extends SF2 at key points, contains shared resources and library code. Because I did not change the way the framework works, the files are where SF2 expects them. This means that I can still use it's generators for Entities.

I won't have a problem with scaffolding / CRUD screens being generated here either as those will be regarded as prototypes, not real application features.


SF2 Layer. - stays the same, untouched. Extended.


like image 35
Aries VII Avatar answered Oct 05 '22 17:10

Aries VII