Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where do private, custom bundles live in Symfony 4?

I have a number of private, custom bundles that I use in my Symfony projects. Under Symfony 3, they lived in a sub-directory of src:

src/
    DSL/
      DSLLibraryBundle/
      DSLTelnetBundle/
      ...
    SiteBundle/      # (or AppBundle)

Under Symfony 4, the application-specific bundle is gone and it's unclear to me where my custom bundles should live.

The documentation on bundles (https://symfony.com/doc/current/bundles/best_practices.html#bundles-naming-conventions) provide no specific recommendations for placing custom bundles.

I have tried placing my DSL directory directly under the project directory and under src/. I end up with undefined class errors either way.

I currently have:

src/
    DSL/
        LibraryBundle/
            DSLLibraryBundle.php

The bundle file:

// src/DSL/DSLLibrary/DSLLibraryBundle.php:

namespace DSL\LibraryBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class DSLLibraryBundle extends Bundle
{

}

The entry in bundles.php:

DSL\LibraryBundle\DSLLibraryBundle::class => ['all' => true],

Current error when running a console command:

PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\ClassNotFoundException: Attempted to load class "DSLLibraryBundle" from namespace "DSL\LibraryBundle".

A couple of notes:
- My custom bundles are not installed via Composer
- The actual DSL/ directory will be a symlink once I get this working

like image 738
David Patterson Avatar asked Jan 25 '18 00:01

David Patterson


People also ask

What are bundles in Symfony?

A Symfony bundle is a collection of files and folders organized in a specific structure. The bundles are modeled in such a way that it can be reused in multiple applications. The main application itself is packaged as a bundle and it is generally called AppBundle.

What Symfony bundles or composer packages do you use the most often?

So, without further ado, here are the most useful bundles according to you, the Symfony community (in parenthesis, the percent of survey answers that noted each bundle): FOSUserBundle (60%) FOSRestBundle (30%) KnpMenuBundle (25%)

Does Symfony 4 support bundle-less applications?

Fabien Potencier said in the Symfony 4 best practices blog post "Bundle-less applications is just one of the best practices changes for Symfony 4". You must not generate new bundles, you can use default "App" bundle for your whole project. Show activity on this post. Show activity on this post.

What is the directory structure of a Symfony bundle?

The directory structure of a bundle is meant to help to keep code consistent between all Symfony bundles. It follows a set of conventions, but is flexible to be adjusted if needed.

What is the acmetestbundle in Symfony?

The new bundle is called AcmeTestBundle, where the Acme portion is an example name that should be replaced by some "vendor" name that represents you or your organization (e.g. AbcTestBundle for some company named Abc ). Start by adding creating a new class called AcmeTestBundle: The AbstractBundle was introduced in Symfony 6.1.

How do I enable/disable Symfony flex bundles?

Bundles used in your applications must be enabled per environment in the config/bundles.php file: In a default Symfony application that uses Symfony Flex , bundles are enabled/disabled automatically for you when installing/removing them, so you don't need to look at or edit this bundles.php file.


2 Answers

Update April 12, 2019: In the end, I took a completely different approach than my initial attempts.
In a nutshell, I now use composer to include my custom bundles.

My custom bundles live in their own directory tree.
Each bundle must have a valid composer.json file defining the bundle. For example:

{
  "name": "dsl/base-bundle",
  "description": "Base bundle required by all other DSL bundles",
  "type": "symfony-bundle",
  "version": "2.1.0",
  "license": "proprietary",
  "authors": [{"name": "David M. Patterson", "email": "[email protected]"}],
  "minimum-stability": "stable",
  "require": {
  },
  "require-dev": {
  },
  "autoload": {
    "psr-4":  {
      "Dsl\\BaseBundle\\": "src/"
    }
  }
}

Then define a custom repository in the project's composer.json file:

"repositories":[
  {
    "type": "path",
    "url":  "/full/path/to/DslBaseBundle"
  },
 ], ...

Then do a composer require dsl/base-bundle
Composer will create a symlink in vendor/ to the bundle and everything works as expected from there on.

My personal library is a regular Symfony project with a lib sub-directory that contains my bundles, each in its own sub-directory below lib/.

The Symfony application provides me with a convenient test bed. Note that the custom bundles must be included in it the same as for any other Symfony project.

@Stnaire, hope that helps.

like image 110
David Patterson Avatar answered Oct 10 '22 08:10

David Patterson


It's actually not as bad as it's painted in other comments - you can still have your private bundles inside src/, you just have to explicitly exclude them from autowiring, so they don't get accidentally loaded with an incorrect namespace.

Lets say you have a PrivateBundle in src/PrivateBundle.

You set up it's autoloading in composer.json like so:

"autoload": {
  "psr-4": {
    "App\\": "src/",
    "SomeNamespace\\PrivateBundle\\": "src/PrivateBundle/"
  }
}

and in your services configuration (I usually use config/services.yaml) do this:

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
    resource: '../src/*'
    exclude: '../src/PrivateBundle'

If you don't add this exclude, your SomeNamespace\PrivateBundle\* classes get automatically loaded by Symfony as App\PrivateBundle\*, but contain namespace SomeNamespace\PrivateBundle;, so when PHP detects a usage of SomeNamespace\PrivateBundle it autoloads them again through Composer, resulting in Cannot declare class *, because the name is already in use errors.

like image 2
Kick_the_BUCKET Avatar answered Oct 10 '22 09:10

Kick_the_BUCKET