9

I use SensioLabs Insight to control my code quality.

For a simple file upload, I have to get the absolute path of my uploads directory:

protected function getUploadRootDir()
{
    // the absolute directory path where uploaded
    return __DIR__.'/../../../../web/'.$this->getUploadDir();
}

Code directly coming from official documentation (How to handle file uploads with Doctrine)

But SLInsight raises a warning if the code analysed contains __DIR__ or __FILE__ PHP magic constants:

__DIR__ and __FILE__ constants may conflict with the Symfony resource overriding system.

How usage of this constants can causes conflicts with Symfony?

And how can I avoid them in my code?

chalasr
  • 12,971
  • 4
  • 40
  • 82
  • 2
    The title is misleading. It's **recommended** to use absolute path constants `__FILE__` and `__DIR__` in general. It's better to use Symfony's file locator instead *only if you use Symfony (or it's file locator)* in your project. – axiac Dec 17 '15 at 10:31
  • Right, I've updated it. Thank you – chalasr Dec 17 '15 at 10:51
  • To be honest, if I saw that code, my reaction would be "there's got to be a better way than that". You're hard-coding that the path you want is exactly 4 levels up, then a dir called 'web', and then a dynamic segment. That looks very fragile and inflexible. Surely this whole path should be configured somewhere, relative to some specific base. – IMSoP Dec 17 '15 at 11:02
  • You are right, Symfony provides helpers for get paths the path of different parts of the application (i.e. @JavierEguiluz's answer), but they are not accessible from an entity. Also, the whole approach can be optimized by do it in a controller instead of an Entity. – chalasr Dec 17 '15 at 11:14

3 Answers3

13

In the case of the file upload class, you can probably ignore this error message. But in other cases, it's better o use the Symfony file locator instead of hardcoding file paths. For example:

$path = $this->get('kernel')->locateResource('@AppBundle/Resources/config/services.xml');

Instead of:

$path = __DIR__.'/../../../src/Acme/AppBundle/Resources/config/services.xml'
Javier Eguiluz
  • 3,987
  • 2
  • 23
  • 44
  • Hi Mr Eguiluz, Is it correct to use this code in an entity model ? (*I used to think that calling kernel or other service wasn't 'very clean' inside model....*) – BENARD Patrick Dec 17 '15 at 10:36
  • 3
    Well, I would say that getting the upload dir from an entity is already not clean. the entity should not be responsible to know where uploaded files are stored (which may not even be locally but on S3 for instance) – Christophe Coevoet Dec 17 '15 at 10:49
  • Thanks for this explanation Mr, and a great **ThankYou** for your whole job. – BENARD Patrick Dec 17 '15 at 10:54
7

Well, this is actually something that SensioLabs Insight does not handles properly. It warns against using the constants because of the resource overriding system, but in many cases, these constants are used in places which are unrelated to the resource overriding system (and this is probably the case for your code here). So you can ignore the warning in this case

  • This morning, The warning was raised on a unit test. This rule should be restricted to classes that can use the symfony resource overriding system. http://prnt.sc/aa68cw – chalasr Mar 02 '16 at 09:14
0

If you are creating a third-party bundle and want to locate some resources, the (good) solution proposed by @Javier is not applicable as it throws an exception:

ServiceNotFoundException in ContainerBuilder.php line 816:
You have requested a non-existent service "kernel".

In this case the solution is to use $this->getPath(), a method inherited by the BundleNameBundle from the Symfony\Component\HttpKernel\Bundle\Bundle class.

This returns the same result of realpath(__DIR__).

So doing $this->getPath() . '/Resources/config/doctrine/mappings' is the same as realpath(__DIR__ . '/Resources/config/doctrine/mappings').

Originally proposed here.

Community
  • 1
  • 1
Aerendir
  • 6,152
  • 9
  • 55
  • 108
  • The `kernel` service is not available at compile time (first because it is synthetic) so you can't use it from a compiler pass, but it actually works fine from any runtime context. Here the context is an entity so we should not use a service, and since my entity is not a Bundle instance (as it would not make sense), `getPath` is not available. So ignoring the warning as stated in the two previous answers stay the best solution I guess – chalasr Feb 07 '17 at 11:57
  • Yes, I know. I've added the answer as this question is shown when looking for the problem in the bundle creation context. But the solutions proposed here are not suitable. So I added the answer so who is looking for a solution in the context of the bundle creation can find it anyway. Is for internal linking... – Aerendir Feb 07 '17 at 12:04