Customize Symfony Namespaces
Recently I have been looking at the setup process for various frameworks. I'm wanting to learn some lessons to apply to my personal framework and review which production-ready system I'd like to start using for a new application. Having decided to go with Symfony I wanted to talk about a minor annoyance I have with the default setup and how to properly fix it.
The Default Namespace
While I understand why the popular PHP framework skeletons all have the same top-level namespace of App
it isn't a pattern I like. In my humble opinion, the top-level namespace should be more descriptive and correlate to the vendor that produced the package. This could be a single individual, in which case I like my GitHub username, or it could be the name of an organization. It is possible to change the default namespace used by Symfony, but you need to do so in several places and is easy to mess up. This article talks about how to properly change the default namespace in a Symfony 5.3+ project so that everything works correctly. I'm going to show how to upgrade the App
namespace to Cspray\MyCoolApp
, you should replace this with something appropriate for your use case!
Step 1 - Update composer.json
The very first step is to update your composer.json
file to ensure autoloading picks up your new namespace.
{
"autoload": {
"psr-4": {
"Cspray\\MyCoolApp\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Cspray\\MyCoolApp\\": "tests/"
}
}
}
After you have finished modifying this file run composer dump-autoload
to ensure Composer knows to autoload code from the correct directories.
Step 2 - Update Generated Code
Next update the namespace for your Kernel. In the skeletons that I worked with this was the only generated code that needed to change. In other skeletons you'll need to ensure that all generated code has their namespace updated.
<?php declare(strict_types=1);
namespace Cspray\MyCoolApp;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel {
// rest of the Kernel implementation should be unchanged
}
Step 3 - Update entrypoints
Next update the entrypoints for Symfony that are instantiating and using your Kernel. You'll need to update the use statement to point to your namespaced Kernel. Change the bin/console
and public/index.php
files.
// ./bin/console
#!/usr/bin/env php
<?php declare(strict_types=1);
use Cspray\MyCoolApp\Kernel;
// rest of the bin/console code
// ./public/index.php
<?php declare(strict_types=1);
use Cspray\MyCoolApp\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
// rest of the public/index.php code
Step 4 - Update services mapping
Next update the namespace used by Symfony to determine autowired services. You can find this in config/services.yaml
.
services:
# default definitions
Cspray\MyCoolApp\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
Step 5 - Update config/preload.php
Next update the cached preload file path to reflect your new namespace. This file is autogenerated by Symfony and will include the fully-qualified class name with namespace separators replaced by underscores.
<?php declare(strict_types=1);
if (file_exists(dirname(__DIR__).'/var/cache/prod/Cspray_MyCoolApp_KernelProdContainer.preload.php')) {
require dirname(__DIR__).'/var/cache/prod/Cspray_MyCoolApp_KernelProdContainer.preload.php';
}
Step 6 - Update Doctrine mappings
Next update the mappings that Doctrine uses to parse your entities. This can be found in config/doctrine.yaml
.
doctrine:
dbal:
# dbal specific configuration
orm:
# orm specific configuration
mappings:
Cspray\MyCoolApp:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'Cspray\MyCoolApp\Entity'
alias: App
Step 7 - Update Maker Config
Finally, we need to make sure that any code we generate with the Symfony MakerBundle reflects the correct namespace. If it doesn't exist already create a new file config/packages/dev/maker.yaml
and ensure it looks like the following.
maker:
root_namespace: 'Cspray\MyCoolApp'
Conclusion
At this point your skeleton Symfony app should be able to process requests, execute console commands, and make generated code with the correct namespace. Updating the default namespace in a Symfony app isn't as straightforward or easy as I'd like it to be. Hopefully this guide will help in making this task a little easier to carry out. If I continue to create other Symfony apps I may create a command line tool to automate the steps seen in this guide. Either way, I hope you find this useful when creating your own Symfony apps!