Search code examples
phpsymfonyvariablesglobal-variablessymfony4

Variables that can be used in the whole symfony app? - Symfony 4


So right now I'm developing an app in Symfony4 where the users can create files with one parameter that can be chosen between a variety of options (these options being already defined), for example:

Year = [2020,2019,2018,2017];
Type = ['A','B','C'];
User = [
  'User' => 'ROLE_USER',
  'Admin' => 'ROLE_ADMIN',
  'Guest' => 'ROLE_GUEST',
];

And I would like that the admin could change this variables by adding a new year or adding a new type of file. So I thought that this could be achievable by creating a global variable for the whole app (a variable that can be accessed from everywhere) in order to use it in the forms, views, etc. But I dont know how to do it. I think I could do it in two ways:

  • Creating a specific table in the db for these parameters, this way using doctrine to fetch the data and being able to updating it easily. (One more call to the database every time I want to use it)
  • Or creating a global variable as I said before that I can access everytime I want

What should I do? Is there any other easier way to achieve this?

Thank you very much in advance


Solution

  • Usually I save these values in a table "settings" and use the cache so I don't have to make calls to the database every time I need to use them.

    • Create entity Settings, it will have 3 properties : years, types, users. (they can be json type)
    • I manually create 1 raw in the database and add the values, and the admin has a form to update these values
    • I create a SettingCache class, and every time the admin submits the form, the values change, so I clear the cache : $settingCache->clear().
    • The next time I call $settingCache->getSetting('years') it will call the database to fetch the new values and rebuild the cache.

    App\Cache\SettingCache

    namespace App\Cache;
    
    use App\Repository\SettingRepository;
    use Psr\Cache\InvalidArgumentException;
    use Symfony\Contracts\Cache\CacheInterface;
    
    /*
     * Cache keys:
     *  - settings
     */
    class SettingCache
    {
        private $cache;
        private $settingRepository;
    
        public function __construct(
            CacheInterface $cache,
            SettingRepository $settingRepository
        ) {
            $this->cache = $cache;
            $this->settingRepository = $settingRepository;
        }
    
        public function getSettings(): array {
            return $this->cache->get('settings', function() {
                return $this->settingRepository->findAllToArray();
            });
        }
    
        public function getSetting(string $key) {
            $settings = $this->getSettings();
            return $settings[$key] ?? null;
        }
    
        public function clear(): void {
            $this->cache->delete('settings');
        }
    }
    
    

    App\Repository\SettingRepository.php

    public function findAllToArray() {
        return $this->createQueryBuilder('s')
            ->where('s.id = 1')
            ->getQuery()
            ->getOneOrNullResult(AbstractQuery::HYDRATE_ARRAY);
    }
    

    That's it !
    But because I also want to access these values in twig easily, I create a TwigFunction :

    App\Twig\SettingExtension

    namespace App\Twig;
    
    use App\Cache\SettingCache;
    use Twig\Extension\AbstractExtension;
    use Twig\TwigFunction;
    
    class SettingExtension extends AbstractExtension
    {
        private $settingCache;
    
        public function __construct(SettingCache $settingCache) {
            $this->settingCache = $settingCache;
        }
    
        public function getFunctions(): array
        {
            return [
                new TwigFunction('setting', [$this, 'getSetting']),
            ];
        }
    
        public function getSetting(string $key) {
            return $this->settingCache->getSetting($key);
        }
    }
    

    So I can call it in a template like

    {% for year in setting('years') %}
        {{ year }}
    {% endfor %}