Accessing new Laravel config files during request - php

I have a scenario where Laravel config files are created and accessed during the same incoming request. However, when accessing the new stored config file's values, config() is unable to access the file's keys/values.
Here is an example scenario:
public function create(Request $request)
{
$settings = ['foo' => 'bar'];
// Store the config.
Storage::disk('config')->put("settings.php", '<?php return ' . var_export($settings, true) . ';');
// Results in an error, value not found.
$config_value = config('settings.foo');
}
Is there a way to re-register Laravel config files during a runtime?

Saving contents to the php file config/settings.php is (obviously) not the best way to do it.
Either save the config to a database, or simply use the config() helper to assign the values like this:
class MyConfigProvider extends ServiceProvider
{
public function boot() {
$this->app->booted(function () {
// This will set the config setting `config/settings.php['app_name']` at runtime:
config([
'settings.app_name' => 'My App Name'
]);
});
}
}
Then, make sure to load this service provider as early in the stack as possible in your config/app.php['providers'] array. Basically it overwrites any predefined config that you have set in config/settings.php. You can even retrieve values here from the request object or your database.

Yes there is a method for that:
config()->set('settings.foo', $somethingNew);
and then you can read it normally with:
$config_value = config('settings.foo');

Related

How to save data on server without using database?

I have an application developed with Laravel. My software has settings that are used globally and should be available in all controllers (such as default information). I take this information from the database in the main controller every time a request is sent and save it in a variable.
namespace App\Http\Controllers;
class Controller extends BaseController
{
protected $config;
public function __construct()
{
$this->config= DB::table('config')->get();
}
}
Is there a way to save and use this information without the intervention of a database? I don't want to use sessions.
It is better if a solution is introduced using laravel packages.
Thanks
Assuming that you collection doesn't hold a lot of data, you can always put it inside your custom config. Create a php file inside your app/config directory, where you can put all your values like this:
<?php
return [
'key1' => value1,
'key2' => value2,
];
You can create any data structure here that you might need. Now, when you need to read single key from this data, you can use Laravel's config() helper:
$config = config('config_name.key');
If you want to get whole collection of the data, you can do it with the same config() helper, like this:
$config = config('app.config_name');
Hope that I understood your question right, and that this can lead you in right direction. You can read more about config on official documentation.

Access variables in other files without setting them as globals

I want to have one class that works with configuration settings. Configuration settings are stored inside config/ directory where I want them to be separated to files. When I call my
Config::gi()->getConfig('config_name')
I want the Config class to be able to access the file config/config_name.cfg.php and return the array (from that file) named exactly the same.
This is because I don't want to read all the configuration data if it's not needed. Also, I'm a bit afraid that setting up configuration inside $GLOBALS variable wouldn't be the best solution. I thought about requiring or including those files and then returning their content, but it also seems a bit unprofessional.
What is the best practice to read the configuration like this? Thank you in advance.
For example:
config/routes.cfg.php
$routes => [
'index' => new Route([
// route config here ...
])
];
and to get the routes array I would execute Config::gi()->getConfig('routes'); from helpers/Config.php class.
I'm not sure I would go this route, I would probably load all configs (most likely from a single file) into the class the first time and go from there. Also you can look at parse_ini_file() if you don't want to write out arrays when they change. But for your case, simply:
public function getConfig($name) {
if(file_exists("config/$name.cfg.php")) {
include("config/$name.cfg.php");
return ${$name}; //this translates to $routes in your example
}
return false;
}
Also, the next logical question might be how to save the config when it changes:
public function setConfig($name, $data) {
file_put_contents("config/$name.cfg.php", "$name = " . var_export($data, true) . ";");
}
$routes = array(/* with some stuff in it */);
Config::gi()->setConfig('routes', $routes);

Laravel dynamic config settings

I'm using a package within my project and it stores a setting inside config/packagename
I would like to dynamically change this value inside the config file, this is how the file structure looks currently;
<?php
return [
'view_id' => '118754561',
'cache_lifetime_in_minutes' => 60 * 24,
];
I would like to change it to something like this -
'view_id' => Auth::user()->id,
Can you do this within the config file, or do you have to store some sort of variable to be updated later within a controller. Is there a way to place these variables in an env file and access these new variables from a controller?
This also is a generic solution to dynamically update your .env file (respective the individual key/value pairs)
Change the setting in your config/packagename like so:
return [
'view_id' => env('VIEW_ID', '118754561'),
etc...
]
Add an initial value into .env:
VIEW_ID=118754561
In an appropriate controller (e.g. AuthController), use the code below and call the function like this:
updateDotEnv('VIEW_ID', Auth::User()->id)
protected function updateDotEnv($key, $newValue, $delim='')
{
$path = base_path('.env');
// get old value from current env
$oldValue = env($key);
// was there any change?
if ($oldValue === $newValue) {
return;
}
// rewrite file content with changed data
if (file_exists($path)) {
// replace current value with new value
file_put_contents(
$path, str_replace(
$key.'='.$delim.$oldValue.$delim,
$key.'='.$delim.$newValue.$delim,
file_get_contents($path)
)
);
}
}
(The $delim parameter is needed if you want to make this function more generic in order to work with key=value pairs in .env where the value has to be enclosed in double quotes because they contain spaces).
Admittedly, this might not be a good solution if you have multiple users at the same time using this package in your project. So it depends on what you are using this package for.
NB: You need to make the function public of course if you plan to use it from other classes.
All configuration files of Laravel framework stored in the app/config directory.
so if we need to create custom configuration values it would be better to keep separate our custom configuration in custom file.
so we need to create custom file in app/config directory.
Laravel auto read this file as a config file and will auto manage it
In this topic we are working with custom configuration in laravel and get configuration value in controller or view.
Now i am going to explain how to create a custom config file in Laravel so that we can implement dynamic feature over to this.
create a file in app/config/custom.php which have config keys and value like:-
return array(
'my_val' => 'mysinglelue',
'my_arr_val' => array('1', '2', '3'),
);
Now need to get these config values in view/controller so we will use Config class get() method for this
Syntax:
echo Config::get('filename.arraykey');
where filename is the config file’s name, custom in our case, and key is the array key of the value you’re wanting to access.
In Our case it will be as:
echo Config::get('custom.my_val');
Create run time configuration in laravel :-
Configuration values which are set at run-time are will set for the current request, not be carried over to subsequent requests.
You can pass the dynamic values over here so that you can modify the config file dynamically over here using the isset() functions.
Like how the #Kundan roy as suggested using of the isset() the same condition applies here to. But this one is the alternative method that will work for the dynamic setting of the values in the config.
Config::set('custom.my_val', 'mysinglelue');
Hence by using this method you can create the dynamic config files based on the values that you need.
Since Laravel v5.2 you can dynamically set config values this way:
<?php
config(['app.timezone' => 'America/Chicago']);
$value = config('app.timezone');
echo $value;
// output: 'America/Chicago'
If you want to actually edit the config files (either config/packagename.php or .env) then you may follow matthiku's answer.
However, if I were you, I guess I'd rather want to configure this 3rd party package based on some value defined at runtime, instead of modifying any file (which by the way won't take effect until the next request, when the env values are read again).
So, in my opinion the cleanest way to do this is:
store your desired value in the config data:
config(['packagename.view_id' => Auth::user()->id]);
However, you may notice this probably won't work: the service provider which provides the service you need is often registered before the request is processed, that is, before your config change takes place. So you are still getting the service with old values config.
So, how could you have the service provider be called only when needed and not before (that is, after setting the new config value)? You could make it a deferred provider. Following your example of "spatie laravel-analytics", replace in config/app.php this line:
Spatie\Analytics\AnalyticsServiceProvider::class
with this one:
App\Providers\AnalyticsDeferredServiceProvider::class
and finally create the App\Providers\AnalyticsDeferredServiceProvider class, with:
:
<?php
namespace App\Providers;
use Spatie\Analytics\Analytics;
use Spatie\Analytics\AnalyticsServiceProvider;
class AnalyticsDeferredServiceProvider extends AnalyticsServiceProvider
{
protected $defer = true;
public function provides()
{
return [Analytics::class];
}
}
This way you can have the provider read the config values when you are about to instantiate the service, after you set any runtime config values.
Use this in controller when you need to change.
<?php
use Illuminate\Support\Facades\Config;
//[...]
$user_id = Auth::user()->id;
Config::set('view_id', $user_id );
You can do like this.
In your custom config file. Add the following code You can send your id dynamically from the query string.
'view_id' => isset($_REQUEST['view_id'])?$_REQUEST['view_id']:null,
To get view id
echo config('app.view_id'); // app is config file name
config(['packagename.view_id' => Auth::user()->id]);
Actually if you are that point of code which forces you to make the config values dynamic, then there should be something wrong with your code flow, as the use of config file is just for initializing required values - which should be defined before the app is loaded.
Making config values dynamic is a "BAD PRACTICE" in the world of coding.
So there is the following alternative for your problem.
Define value in .env file (optional)
VIEW_ID=your_view_id_here
Use value inside Controller
$auth_id = auth()->user()->id;
$view_id = env('VIEW_ID', $auth_id);
// If .env file doesn't contains 'VIEW_ID' it will take $auth_user as the view_id
Hope this helps you!
config::set() doesn't works for me in laravel 8. but I got best answer for Create or edit Config file
config(['YOUR-CONFIG.YOUR_KEY' => 'NEW_VALUE']);
$text = '<?php return ' . var_export(config('YOUR-CONFIG'), true) . ';';
file_put_contents(config_path('YOUR-CONFIG.php'), $text);
just try this way this works for me.
original answer you can see here

How to make custom configuration file in Laravel 5.2 that fetches specific data from database?

I'm newbie and I'm learning laravel 5.2, I have a blog that I'm making with laravel and I have a table in the database called "settings" and Here's the migration file of it:
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('site_name');
$table->text('site_description');
$table->string('about_head');
$table->text('about_description');
$table->text('about_body');
$table->timestamps();
});
}
I entered data to this table, now I wanna pass these data to all controllers and all methods.
I found that the best way to do that is to make a custom configuration file on App\Config folder.
So I made a file called "custom" and I tried to access the database to get data from settings table and here's the custom config:
<?php
use Illuminate\Support\Facades\Config;
use App\Setting;
$setting = Setting::find(1);
return array(
'site_name' => $setting->site_name,
'site_description' => $setting->site_description,
'about_head' => $setting->about_head,
'about_description' => $setting->about_description,
'about_body' => $setting->about_body,
);
But I got that error on my laravel root directory
Fatal error: Call to a member function connection() on null in C:\xampp\htdocs\myblog\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php on line 3280
Have any idea how to fix it? or at least do you know another solution to pass my site settings data to all controllers, methods and views?
Thanks for your time.
Maybe adding the Connection Facade will resolve this issue -
<?php
use Illuminate\Database\Connection;
use Illuminate\Support\Facades\Config;
use App\Setting;
$setting = Setting::find(1);
return array(
'site_name' => $setting->site_name,
'site_description' => $setting->site_description,
'about_head' => $setting->about_head,
'about_description' => $setting->about_description,
'about_body' => $setting->about_body,
);
It seems your model can't connect to the database, that's your main problem.
I don't think query inside config file will work. What you can do is to create a service provider and use singleton. Create service provider:
php artisan make:provider MyConfigServiceProvider
Bind singleton:
$this->app->singleton('myconfig', function ($app) {
return new MyConfig();
});
Use it:
$siteName = App::make('myconfig')->getConfig('site_name');
I would suggest NOT to use database when you're using config.
What I generally do is create a config file inside config folder (just like what you are doing) and hard code those values inside that config file.
P.S if your setting values are environment specific then put those values in env file and read those values in your config file

Set session variable in laravel

I would like to set a variable in the session using laravel this way
Session::set('variableName')=$value;
but the problem is that I don't know where to put this code, 'cause I would like to set it for one time (when the guest visite the home page or any other page)?
The main idea is to use a global variable to use it in all application controllers, I heared about something related to configuration variables but I'm not sure if it will be a good Idea to use config variables or only the session?
Thanks
The correct syntax for this is:
Session::set('variableName', $value);
For Laravel 5.4 and later, the correct method to use is put:
Session::put('variableName', $value);
To get the variable, you would use:
Session::get('variableName');
If you need to set it once, I'd figure out when exactly you want it set and use Events to do it.
For example, if you want to set it when someone logs in, you'd use:
Event::listen('auth.login', function() {
Session::set('variableName', $value);
});
I think your question ultimately can be boiled down to this:
Where can I set a long-lived value that is accessible globally in my application?
The obvious answer is that it depends. What it depends on are a couple of factors:
Will the value ever be different, or is it going to be the same for everybody?
How long exactly is long-lived? (Forever? A Day? One browsing 'session'?)
Config
If the value is the same for everyone and will seldom change, the best place to probably put it is in a configuration file somewhere underneath app/config, e.g. app/config/companyname.php:
<?php
return [
'somevalue' => 10,
];
You could access this value from anywhere in your application via Config::get('companyname.somevalue')
Session
If the value you are intending to store is going to be different for each user, the most logical place to put it is in Session. This is what you allude to in your question, but you are using incorrect syntax. The correct syntax to store a variable in Session is:
Session::put('somekey', 'somevalue');
The correct syntax to retrieve it back out later is:
Session::get('somekey');
As far as when to perform these operations, that's a little up to you. I would probably choose a route filter if on Laravel 4.x or Middleware if using Laravel 5. Below is an example of using a route filter that leverages another class to actually come up with the value:
// File: ValueMaker.php (saved in some folder that can be autoloaded)
class ValueMaker
{
public function makeValue()
{
return 42;
}
}
// File: app/filters.php is probably the best place
Route::filter('set_value', function() {
$valueMaker = app()->make('ValueMaker');
Session::put('somevalue', $valueMaker->makeValue());
});
// File: app/routes.php
Route::group(['before' => 'set_value'], function() {
// Value has already been 'made' by this point.
return View::make('view')
->with('value', Session::get('somevalue'))
;
});
In Laravel 5.6, you will need to set it as:
session(['variableName' => $value]);
To retrieve it, is as simple as:
$variableName = session('variableName');
For example, To store data in the session, you will typically use the putmethod or the session helper:
// Via a request instance...
$request->session()->put('key', 'value');
or
// Via the global helper...
session(['key' => 'value']);
for retrieving an item from the session, you can use get :
$value = $request->session()->get('key', 'default value');
or global session helper :
$value = session('key', 'default value');
To determine if an item is present in the session, you may use the has method:
if ($request->session()->has('users')) {
//
}
in Laravel 5.4
use this method:
Session::put('variableName', $value);
To add to the above answers, ensure you define your function like this:
public function functionName(Request $request) {
//
}
Note the "(Request $request)", now set a session like this:
$request->session()->put('key', 'value');
And retrieve the session in this way:
$data = $request->session()->get('key');
To erase the session try this:
$request->session()->forget('key');
or
$request->session()->flush();
You can try
Session::put('variable_Name', "Your Data Save Successfully !");
Session::get('variable_Name');
In Laravel 6.x
// Retrieve a piece of data from the session...
$value = session('key');
// Specifying a default value...
$value = session('key', 'default');
// Store a piece of data in the session...
session(['key' => 'value']);
https://laravel.com/docs/6.x/session
If you want persistence sessions,
Method 1: use session()->save() or Session::save()
session(['key' => 'value']);
//or
session()->put('key', 'value');
//then
session()->save();
echo session('key');
Method 2: Move bellow line from protected $middlewareGroups of app\Http\Kernel.php to protected $middleware array as first line
\Illuminate\Session\Middleware\StartSession::class,
Make sure the storage directory has write permission
chmod -R a+rw storage/
Don't use dd() to verify session, use print_r()
to set session you can try this:
$request->session()->put('key','value');
also to get session data you can try this:
$request->session()->get('key');
If you want to get all session data:
$request->session()->all();

Categories