I am writing a web service using Lumen and need to store some constants, specifically error values, but also other configuration parameters. Where would it be most appropriate to put these?
Here is how I did it.
I made a const.php file within bootstrap folder where I have defined some error codes.
<?php
define('VALIDATION_EXCEPTION',422);
I included the const.php file in app.php using require_once.
<?php
require_once __DIR__.'./const.php';
Now I can call VALIDATION_EXCEPTION from anywhere. for instance.
$router->get('/test',function(){
return VALIDATION_EXCEPTION;
});
That's it!
Create a file constants.php inside config/ and put your settings in an array:
<?php
return [
'CONTACT_NAME' => 'Admin'
];
Then in your controllers you can get the value by using Config Facade:
echo Config::get('constants.CONTACT_NAME');
This solution was from this link
.env is intended for per-environment configuration and sensitive credentials.
You can maintain a config with this type of data. There is no default config for Lumen like there is for Laravel, so you need to add the required config directory, and tell Lumen to use it:
$ mkdir config
$ touch config/app.php
In the app.php file, you can return an array with the config:
// config/app.php
<?php
return [
'order_by' => 'whatever'
// and so on
];
Then tell Lumen to load the config from app.php inside bootstrap/app.php, by adding (after $app has been initialised):
$app->configure('app');
Finally, you can use the config() helper method to get the configuration:
config('app.order_by') // whatever
1.Create New Directory Helpers under App Directory.
2.Create New php file ErrorCodes.php under Helpers directory
3.Put your constants in that file
<?php define('VALIDATION_ERROR', 'E001'); define('EXCEPTION', 'E002'); define('CUSTOM','E003'); ?>
4.Add this ErrorCodes file under autoload section of composer.json
"files" : [
"app/Helpers/ErrorCodes.php"
]
5.Run composer autoload command in your artisan terminal
composer dumpautoload
And you are all set to use your constants anywhere in your lumen App.
Seems like you are talking about two different things here. For configuration values the only correct location is the .env file (as already mentioned in the comments).
https://lumen.laravel.com/docs/5.5/configuration#environment-configuration
This is where you put all environmental specific configuration values (e.g. API keys, debug mode, etc. etc.). If you have a strong wish for it you can put the env-variables into constants during the bootstrap process e.g.:
define('APP_DEBUG',env('APP_DEBUG', true));
For defining simple constants there should be multiple possibiilties.
You could do this either during the bootstrap process or define a class (e.g. a model):
class Error
{
const FATAL = 1;
const WARNING = 2;
}
use Error;
....
Error::FATAL;
...
Related
I need to load a different .env file, named .env.test under certain conditions.
I attempted to do that through a middleware by adding
app()->loadEnvironmentFrom('.env.test');
Dotenv::create(base_path(), '.env.test')->overload();
to the bootstrap() method of Kernel.php. I also tried to create a dedicated middleware for this and load it as the first one in the web middleware group. But either way, it is loading the standard .env file.
It works if I do it in the /bootstrap/app.php file but I really don't want to put it there.
I just figured it out: The default .env file is being loaded inside of the bootstrap() method of LoadEnvironmentVariables.php.
To use the .env.test file I had to restructure my initial bootstrap() method inside of the App/Http/Kernel.php file to look like this:
public function bootstrap()
{
app()->loadEnvironmentFrom('.env.test');
parent::bootstrap();
}
So the essential part was to move the parent::bootstrap() call below the loadEnvironmentFrom() call.
Instead of doing any code change, you can use export command create a file called .env.test, you want to sue this as .env file use terminal
APP_ENV=local
php artisan config:cache
php artisan key:generate
This below edit is to explain how .env file is getting set
In Illuminate\Foundation\Application class has method loadEnvironmentFrom which is taking the file as parameter and setting it,
you can use bootstrap/app.php after you are getting $app
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
here you will be having instance of Illuminate\Foundation\Application
you can just call the loadEnvironmentFrom function like
$app->loadEnvironmentFrom('.env.local');
May be it is better to use Kernel.php instead of this, I do not think either of bootstrap/app.php or kernel.php will get overridden with composer update, so make more calculation while using it. I have added this, so that it will help you understand the stuffs.
You can load a different environment file using APP_ENV
For example if APP_ENV=test then .env.test can be loaded.
More info: https://github.com/laravel/framework/blob/6.x/src/Illuminate/Foundation/Bootstrap/LoadEnvironmentVariables.php#L41
I would like to access single laravel application by multiple domain.
For routing i have used laravel route pattern for eg.
$appRoutes = function() {
Route::group(['namespace'=>"Interface1"], function(){
/** route for index page and User authentication pages **/
Route::get('/', 'LoginController#showLoginForm')->name('login');
});
};
Route::group(array('domain' => 'example1.com'), $appRoutes);
Route::group(array('domain' => 'example2.com'), $appRoutes);
Now .env for each domain i have replaced config variable value inside AppServiceProvider.php register method:
if(isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST']) ){
if($_SERVER['HTTP_HOST']=='example1.com'){
$configArray = [
'APP_NAME' => 'Application 1',
'APP_URL' => 'http://example1.com',
];
}else{
$configArray = [
'APP_NAME' => 'Application 2',
'APP_URL' => 'http://example2.com,
];
}
config($configArray);
}
but still i am not getting correct domain url using url(config('app.url'))
How to load all .env variable overwrite for each domain?
For the current Laravel 7.x. at the time of writing this, you can add the following code in your bootstrap/app.php file just before return $app statement.
// bootstrap/app.php
// ...
/*
|-----------------------------------------------
| Load domain-specific .env file if it exists
|-----------------------------------------------
*/
if(isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST'])){
$domain = $_SERVER['HTTP_HOST'];
}
if (isset($domain)) {
$dotenv = Dotenv\Dotenv::createImmutable(base_path(), '.env.'.$domain);
try {
$dotenv->load();
} catch (\Dotenv\Exception\InvalidPathException $e) {
// No custom .env file found for this domain
}
}
// ...
return $app;
Next, you should have a .env file for each domain in the following format .env.example1.com .env.example2.com. You can leave the original .env as a fallback for domains that lack an explicit .env file.
For Laravel 5.x or Laravel 6.x, you can find more from the original solution.
config() sets the configuration settings but not the environment settings.
You have to do the following:
if(isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST']) ){
if($_SERVER['HTTP_HOST']=='example1.com'){
$configArray = [
'app.name' => 'Application 2',
'app.url' => 'http://example2.com',
]; ;
}else{
$configArray = [
'app.name' => 'Application 2',
'app.url' => 'http://example2.com',
];
}
config($configArray);
}
You can then retrieve the values via:
config("app.name");
config("app.url");
As far as I know there is no way to modify the environment variables before the configuration is actually loaded, because the configuration is loaded and reads the environment variables before the service providers are registered.
Also betware of using HTTP_HOST as it's a client-set header and may not be reliable.
A simple solution is here Laravel Multi Domain Package
This package allows a single Laravel installation to work with multiple HTTP domains.
There are many cases in which different customers use the same application in terms of code but not in terms of database, storage and configuration.
This package gives a very simple way to get a specific env file, a specific storage path and a specific database for each such customer.
Installation steps
Add gecche/laravel-multidomain as a requirement to composer.json:
{
"require": {
"gecche/laravel-multidomain": "4.*"
}
}
Update your packages with composer update or install with composer install.
You can also add the package using composer require gecche/laravel-multidomain and later specify the version you want (for now, dev-v1.1.* is your best bet).
This package needs to override the detection of the HTTP domain in a minimal set of Laravel core functions at the very start of the bootstrap process in order to get the specific environment file. So this package needs a few more configuration steps than most Laravel packages.
Installation steps:
replace the whole Laravel container by modifying the following lines at the very top of the bootstrap/app.php file.
//$app = new Illuminate\Foundation\Application(
$app = new Gecche\Multidomain\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
update the two application Kernels (HTTP and CLI).
At the very top of the app/Http/Kernel.php file , do the following change:
//use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Gecche\Multidomain\Foundation\Http\Kernel as HttpKernel;
Similarly in the app/Console/Kernel.php file:
//use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Gecche\Multidomain\Foundation\Console\Kernel as ConsoleKernel;
Override the QueueServiceProvider with the extended one in the $providers array in the config/app.php file:
//Illuminate\Queue\QueueServiceProvider::class,
Gecche\Multidomain\Queue\QueueServiceProvider::class,
publish the config file.
php artisan vendor:publish
Usage
This package adds three commands to manage your application HTTP domains:
domain.add artisan command
The main command is the domain:add command which takes as argument the name of the HTTP domain to add to the application. Let us suppose we have two domains, site1.com and site2.com, sharing the same code.
We simply do:
php artisan domain:add site1.com
and
php artisan domain:add site2.com
These commands create two new environment files, .env.site1.com and .env.site2.com, in which you can put the specific configuration for each site (e.g. databases configuration, cache configuration and other configurations, as usually found in an environment file).
The command also adds an entry in the domains key in config/domains.php file.
In addition, two new folders are created, storage/site1_com/ and storage/site2_com/. They have the same folder structure as the main storage.
Customizations to this storage substructure must be matched by values in the config/domain.php file.
domain.remove artisan command
The domain:remove command removes the specified HTTP domain from the application by deleting its environment file. E.g.:
php artisan domain:remove site2.com
Adding the force option will delete the domain storage folder.
The command also removes the appropriate entry from, the domains key in config/domains.php file.
domain.update_env artisan command
The domain:update_env command passes a json encoded array of data to update one or all of the environment files. These values will be added at the end of the appropriate .env.
Update a single domain environment file by adding the domain option.
When the domain option is absent, the command updates all the environment files, including the standard .env one.
The list of domains to be updated is maintained in the domain.php config file.
E.g.:
php artisan domain:update_env --domain_values='{"TOM_DRIVER":"TOMMY"}'
will add the line TOM_DRIVER=TOMMY to all the domain environment files.
domain.list artisan command
The domain:list command lists the currently installed domains, with their .env file and storage path dir.
The list is maintained in the domains key of the config/domain.php config file.
This list is automatically updated at every domain:add and domain:remove commands run.
config:cache artisan command
The config:cache artisan command can be used with this package in the same way as any other artisan command.
Note that this command will generate a file config.php file for each domain under which the command has been executed. I.e. the command
php artisan config:cache --domain=site2.com
will generate the file
config-site2_com.php
Please visit the repository for more information
I have a Lumen project with external Composer packages installed. As usual with Lumen, they're stored in the vendor directory, each in their respective folder. Some of these packages have configuration files, which I would like to override with custom ones.
I have registered the files in my bootstrap/app.php using $app->configure() right after I register the application itself, so it looks like this:
require_once __DIR__ . '/../vendor/autoload.php';
try {
(new Dotenv\Dotenv(__DIR__ . '/../'))->load();
} catch (Dotenv\Exception\InvalidPathException $e) {
//
}
$app = new Laravel\Lumen\Application(
realpath(__DIR__ . '/../')
);
$app->withFacades();
$app->withEloquent();
$app->configure('/Configuration/Lumen/app.php');
$app->configure('/Configuration/Lumen/auth.php');
$app->configure('/Configuration/Tymon/jwt.php');
The files are present in their respective directories, and contain the settings I want Lumen to use instead of the defaults, which are located, respectively, at:
/vendor/laravel/lumen-framework/config/app.php
/vendor/laravel/lumen-framework/config/auth.php
/vendor/tymon/jwt-auth/config/config.php
The problem I run into is that with this configuration, Lumen seems to ignore my custom files, and instead uses the defaults. What am I doing wrong here?
Put your configuration files in config/ and register them in bootstrap/app.php by their filename, without the .php file ending.
// Your custom config in config/jwt-auth.php
$app->configure('jwt-auth');
I don't think any of the above answers is truly answering what the OP wanted to know how to do.
What they appear to want, is to load a composer package and register that packages configuration into the app without having to do any kind of manual configuration.
Sort of like when you import a standard composer package which builds a logger using environment variables and autoconfigures its setup without having to add that configuration to the app. So then things are simpler.
Although I'm assuming the OP knows that this leads to a few problems, in that you're stuck with a composer package configuring your app, with a few options to override those settings locally.
But I assume you're happy with that. So therefore, I'd like to propose this solution
In your composer package, create a providers folder, then add this code into a lumen service provider class, in my case I've called it TestProvider
<?php declare(strict_types=1);
namespace YourLibrary\Providers;
class TestProvider extends \Illuminate\Support\ServiceProvider
{
public function boot()
{
// Because we're using 'require', this needs to be a valid path
$path = __DIR__.'/vendor_config.php';
// Get a configuration object from the service container
$config = app()->make('config');
// An example: Set into the 'app' configuration at a specific subkey
// just to show you can modify the default app configuration
$config->set('app.subkey', require $path);
error_log(json_encode(config('app')));
// An example: Set into the 'vendor.test' configuration at a specific subkey
$config->set('vendor.test', require $path);
error_log(json_encode(config('vendor')));
}
}
As you can see, you can use the dot notation for the first parameter to set() to insert your configuration into the applications config, but be careful with the naming cause in theory I guess you could override any setting like this, it could be that you end up overwriting the entire config('app') and all it's settings which would lead to a partially non-functioning app.
Then inside your bootstrap.php file in your app, you need to register this service provider, like so:
$app->register(YourLibrary\Providers\TestProvider::class);
I've tested it with an app I was working on locally and this works and I'm already using it for a library that has a very static configuration, everything is working pretty great.
I'm planing to do something like, specifying what env file to load during application bootstrap time by creating a variable in .env.master such as ENV_VER = dev.env
This is because I have several branches such as development, release-1.1 and etc. Thus by loading the env file based on the name specified in a master env file, developers no longer have to copy and paste new variables into their local copy of .env and instead, just specify what version of env file to load in the master env file. By the way, I have several env files such as dev.env, 1.6.env etc.
Is it possible?
Definitely, me myself I tend to "bend" a framework little bit everytime and there's always a way, not always the best solution though. I'm not giving a whole implementation here, just pointing you in some direction, that might work for you.
You can extend Laravel's base application class Illuminate\Foundation\Application, which contains $environmentFile variable storing environment file loaded during appplication bootstrap or possibly override function loadEnvironmentFrom($file) or environmentFile(). The whole logic is up to you.
So basically all you need to do in order to be able to "play" with .env loading is...
Create a new application class extending Laravel's one:
namespace MyNamespace;
...
use Illuminate\Foundation\Application as App;
/**
* I'm doing alots of magic with .env in this class
*/
class Application extends App
{
...
/**
* The environment file to load during bootstrapping.
*
* #var string
*/
protected $environmentFile = '.env.main';
...
}
And now, because we have a new bootstraping class, we have to tell Laravel we want to use it. So you'll have to modify bootstrap/app.php file in point where a new instance is being created:
...
$app = new MyNamespace\Application(
realpath(__DIR__.'/../')
);
...
Note: For inspiration I recommend you to really look at Illuminate\Foundation\Application class.
In laravel 5.5+ you can, maybe earlier, you can set your server have a APP_ENV environment or server variable that the process can see (apache, command line...)
this will allow you to use a suffix or file extension on your .env files for auto loading those files...
APP_ENV=dev :: .env.dev
APP_ENV=production :: .env.production
much easier than other solutions.
If you want to look into how this is done, it starts with
1. application bootstrappers
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
2. LoadEnvironmentVariables
first the environment is determined…
\Illuminate\Foundation\Bootstrap\LoadConfiguration::bootstrap calls
\Illuminate\Foundation\Application::detectEnvironment
If
--env={env} for CLI then it will use that for APP_ENV.
Else
\Illuminate\Foundation\EnvironmentDetector::detectWebEnvironment
is called which uses a callback…
function () use ($config) {
return $config->get('app.env', 'production');
}
where app.env defaults to env('APP_ENV', 'production')
3 LoadConfiguration
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::bootstrap calls...
\Illuminate\Foundation\Application::afterLoadingEnvironment
which eventually gets to
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::checkForSpecificEnvironmentFile
which sets the environment file based on app env IF the file exists.
$this->setEnvironmentFilePath(
$app, $app->environmentFile().'.'.env('APP_ENV')
);
allowing it to load the .env.{APP_ENV} instead of .env
NOTE: Testing.
when running php unit tests. the Illuminate/Foundation will try to load the .env.testing file for configurations!
I have created a file called db-constant.php in conifg directory in laravel , this file contains my constants,then i added this line require_once 'db-constants.php'; in app.php ,the problem is where i type php artisan cache:clear or any command this message will appear
PHP Notice: Constant FLD_EMAIL already defined in /var/www/html/test/config/db-constants.php on line 1
how can i fix this ?
If you use Laravel, you don't have to use require_once or it's counterparts. composer's autoloading is used for everything, and configuration files are loaded automatically. What you have to do is read the docs about configuration, place the file in config/ directory and return an array with configuration values.
Now, what it seems (to me at) is that for some odd reason you want to use constants instead of Laravel's mechanism for accessing configuration values. In that case, you:
1.) DON'T place anything in config/ directory
2.) DON'T manually require_once anything
3.) DO use Composer's autoloading capabilities
How to load a file with constants in Laravel
1.) create app/MyConstants directory.
2.) create your file, let's call it constants.php. Path is:
app/MyConstants/constants.php
3.) Add your define code
4.) Open composer.json
5.) Find "autoload"
6.) Look for "files" under "autoload". If it doesn't exist, create it.
7.) Add the list of files you want to include automatically
Your "autoload" in composer.json should look like this:
"autoload": {
"files": ["app/MyConstants/constants.php"]
}
In terminal, type composer du or composer dump-autoload. It will re-create autoloader and automatically include the file with your constants.
Remove bootstrap/cache so you can use artisan again.
Now you can:
1.) Have a place where you can define constants
2.) Avoid manually requiring files
Personally, I don't see a reason for this, but then again - I'm just a human, I've no clue about anything in the grand scheme :)
You need to read this docs first https://laravel.com/docs/5.4/configuration. As well as the rest of the documentation for Laravel. How to use config files:
Create your own file db-constant.php in config directory.
Fill it as you need. For example
return [
'FLD_EMAIL' => 'your-field-here',
];
Use it wherever you need
$email = config('db-constant.FLD_EMAIL');
It's all.