Laravel: Where to store global arrays data and constants?
Asked Answered
F

9

106

I just started working with Laravel. I need to rewrite a whole system I made some years ago, using Laravel 4 as base framework. In my old system, I used to have a constant.php file with some constants declared, and a globals.php file which contained lots of array sets (for example, categories statuses, type of events, langs, etc.). By doing so, I could use something like

foreach ( $langs as $code => $domain ) {
    // Some stuff
}

anywhere in my app.

My question is, how can I store that info in the so called "laravel way". I tried using some sort of object to store this info, setting this as a service and creating for it a facade:

app/libraries/Project/Constants.php

namespace PJ;

class Constants {

    public static $langs = [
            'es' => 'www.domain.es',
            'en' => 'www.domain.us',
            'uk' => 'www.domain.uk',
            'br' => 'www.domain.br',
            'it' => 'www.domain.it',
            'de' => 'www.domain.de',
            'fr' => 'www.domain.fr'
        ];
}

app/libraries/Project/ConstantsServiceProvider.php

namespace PJ;

use Illuminate\Support\ServiceProvider;

class ConstantsServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->singleton('PJConstants', function() {
            return new Constants;
        });
    }
}

app/libraries/Project/ConstantsFacade.php

namespace PJ;

use Illuminate\Support\Facades\Facade;

class ConstantsFacade extends Facade {
    protected static function getFacadeAccessor() { 
        return 'PJConstants';
    }
}

composer.json

"psr-4": {
     "PJ\\": "app/libraries/Project"
},

and so I access that property as PJ\Constants::$langs.

This works, but I doubt it is the most efficient or correct way of doing it. I mean, is it the right way to "propagate" a variable by creating a whole Service Provider and facades and all such stuff? Or where should I put this data?

Thanks for any advice.

EDIT # 01

Data I want to pass to all controllers and views can be directly set in script, like in the example at the beginning of my post, but it can also be generated dynamically, from a database for example. This data could be a list of categories. I need them in all views to generate a navigation bar, but I also need them to define some routing patterns (like /category/subcategory/product), and also to parse some info in several controllers (Like get info from the category that holds X product).

My array is something like:

$categories = [
    1 => ['name' => 'General', 'parent' => 0, 'description' => 'Lorem ipsum...'],
    2 => ['name' => 'Nature', 'parent' => 0, 'description' => 'Lorem ipsum...'],
    3 => ['name' => 'World', 'parent' => 0, 'description' => 'Lorem ipsum...'],
    4 => ['name' => 'Animals', 'parent' => 2, 'description' => 'Lorem ipsum...']
]

Just as an example. Index is the id of the category, and the Value is info associated with the category.

I need this array, also, available in all Controllers and Views.

So, should I save it as a Config variable? How else could I store these data; what would be the best and semantically correct way?

Frodine answered 10/11, 2014 at 22:16 Comment(0)
L
137

For most constants used globally across the application, storing them in config files is sufficient. It is also pretty simple

Create a new file in the app/config directory. Let's call it constants.php

In there you have to return an array of config values.

return [
    'langs' => [
        'es' => 'www.domain.es',
        'en' => 'www.domain.us'
        // etc
    ]
];

And you can access them as follows

Config::get('constants.langs');
// or if you want a specific one
Config::get('constants.langs.en');

And you can set them as well

Config::set('foo.bar', 'test');

Note that the values you set will not persist. They are only available for the current request.

Update

The config is probably not the right place to store information generated from the database. You could just use an Eloquent Model like:

class Category extends Eloquent {
    // db table 'categories' will be assumed
}

And query all categories

Category::all();

If the whole Model thing for some reason isn't working out you can start thinking about creating your own class and a facade. Or you could just create a class with all static variables and methods and then use it without the facade stuff.

Lorca answered 10/11, 2014 at 22:25 Comment(17)
Easy way! Doing it like that is nice for "constant arrays" already set in project code. But what about variables or arrays generated at runtime that I want to globally access from everywhere else. I have some basic start code at global.php, and some variables are created there that i will need after in some controllers or views. Is there a way to set the value of that Config variables, or even create new ones at runtime?Flew
I didn't think it could be so easy. I will mark it as answer, but I have one last doubt about it. One of those variables I need to make globally accessible holds a set of categories taken from the database. It is required for all views as it will be used for the navigation menu, but it is also required in some controllers and even for routing. Is it correct (semantically speaking) to save this type of data as a Config variable? Or should I store it in some other way?Flew
if you post, what is that thing which is needed everywhere, how it is needed, how you accessing it, it will be easier to answer.Cyd
@lukasgeiter, Thanks for your update/reply. Can I handle this through models? This data is parsed after taking it from db, It includes some content even from the Cache. So, a Class and Facade (as I've been doing) for storing data is the proper way?Flew
I would say so yes. You could handle it within your model, but I would do it in its own class...Lorca
app/config directory not exists in Laravel 5.1 right? What to do then?Uis
@Corner since 5.0 the config directory is located directly in the root of your project directory.Lorca
I am using Lumen and i did the same procedure, but getting error 'class config not found' please help.Rozamond
@SachinVairagi This answer is written for laravel, so I can't guarantee this will work, but you can try some things from this thread: laracasts.com/discuss/channels/lumen/…Lorca
This is a bad idea if you have large arrays as these get cached and loaded on all requestsRelate
For people using Laravel 5 or higher you have to add 'use Config;' in your Controller or put a slash in font of Config like this: \Config::get('constants.langs');Isma
In Laravel 5.4 we need to use Config folder constants.phpCranial
You can use the config() helper rather than using Config::get() now.Hapten
I use serviceProvider for storing data available in all laravel views / controllersDermatitis
you can direct use config('constants.langs.en');Mm
I would advise not to do it this way. Those are not constants. They are variables and could be modified. A constant should not be able to be modified during the execution of the program (that's why they're called constants). I suggest the app/constants.php with composer.json method described below, or on this post.Interpret
use Illuminate\Support\Facades\Config; or use Config; should be usedColb
S
32

For Constants

Create constants.php file in the config directory:-

define('YOUR_DEFINED_CONST', 'Your defined constant value!');

return [

'your-returned-const' => 'Your returned constant value!'

];

You can use them like:-

echo YOUR_DEFINED_CONST . '<br>';

echo config('constants.your-returned-const');

For Static Arrays

Create static_arrays.php file in the config directory:-

class StaticArray
{

    public static $langs = [
        'es' => 'www.domain.es',
        'en' => 'www.domain.us',
        'uk' => 'www.domain.uk',
        'br' => 'www.domain.br',
        'it' => 'www.domain.it',
        'de' => 'www.domain.de',
        'fr' => 'www.domain.fr'
    ];

}

You can use it like:-

echo StaticArray::$langs['en'];

Note: Laravel includes all config files automatically, so no need of manual include :)

Suffer answered 25/8, 2016 at 7:25 Comment(1)
Not available in some console commands such as route:cache: Use of undefined constant ID - assumed 'ID'Tortuga
A
20

Create common constants file in Laravel

app/constants.php

    define('YOUR_CONSTANT_VAR', 'VALUE');

    //EX
    define('COLOR_TWO', 'red');

composer.json add file location at autoload in composer.json

"autoload": {
    "files": [
        "app/constants.php"
    ]
}

Before this change can take effect, you must run the following command in Terminal to regenerate Laravel’s autoload files:

composer dump-autoload
Apartheid answered 30/10, 2018 at 12:0 Comment(3)
Thanks for sharing. I had forgotten about the autoloading :DTheis
it's my pleasure @ChannaveerHakariApartheid
How to use public_path() and config function in app/Constants.php in laravel 10 whenever I am trying each time I get error.Bod
S
8

For global constants in Laravel 5, I don't like calling Config for them. I define them in Route group like this:

// global contants for all requests
Route::group(['prefix' => ''], function() {
    define('USER_ROLE_ADMIN','1');
    define('USER_ROLE_ACCOUNT','2');
});
Smokechaser answered 9/6, 2015 at 8:41 Comment(5)
If I have a large number of constants, is there a way to store them in another file(s) and then include them in the route's function? Also, what is the line ['prefix' => ''] doing? I know it's an associative array, but does this make the constants available to all routes? Thanks.Sonasonant
Aha well I figured out the prefix part: laravel.com/docs/5.1/routing#route-group-prefixesSonasonant
Another side note, no matter what I do, it seems like PHPUnit does not like it. When I try it your way, everything works fine on the browser, but PHPUnit is telling me my constants are already defined, and that's simply not true.Sonasonant
If you are caching your configs then defining constants in them will not work.Relate
Great idea to use the prefixTravel
S
5

I think the best way is to use localization.

Create a new file messages.php in resources/lang/en (en because that is what is set in my config/app 'locale'=>'en') return an array of all your values

return [
    'welcome' => 'Welcome to our application'
];

to retrieve for laravel 5.3 and below

echo trans('messages.welcome');

or

echo Lang::get('messages.welcome');

for 5.4 use

echo __('messages.welcome') 

laravel 5.0 localization

or

laravel 5.4 localization

Smolt answered 12/4, 2017 at 9:44 Comment(1)
That's correct. Sub query from a newbie is how to read that message.php file and get the key value as array? I want to read it as array & send as json response for my client side library i.e. Angular JS to handle certain strings.Menefee
T
3

Create a constants class:

<?php
    
    namespace App\Support;
    
    class Constants {
        /* UNITS */
        public const UNIT_METRIC = 0;
        public const UNIT_IMPERIAL = 1;
        public const UNIT_DEFAULT = UNIT_METRIC;
    
    }

Then use it in your model, controller, whatever:

<?php

namespace App\Models;

use App\Support\Constants;

class Model
{
  public function units()
  {
      return Constants::UNIT_DEFAULT;
  }
}
Transfigure answered 21/12, 2021 at 3:8 Comment(0)
A
2

Just to add to the above answer you will have to include the config class before you could start using it in Laravel 5.3

use Illuminate\Support\Facades\Config;
Amphithecium answered 6/2, 2017 at 18:0 Comment(1)
Or simple use the function config().Yeaton
W
2

Atleast in Laravel 5.4, in your constructor you can create them;

public function __construct()
{
  \Config::set('privileged', array('user1','user2');
  \Config::set('SomeOtherConstant', 'my constant');     
}     

Then you can call them like this in your methods;

\Config::get('privileged');

Especially useful for static methods in the Model, etc...

Reference on Laracasts.com https://laracasts.com/discuss/channels/general-discussion/class-apphttpcontrollersconfig-not-found

Whicker answered 10/8, 2017 at 17:34 Comment(0)
D
0

Just put a file constants.php file into the config directory and define your constants in that file, that file will be auto loaded, Tested in Laravel 6+

Dorri answered 16/6, 2020 at 18:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.