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.
Related
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
I am a Java developer (I often used Spring MVC to develop MVC web app in Java) with a very litle knowledge of PHP and I have to work on a PHP project that use CodeIgniter 2.1.3.
So I have the following doubt about how exactly work this controller method:
So I have this class:
class garanzieValoreFlex extends CI_Controller {
.....................................................
.....................................................
.....................................................
public function index() {
$this->load->model('Direct');
$flagDeroga = "true" ;
$this->session->userdata("flagDeroga");
$data = $this->session->userdata("datiPreventivo");
$this->load->model('GaranzieValoreFlexModel');
$data = $this->session->userdata("datiPreventivo");
$this->load->model('GaranzieValoreFlexModel');
$this->load->view('garanziavalore/index_bootstrap',$data);
}
}
I know that the index() method of the garanzieValoreFlex controller class handle HTTP Request toward the URL: http://MYURL/garanzieValoreFlex and show the /views/garanzievalore/index_bootstrap.php page.
It works fine. The only think that I can't understand is what exactly does this code line:
$data = $this -> session -> userdata("datiPreventivo");
Can you help me what exactly is doing? I think that it is putting something into the HttpSession or something like this but I am absolutly not sure about it and I can't understand the logic.
session is a Codeigniter (CI) library (class) that allows data to persist across multiple page calls from a browser. In the version of CI you are using "native" PHP session functionality is not used. But CI's session class does mimic PHP's session in that data is stored in a PHP associative array.
The class has many different methods to store and retrieve user defined data. The function userdata("index_to_data") is one of the main class methods. It is used to retrieve data that has been stored in the session class.
The argument passed to userdata() is the key to a value in the session class array $userdata. So, $this->session->userdata("datiPreventivo"); returns the value stored at $userdata["datiPreventivo"]. If the key (in this case "datiPreventivo") does not exist then $this->session->userdata("datiPreventivo") returns FALSE.
Somewhere in the code you are working with you will find a line where data is stored in the session. The line of code might look something like this.
$newdata = array("datiPreventivo" => $something_value);
$this->session->set_userdata($newdata);
Searching your code for "$this->session->set_userdata" might be helpful to understand what exactly is being saved for future page loads.
It is important to know that CI's session class was completely rewritten in versions > 3.0 so the current documentation may not be very helpful to you. You will need to find the documentation for the version you are using to learn more about the session library. I believe that documentation is included in the download for your version which can be found here.
I have tried to google out where i can store in Laravel static data ( just simple arrays ) but have not found any obvious reasons or explanations, just some existing solutions.
Data could be for example list of countries. Yes it could be stored in DB but it sounds for me useless since that data would be static and used only for retrieval puposes.
I have seen many approaches for storing data like this for example:
Models ( Entities )
Storing as package
Controllers
Is there any practises where to store such static data?
Or maybe "data" it self refers to store data where it should be belong, - database, no matter what operations would be done on it?
Laravel is opinionated, and you should be. There is more than one way to do it.
You can make it stay like a config, and query as a piece of config. For example: config/mydata.php (make sure to return an array), and then config()->get('mydata.***').
You can make a helper and register to autoloader, create app/helpers.php,
public function generate_data()
{
return [ 'x' , 'x' ,'x' ... ];
}
register via composer.json,
{
"autoload": {
"files": [
"app/helpers.php"
]
}
}
Well, if you need another obvious PHP style, create a file anywhere in root project, for example: MY_LARAVEL_PROJECT_ROOT/mydata/country.php, create the file and returning an array of your things. At the end of app/start/global.php, require it,
require base_path().'/mydata/country.php';
It just works like that and have fun :)
You can store static arrays and other constant variables in config/constants.php file...
In the old laravel 4 Code we use an constants.php to define global vars.
What is the best practices to use define vars in Laravel 5?
We wouldn't store it in the .env file or the routes.php
I just want to improve a little bit #Adam's answer. Suppose an online shopping cart. Then, you want a global var to store the currency symbol in order to be displayed at views. Because this value can be changed across the time, you can specify it at App\Providers\ConfigServiceProvider like so:
public function register()
{
$currency = 'whatever you want';
config([
'currency' => $currency
]);
}
The $currency = config('currency') var is global for use at entire application even the request is not yet arrived at controllers (you can read more about middleware classes).
If you definitively want to use constanst (values never change) you could consider set the values at config files direclty as below:
# create a new config file config/customs.php
# like content, you could start with:
return [
'currency' => '$'
];
Finally, you grap the value in your app with config('customs.currency').
Depends on what sort of variables you are trying to store. If they are related to the model they should be stored in the model, if they are related to the environment they should be stored in .env. What sort of variables are you trying to store?
I'm looking to use Lithium framework to build my application config interface as I like its minimal approach and the document-store (i.e. Mongodb) centric model.
However, (and I know its not quite released yet), there is little-to-no information, tutorials or examples out there to move you on from the simple blog tutorial.
What I am trying to do now is build an app that will show me the collections I have in Mongodb, and then let me work with which ever collection I choose. I can't seem to figure out:
a) how would I build a model that enumerates the collections - preferably according to my internal naming scheme,
b) how do I break the convention model so I can specify the name of the collection to use?
I think there are two things i'm struggling with to answer these two questions - perhaps a fundamental misunderstanding of how to move a model in MVC beyond the simple collection-model-controller-view examples, and secondly, the actual process of telling the mongo datasource what collection to use.
any pointers or examples, gratefully received.
Chris
update::
So I figured out how to set the collection - for reference you can set source in the $_meta array like this:
protected $_meta = array(
'source' => '<<collectionName>>'
);
still no idea how to use a Model that will list me all the collections I have in my DB though. Any ideas how to do that from a philosophical and also technological manner?
further update::
so I have got a bit further thanks to the comments below. At least I might now be able to re-phrase the question a bit. I can define my model something like this:
<?php
namespace app\models;
use lithium\data\Model;
class Posts extends \lithium\data\Model{
protected $_meta = array('source' => false);
public function testcolls(){
return (self::connection()->sources());
}
}
?>
then in my view I can use:
<?php foreach ($post->testcolls() as $coll): ?>
<h2><?=$coll ?></h2>
<?php endforeach; ?>
that works - however, what I really want to do is not create a 'testcolls' method in my Model but as Medhi suggested below, I need to override the find method. I can't seem to figure out how to do that and what it would need to return. The docs are not too clear on this.
final update
based on the comment below and a bit of experimentation, I came up with the following that works for being able to call find with a collection as a parameter.
model:
class Dataqueues extends \lithium\data\Model{
protected $_meta = array('source' => false);
public static function find($filter, array $options = array()) {
if (isset($options['collection'])){
self::meta('source', $options['collection']);
}
return parent::find('all',$options);
}
}
controller:
class DataqueuesController extends \lithium\action\Controller {
public function index() {
$dataqueues = Dataqueues::find('all',array('limit'=>20,'collection'=>'W501'));
return compact('dataqueues');
}
}
getting a model that returns a list of collections was also pretty simple in the end:
class Collections extends \lithium\data\Model{
protected $_meta = array('source' => false);
public static function find($filter, array $options = array()) {
return self::connection()->sources();
}
}
note that the controller won't support options or filters.
Nothing holds you from having a Collections Model, where you set $_meta['source'] = false to prevent Lithium from looking for a Collection in your database named collections.
In this model, you can call YourModel::connection()->sources() to list all your Mongo Collections.
Docs for sources(): http://li3.me/docs/lithium/data/source/MongoDb::sources(). Basically it calls listCollections() on a MongoDB instance http://php.net/manual/en/mongodb.listcollections.php
You can override your Model::find() method to return the list of collections, instead the list of documents, or pass the collection as a param Collections::find('all', array('conditions' => ..., 'collection' => 'foo'))... or wathever you want :-)
Lithium is designed to don't force that much on you !
First of all, Lithium follows the convention over configuration approach.
What this means:
Configuration: 'source' => '<< collectionName >>'
Convention: Name your model and your collection the same thing, the framework handles the rest.
IE: A "People" collection will have a "People" model
Second, connect to your database:
Configure your connections.php file in app\bootstrap\connections.php. I know I said convention over configuration, but you still need to let the framework know where the database is and what the login info is. For details look at the http://li3.me/docs/manual/quickstart. Here is the relevant code:
// MongoDB Connection
Connections::add('default', array('type' => 'MongoDb', 'database' => 'blog', 'host' => 'localhost'));
Third, get data
Create a model, matching your collection name, and then in your controller, add this line:
$model = Models::all();
where model is the singular name for what you are storing in your collection, and Models is the name of your model. That is it.
If you put a break point after this line, you will see your Models collection. For more information, see http://li3.me/docs/manual/working-with-data/using-models.wiki
Finally, to pass it to your view, simply put this line of code at the end of your controller:
return compact('model', 'model2', 'model3');
where model would be what you just pulled in the third step. The models 2 and 3 that I tacked on is how you would pass any other collections you pulled.
In your view, you would just reference $model to and assume that the relevant fields are there. You don't have to worry about putting getters or setters or anything else like that.
For example: if you want to show the data in $model:
foreach ($model as $aModel) {
echo $aModel;
}
See Accessing View Variables in: http://li3.me/docs/manual/handling-http-requests/views.wiki
Hope this helps.