3

I'd like to use a simple function in Symfony 4, something like this :

src/Service/Utils.php

<?php

namespace App\Service;

/**
 * @param string $attr
 *
 * @return bool
 */
function attributNilTrue($attr): bool
{
    return json_encode($attr) === '{"@attributes":{"nil":"true"}}';
}

some/other/file.php

use function App\Service\attributNilTrue;

if (attributNilTrue($foo['bar'])) {
    // Do something...
}

But I get the following error:

The autoloader expected class "App\Service\Utils" to be defined in file "/var/www/interop/vendor/composer/../../src/Service/Utils.php". The file was found but the class was not in it, the class name or namespace probably has a typo.

Is there a way to do that without having to create a Utils class?

yivi
  • 42,438
  • 18
  • 116
  • 138
Baptiste Costa
  • 1,044
  • 1
  • 12
  • 24
  • 2
    Basically no. Php does not support autoloading for functions. A static class function is really your best bet. Or figure out the best spot to use a require statement. – Cerad Jul 11 '19 at 15:47

2 Answers2

4

You could use the autoloader files key in composer.

In your composer.json file include something like this:

{
    "autoload": {
        "files": ["src/utility_functions.php"]
    }
}

(where src/utility_functions.php is a file containing your function definitions).

Dump your autoloader (composer dump-autoload) so this is incorporated into your autoloader files, and whatever functions you define in this file will be available on each request.

Your typical Sf4 will already include a PSR4 entry there, so you will have to add your own. The end result would look more or less like this:

"autoload": {
    "psr-4": {
      "App\\": "src/"
    },
    "files": [
      "src/utility_functions.php"
    ]
  },
yivi
  • 42,438
  • 18
  • 116
  • 138
0

I would recommend to wrap such functions in class - for example:

namespace App\Service;

class Utils
{
    /**
     * @param string $attr
     *
     * @return bool
     */
    public static function attributNilTrue($attr): bool
    {
        return \json_encode($attr) === '{"@attributes":{"nil":"true"}}';
    }
}

If you have autoloading configured for that directory then it should be loaded automatically - otherwise add service definition like this:

App\Service\Utils:

Then you can use it like:

use App\Service\Utils;

...

if (Utils::attributNilTrue($foo['bar'])) {
    // Do something...
}

This way:

  1. Your class is correctly defined according to PSR4 (https://www.php-fig.org/psr/psr-4/) :

    2.3.3:
    The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
    
  2. You dont need to mess with composer.

  3. When in future you will need some dependecies inside those functions/methods then you can easily inject them because it is a service.
domis86
  • 1,227
  • 11
  • 9