28

I have an image under the public folder.
How can I get my image directory in symfony4 ?
In symfony 3, it's equivalent is :

$webPath = $this->get('kernel')->getRootDir() . '/../web/'; 
2

7 Answers 7

37

It is a bad practice to inject the whole container, just to access parameters, if you are not in a controller. Just auto wire the ParameterBagInterface like this,

protected $parameterBag; public function __construct(ParameterBagInterface $parameterBag) { $this->parameterBag = $parameterBag; } 

and then access your parameter like this (in this case the project directory),

$this->parameterBag->get('kernel.project_dir'); 

Hope someone will find this helpful.

Cheers.

Sign up to request clarification or add additional context in comments.

Comments

31

You can use either

$webPath = $this->get('kernel')->getProjectDir() . '/public/'; 

Or the parameter %kernel.project_dir%

$container->getParameter('kernel.project_dir') . '/public/'; 

2 Comments

Worth to mention that the controller needs to extend the Symfony\Bundle\FrameworkBundle\Controller\Controller class, not the abstract one that you find on most examples Symfony\Bundle\FrameworkBundle\Controller\AbstractController
worth to mention @CarlosDelgado that the controller class you mentioned is being deprecated in Symfony 4.2 @deprecated since Symfony 4.2, use {@see AbstractController} instead.
10

In Controller (also with inheriting AbstractController):

$projectDir = $this->getParameter('kernel.project_dir'); 

3 Comments

Why did you downvote this? This is the only one that worked for me?!
@godrar because we're talking about Symfony 4 where your controllers should be defined as services thus, not inheriting from AbstractController.
@vdavid Yes, it worked in old versions. In the new version you do not have access to the kernel in this way (inject "container" is bad practice)
7

In config/services.yaml:

parameters: webDir: '%env(DOCUMENT_ROOT)%' 

In your controller:

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; ... public function yourFunction(Parameterbag $parameterBag) { $webPath = $parameterBag->get('webDir') } 

If you need to access a directory within public, change the last line to the following:

$webPath = $parameterBag->get('webDir') . '/your/path/from/the/public/dir/' 

2 Comments

Moving forward to Symfony 4 and beyond, this is closer to the real answer. $this->get('kernel') is deprecated in 4.2.
+1 for being the only answer that uses an environment variable instead of hard coding the public directory. Although, I would recommend binding this as an argument for the service in its config instead of injecting the whole parameter bag.
5

You can inject KernelInterface to the service or whatever and then get the project directory with $kernel->getProjectDir():

<?php namespace App\Service; use Symfony\Component\HttpKernel\KernelInterface; class Foo { protected $projectDir; public function __construct(KernelInterface $kernel) { $this->projectDir = $kernel->getProjectDir(); } public function showProjectDir() { echo "This is the project directory: " . $this->projectDir; } } 

Comments

3

All above answers seems valid, but I think it's simplier if you configure it as parameter in services.yaml

If you need to use it in serveral services, you can bind it like this:

# services.yaml services: _defaults: autowire: true autoconfigure: true bind: $publicDir: "%kernel.project_dir%/public" 
# src/Services/MyService.php class MyService { public function __construct( private string $publicDir, ) { } // … } 

This way, this is configured at one place only, and if later you decide to change /public to something else, you will have to change it only in .yaml file.

If you don't need the root directory but a subdirectory, it might be better to define the final target path: This way you will be more flexible if you need later to move only that directory, like $imageDir or $imagePath (depends if you will use the full directory or only the public path).

Note also the default public path is defined in composer.json file, in the extra.public-dir key

edit mai 2025:

In latest Symfony version (since 6.1), you can also use the #[Autowire] attribute. So you can use parameters section in a yaml file to define for example public_dir , and inject it in your service. Depending of your needs / usages you might prefer this:

# config/services.yaml parameters: public_dir: 'public' services: … 
# src/Services/MyService.php class MyService { private string $publicPath; public function __construct( #[Autowire(param: 'kernel.project_dir')] string $rootDir, #[Autowire(param: 'public_dir')] string $publicDir, ) { $this->publicPath = realpath($rootDir . DIRECTORY_SEPARATOR . $publicDir); } // … } 

Comments

2

Starting from Symfony 4.3 we can generate absolute (and relative) URLs for a given path by using the two methods getAbsoluteUrl() and getRelativePath() of the new Symfony\Component\HttpFoundation\UrlHelper class.

New in Symfony 4.3: URL Helper

public function someControllerAction(UrlHelper $urlHelper) { // ... return [ 'avatar' => $urlHelper->getAbsoluteUrl($user->avatar()->path()), // ... ]; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.