I have a sequence of number like follows
1 -> 25,
2 -> 60,
3 -> 80,
4 -> 100
and so on
which means that if input is 1 output will be 25 and so on...I need to store it in global array.I would like to use it in multiple pages also.In codeigniter where i can declare a global array and store all these?
I am trying like as follows in constants.php
$CONFIDENCEVALUE = array();
$CONFIDENCEVALUE[] = array('1'=>25,'2'=>'60','3'=>80,'4'=>100);
If it is correct how can access these array value in required pages.Help me please.I am not an expert with codeignitor.
If I were you I'd look at adding a custom config file (see https://www.codeigniter.com/user_guide/libraries/config.html).
So in eg. application/config/confidencevalue.php add the following
$CONFIDENCEVALUE = array('1'=>25,'2'=>'60','3'=>80,'4'=>100);
$config['confidencevalue'] = $CONFIDENCEVALUE;
Add the config file to your application/config/autoload.php and you'll then be able to access your array through the config class using $this->config->item('1', 'confidencevalue'); (replacing the 1 for the value you're looking for).
Store the array in a session variable:
$this->session->set_userdata('cvarray', $CONFIDENCEVALUE);
To access the array later:
$this->session->userdata('cvarray');
CodeIgniter Session Class
One way of doing this is by adding a function to a helper file that you make available globally.
I have a helper file application/helpers/main_helper.php in which I load a number of generic, common functions which are used throughout my application.
If you add the following function to the main_helper file:
/*
|--------------------------------------------------------------------------
| Function to retrieve Static Variables used Globally
|--------------------------------------------------------------------------
*/
function get_var($var = 'CONFIDENCEVALUE', $KEY = NULL) {
$r = false;
switch ($var) {
case 'CONFIDENCEVALUE':
$r = array('1'=>25,'2'=>'60','3'=>80,'4'=>100);
if($KEY !== NULL) $r = $r[$KEY];
break;
}
return $r;
}
This file is auto-loaded by editing the file application/config/autoload.php and editing the line:
$autoload['helper'] = array('main_helper');
Whenever this array (or a value from the array) is needed, call the function instead. eg.:
$CONFIDENCE = get_var('CONFIDENCEVALUE', 2);
If you include the $KEY when calling get_var(), then only the value is returned, otherwise the whole array is returned.
To make additional variables available, just add them to the switch and call them as needed.
Feedback welcome :).
Related
I am trying to implement the "Edit Application Settings" feature. After a bit of thinking, my configuration values are stored in the DB with key -> value structure, like this:
id
key
value
1
logo_path
img/logo.png
As you can see, for each setting, there is only a key & value column. I made an App Service provider to cache them forever, and a helper function (config('setting_key')) to get the value, but now I'd like to update it in the most efficient way.
The user interface consists of the <form action="post" ...> and input with a corresponding name, like this: <input name="setting_key_name" ... />. As you can see, the name attribute here has the value of the key column value and the actual value of the input would be the value column value (a bit of confusion here).
First thing that came to my mind, was to make a foreach loop and find & update every row in DB, but IMHO it is very unoptimized way, cause if the page has a form with 10 values, it is 10 SQL queries. But till now, this is what I've done:
$keys = collect($request->except('_token'))->keys()->toArray();
// get all settings if the key name matches the request's input name
$setting = Setting::whereIn('key', $keys)->get();
$logo = self::GENERAL_APP_LOGO; // contant with a key-name (general_application_logo);
if($request->has(self::GENERAL_APP_LOGO) && $request->$logo) {
// Processing uploaded image here;
$this->uploadLogo($image, self::LOGO_IMAGE_PATH, $name); // Using an upload trait
$setting->where('key', $logo)->value = self::LOGO_IMAGE_PATH . $name; // just a try to update the DB this way
}
foreach ($keys as $key) {
$setting->where('key', $key)->value = $request->$key; // putting all request's input values to corresponding key
}
$setting->save(); // saving the DB.
As you can see, this won't work and will throw an Exception, like Call to undefined method ...\Eloquent\Builder::save(). I tried the same code with an update, but the difficult part here is to update it multiple times (since the if section should have the update as well, for the logo), as well as binding the key to value.
So, a little bit of your help would be appreciated - what the logic should be here? How can I update a DB rows with corresponding column's value? I mean - like this (update where key = 'general_app_name' set value, 'some_setting_value'), but using the optimized and clear way?
Working solution
As #miken32 stated in his answer, I used hid version of code, but with slight changes:
// Changed the $request->settings->keys() to PHP native method array_keys():
$settings = Settings::whereIn('key', array_keys($request->settings))->get()->groupBy('id');
// Also, here I changed the `whereIn('id', ...)` to `whereIn('key', ...)`, since it was my primary index.
foreach ($request->settings as $k=>$v) {
if ($k === self::GENERAL_APP_LOGO_ID) {
// not sure about this one, but I think this is
// how you'd access a file input in an array
$image = $request->file('settings')[$k];
$this->uploadLogo($image, self::LOGO_IMAGE_PATH, $name);
$v = self::LOGO_IMAGE_PATH . $name;
}
// take the Setting object out of the list we pulled
// Here I added the ->first() to get the first element from the retrieved collection;
$setting = $settings->get($k)->first();
$setting->value = $v;
$setting->save();
}
Since I was fetching the configuration values via helper, that only returns the value of the current key (and no id column), I changed the id to key and made the key as my PK in a model. Works like a charm!
With each setting in a separate row, there's no way to avoid multiple database queries – one to get the current values for all settings, and other to update each one. Looking up items by primary key is more efficient, so I'd recommend putting the contents of the id column in your blade view, like this:
<label for="setting_{{$setting->id}}">{{$setting->key}}</label>
<input name="settings[{{$setting->id}}]" id="setting_{{$setting->id}}" value="{{$setting->value}}"/>
Now in your controller, $request->settings will be an array you can loop through. You can continue treating your file upload separately, but now you've got the id column to look up, so change your constant to that.
$settings = Settings::whereIn('id', $request->settings->keys())->get()->groupBy('id');
foreach ($request->settings as $k=>$v) {
if ($k === self::GENERAL_APP_LOGO_ID) {
// not sure about this one, but I think this is
// how you'd access a file input in an array
$image = $request->file('settings')[$k];
$this->uploadLogo($image, self::LOGO_IMAGE_PATH, $name);
$v = self::LOGO_IMAGE_PATH . $name;
}
// take the Setting object out of the list we pulled
$setting = $settings->get($k);
$setting->value = $v;
$setting->save();
}
Note that Laravel does offer methods to bulk-update multiple models at once, but they are doing separate queries to the database in the background. IIRC, the save() method doesn't do anything if the value hasn't changed, which will spare you some hits.
You could try creating a text field, or a json field if your database supports it, and storing all of your settings as a JSON string in that field.
id
settings
1
{ "logo_path" : "img/logo.png", "foo" : "bar", "thing_count" : 17 }
2
{ "logo_path" : "img/logo2.png", "foo" : "baz", "thing_count" : 4 }
In your Laravel model, you can cast it as an array
protected $casts = ["settings" => "array"];
and then use it from the model
echo $theModel->settings['logo'];
echo $theModel->settings['foo'];
or you can cast it as a fully fledged object if you need to using value object casting.
One gotcha that can be confusing for people is the setting of the values in the array to update it. This will not work:
$theModel->settings['foo'] = "boz";
The reason is due to the way the Laravel mutators work. Instead, you make a value copy of the settings, change that, and reassign it to the model:
$settings = $theModel->settings;
$settings['foo'] = "boz";
$theModel->settings = $settings;
This approach has the capacity to infinitely expandable in the future as you just add new keys to your json. Be sure to do checks on the settings array to ensure fields you are looking for are set (which is why value objects can be very handy to do validation).
It also solves your database query problem - it's only ever one.
You don't need to put
$setting->where('key', $logo)->value = ...;
Just call
$setting->where('key', $logo)->update($request->toArray());
$setting->save(); called when you instantiated setting class like :
$setting = new Setting();
Or
$setting = Setting::whereIn('key', $keys)->get()->first();
Then
$setting->val = ...;
$setting->save(); // then it work's
I'm working on a simple session manager for my framework. Im trying to setup a more user friendly structure for the session data. Essentially my sessions are stored like this:
$app_name = "Some_App_Name";
$component = "notifications";
$key = "errors";
$value = "There was some error";
$_SESSION[$app_name][$component][$key] = $value;
The problem I am facing is creating this structure through parameters within the session class. I have a set method which should ideally set a session value. The $app_name as listed above is by default added to the session class through the constructor, but I need to find a simple way of taking the parameters passed in within the method and then creating the rest. A simple example:
// Where keys could be: $key1 = notifications, $key2 => "notices"
public static function set($key1,$key2,$value) {
$_SESSION[self::$app_name][$key1][$key2] = $value;
}
The above would work if I always have 4 parameters but in some cases I might only have 2 parameters. I could pass 2 parameters (both being an array) but I'm looking for a more streamlined approach (if such an approach exists).
With the creating of the structure and setting values I also need a similiar way of verifying if the value or last key exists:
// Where keys could be: $key1 = notifications, $key2 => "errors"
public static function exists($key1,$key2) {
if(isset($_SESSION[self::$app_name][$key1][$key2])) {
return true;
}
Any suggestions would greatly be appreciated.
$params = array(
"key1" => "value1",
"key2" => "value2",
"value" => "value"
);
public static function set($params = NULL) //default null if no value is passed
{
if (!self::exists($params)) return false;
$_SESSION[self::$app_name][$params["key1"]][$params["key2"]] = $value;
return true;
}
public static function exists($params = NULL)
{
if(isset($_SESSION[self::$app_name][$params["key1"]][$params["key2"]]))
{
return true;
}
return false;
}
In the light of assisting other members wanting to do something similiar, I want to strongly advise you against using this concept as off the bat it sounds like a good idea but your true issue comes with the management of the array itself. Working straight with the $_SESSION superglobal really is the more powerful option on the basis that:
Even with a parameter in place for say server and component ($_SESSION ['somename']['auth']), what happens when you want to access content from that level from another instance of the object? Say I have another session object instance for $_SESSION ['somename']['errors'] but need to access properties from $_SESSION ['somename']['auth'] but within scope my base within the session array is incorrect.
Adding properties is fine $this->session->add("key","name") but what if you want to append to that array (where name is actually an array and not just a value), or vise versa. Or checking for occurances if $_SESSION['somename']['auth']['key']['name'] actually has another key or value within it?
All and all having worked with this the last couple of days I can definately say that it might not be impossible to write a "fully functional" session manager class but at the end of the day for simplicity it's better to rather just work with the session array directly as it's less code and less issues as you go.
I hardly know any OOP PHP so I don't know how to properly pass variables.
I have a function that passes my results to a .php file that has the HTML table to show the results. I want to pass a variable "$config" to that file so I make a if/else statement.
Here is the function that passes my results to the file, that I need to pass the "$config" variable to create my if/else.
public function outputBrowser($results)
{
// $rows = array();
// print_r($results);
// die();
$config = $this ->config
$this->EE->load->add_package_path($this->report_path);
return $this->EE->load->view('output_browser', array("results" => $results), TRUE);
}
The main objective is to pass the selected drop down item to my file so I can output various HTML tables based on that selection. That selected value is in my config class or $config variable.
As my comment seemed to have fixed it:
Just add the $config variable to the array you pass:
array("results" => $results, "config" => $config)
I've been trying all night to update a record like this:
$r = $this->Question->read(NULL, $question['Question']['id']);
debug($r);// This is a complete Question array
$this->Question->set('status', 'version');
$s = $this->Question->save();
//$s = $this->Question->save($r['Question']);//this also doesn't work
debug($s); // = False every time!! Why??
exit;
The two comments show variations I've tried but didn't work either.
#Dipesh:
$this->data = $this->Question->read(NULL, $question['Question']['id']);
$this->Question->status = 'version';
$s = $this->Question->save($this->data);
debug($s);
exit;
#Dipesh II:
$this->request->data = $this->Question->read(NULL, $question['Question']['id']);
debug($this->data);
//$this->Question->status = 'version';
$this->request->data['Question']['status'] = 'version';
$s = $this->Question->save($this->request->data);
//$s = $this->Question->save($r['Question']);
debug($s);
exit;
#Dipesh III:
(removed)
cakePHP provide a method called set() in both Models::set() as well as in Controller::set();
About Controller::set()
This method is used to set variables for view level from any of the controller method. For example fetching records and from models and setting them for views to display it to clients, like this
$data = $this->{ModelName}->find('first');
$this->set('dataForView',$data) // now you can access $data in your view as $dataForView
About Model::set()
This method is used to set data upon a model, the format of the array that will be passed must be same as that used in Model::save() method i.e. like this
$dataFormModel = array('ModelName'=>array('col_name'=>$colValue));
$this->{ModelName}->set($dataForModel);
Model::set() will accept its parameter only in this format, once successfully set you can do following
validate this data against the validation rules specified in model directly like this
$isValid = $this->ModelName->validate();
save/update data by calling Model::save()
Use $this->data instead of $r
Example
$this->data = $this->Question->read(NULL, $question['Question']['id']);
$this->set is used to set variable value and pass it to view so view can access it where as $this->data represent the data to be stored in database.
If You're using Cake 2.0 then replace $this->data which is read only in Cake 2.0 to $this->request->data.
It's not very "automagical" but I was able to get this working like this:
$set_perm_id = 42;//who cares
$data = array(
'Question'=> array(
'id'=> $question['Question']['id'],
'perm_id'=> $set_perm_id,
'status'=>'version'
)
);
$s=$this->Question->save($data);
Basically I'm just building the data array manually. If anyone knows why this works instead of what I was doing before, I'd love to hear it.
Just try these lines..
$this->Question->id = $question['Question']['id'];
$this->Question->set('status','version');
$this->Question->save();
OR
$aUpdate["id"] = $question['Question']['id'];
$aUpdate["status"] = "version";
$this->Question->save($aUpdate);
I have a sfuser/attributes looking like this:
session:
symfony/user/sfUser/attributes: {
symfony/user/sfUser/attributes:{
15:{
Telefon:'+304994994994',
option:'15',
rules:'12',
arrayBunch:[{
this: 'da',
that: "where"
}]
},
17:{...},
mysetting: "val"
},
sfGuardSecurityUser:{},
admin_module:{},
sfGuardUserSwitcher:{}
}}
When i use setAttribute("mysetting", "val") they stores mysetting like show on my example. It is therefore unnecessary to use setAttribute("mysetting", "val", 15) because i got the same answer.
How can i access the nodes 15 or arrayBunch an use setAttribute to input a value there or getAttribute to get'em?
I think you are doing it in a wrong way (about parameters).
What you want to do is:
add a variable called val
with the value 15
in the namespace mysetting.
But, you have written parameters in a wrong order.
If you check the code, parameters are :
public function setAttribute($name, $value, $ns = null)
So you should try:
->setAttribute('val', 15, 'mysetting');
Edit: (sorry didn't notice the arrayBunch problem)
If you want to edit the arrayBunch value:
// retrieve the current value
$arrayBunch = $this->getUser()->getAttribute("arrayBunch", array(), 15);
// made some modification
$arrayBunch['toto'] = 'titi';
$arrayBunch['this'] = 'do';
// put back the modification
$this->getUser()->setAttribute("arrayBunch", $arrayBunch, 15);
Edit:
With a closer look to your json, you should retrieve the whole attribute 15, since the namepsace is the default one: symfony/user/sfUser/attributes. So:
$attribute15 = $this->getUser()->getAttribute(15);
$arrayBunch = $attribute15['arrayBunch'];
And if you want to apply some changes:
// update arrayBunch
$arrayBunch['this'] = 'dada';
// do not forget to re-add modified arraybBunch to the whole variable
$attribute15['arrayBunch'] = $arrayBunch
// and if you want to add a value
$attribute15['mysetting'] = 'val';
// then, save every thing to the session again
$this->getUser()->setAttribute(15, $attribute15);