Global Variables in CodeIgniter not Working - codeigniter

I want to generate global variables in CodeIgniter by creating my own library and config file. This is what I wrote ini my library file, let's say globalvars.php. I put it in /application/libraries.
class Globalvars{
function __construct($config = array())
{
foreach ($config as $key => $value) {
$data[$key] = $value;
}
$CI =& get_instance();
$CI->load->library('session');
$CI->load->vars($data);
}
}
I want the user id stored in the session to be available in global variable, so I wrote this in my config file. It's named also globalvars.php. It's in /application/config directory.
$config['user']=$this->session->userdata('id');
I then test to see if it's working by write it in my controller this way.
echo $data['user'];
But I get this error in the browser
Message: Undefined property: CI_Loader::$session
Filename: config/globalvars.php
It seems that the session functions is not defined yet. How can I get it work? What have I missed here? Any help would be appreciated.

You cannot use the session library in config file.
The config files are loaded before any libraries, so $this->session is undefined.

The config.php has to be loaded in order for the Session class to even be initialized, as it reads settings from that file.
A lot of issues with this type of thing (setting some "global" data) can be resolved using a base controller, and extending it in your controllers.
// core/MY_Controller.php
MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct(); // Now the Session class should be loaded
// set config items here
}
}
"Normal" controllers will now extend MY_Controller to take advantage of this.
See: http://codeigniter.com/user_guide/general/core_classes.html for more details.
In addition, when you load->vars(), they are available to the view layer only, it does not create a global variable called $data as you seem to be trying to access. If you do this:
$this->load->vars(array('user' => '1'));
You would access it in a file loaded by $this->load->view() like this:
echo $user; // outputs "1"
See: http://codeigniter.com/user_guide/libraries/loader.html
$this->load->vars($array)
This function takes an associative array as input and generates
variables using the PHP extract function. This function produces the
same result as using the second parameter of the $this->load->view()
function above. The reason you might want to use this function
independently is if you would like to set some global variables in the
constructor of your controller and have them become available in any
view file loaded from any function. You can have multiple calls to
this function. The data get cached and merged into one array for
conversion to variables.
I will say that as an experienced Codeigniter user, the concept of a "global vars" class is a bit wonky and probably unnecessary, especially when it's already so easy to get and set config items. You could definitely run into some confusing issues and variable name conflicts with this method (pre-loading lots of view variables on every request).

Related

How to set global variables from database in Laravel 5.4

I'm facing the same problem very often in various projects - I need to set some global variables from database and be able to receive them in anywhere in laravel - views, controllers, models. Is it possible? Or what is the most easy way to do this?
Why I need this? For language translations. I need them not cached and saved in file. For website options which can be taken from any place of app. For website language to set, because I don't want to make /language/ prefix on url.
Sorry if this question can be a duplicate, but none of the answers in similar questions worked in a way I have explained.
You can try view composers for sharing data globally to all views.
public function compose(View $view)
{
//get value from database
$options = Model::where('domain_name', \Request::server("SERVER_NAME"))->get();
//render to view
$view->with('options', $options);
}
The $options variable (model) would be available in every view.
To share data with all controllers define variables in base controller to access them in controllers which inherit base controller
class Controller extends BaseController
{
public $options = Model::where('domain_name', \Request::server("SERVER_NAME"))->get();
}
you can access it using
class LoginController extends Controller
{
public function dashboard()
{
//access here using
$x = $this->options;
}
}
Like this you can create a base model and use the inherit property to access data globally in models.
Hope it will be useful for you. The options variable may contain all the options from database.
Another way to do this is to create a helper class:
1> Add line to composer.json:
"autoload": {
"files": [
"app/Http/helpers.php"
],
2> Create file:
app/Http/helpers.php
3> Add code:
function o($code = null) {
$option = \Option::where('code', $code)->first();
return $option->value;
}
4> Use where you need:
echo o('option_code')
This works in Controller and View, before any render if called. Here can be checked session, config, cookies and etc.
the best way to access a variable everywhere in your project is using sessions. you can store everything in sessions and access it everywhere in your controllers, models and views.
Read the topic: https://laravel.com/docs/5.5/session#using-the-session

Laravel: Grab data from the Controller from inside a view composer

Atm I'm creating this view composer for fun. It is collecting .js filenames and then passing it to the layout to be linked. The filenames used depend on the current page. For example a lower ranked page like Slides, doesn't include ajax requests used in UserManagement. Please don't ask me why I would do this xD. Im planning to validate requests anyway. Just being bored.
Anyways, as I'm quite new to laravel I'm still looking for more efficient ways to do things.
Atm Im accessing the file names staticly. The Controller now looks like this
class Controller extends BaseController
{
public static $js_file_names = [];
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
In the pagecontroller I construct the filenames:
class SlidesController extends Controller
{
public function __construct()
{
parent::$js_file_names = ['ccs', 'ajax-updates'];
}
And finaly I retreive them inside the registered Viewcomposer like this:
(during development $use_filenames has all files as default)
public function __construct()
{
$filenames = Controller::$js_file_names;
if( !empty($filenames) )
$this->use_filenames = $filenames;
var_dump($this->use_filenames);die;
}
It all seems to be working fine, but the big question is, is there a better way to access controller data from inside a viewcomposer? Every time I try to google this, I get results like 'passing data to views' etc, which is not rly the problem.
Update:
Another idea I had is to store all the filenames to be used in an array inside the viewcomposer itself, and check if the current page exists in that array. This would keep the controllers cleaner.
Using a view composer doesn't really make sense in this situation. Since your controllers already 'know' which files they intent to share, you may as well just pass them to the view like so:
class SlidesController extends Controller
{
public function __construct()
{
View::share('user_filenames', ['ccs', 'ajax-updates']);
}
}
A composer is more for sharing concrete elements such as collections of users, a service provider or some other class instance, for example.

Configure langs in Laravel Translatable BootForms

I'm new to Laravel Translatable BootForms, and I was wondering something.
When I use this code :
{!!
TranslatableBootForm::text('Nom', 'name')
->required()
!!}
The render is as follows :
I don't know where this language list comes from.
I only want to list some languages specified in my database, as I do with this workaround :
#foreach($availableLangs as $availableLang)
{!!
TranslatableBootForm::text('Nom', 'name')
->renderLocale($availableLang['locale'])
!!}
#endforeach
Which gives me this :
My two questions are :
Where does this language list come from ?
How can I replace it by my own language list ?
Answering the first question may lead to an automatic answer for the second, though)
In Laravel, you should always try to read the Service Providers, they provide important clues about the project structures. Let's try to follow the trail of the function calls:
TranslatableBootForm is a facade and it resolves to and instance of translatable-bootform from the Service Container according to this line:
protected static function getFacadeAccessor() { return 'translatable-bootform'; }
Now, in the file TranslatableBootFormsServiceProvider.php we can see that translatable-bootform is an instance of TranslatableBootForm. So when you call TranslatableBootForm::text, you will be using the Facade which resolves to an instance of TranslatableBootForm
Opening the TranslatableBootForm class, we cannot find the text method, so there should be a __call method. The __call method always returns whatever is returned from the method render. So that's where the action is happening.
Reading the code there, you will find that it gets the locales from a method called locales and it will intersect it with the func_get_args() function to get whatever languages you pass to it. So renderLocale or simply render will do the same thing.
The method locales just returns an array which is by default empty in the class. If we return back to the TranslatableBootFormsServiceProvider we will see that there's an important line:
$formBuilder->setLocales($this->getLocales());
Which gets the locales from Translatable\TranslatableWrapper which is just a wrapper around this file in another package: https://github.com/dimsav/laravel-translatable/blob/master/src/Translatable/Translatable.php
Looking at the configuration file in the laravel-translatable package, we can see the languages:
https://github.com/dimsav/laravel-translatable/blob/master/src/config/translatable.php
Solutions
Now, you can simply copy the file translatable.php in your config folder and set your locales.
Or, you create a new service provider MyTranslatableBootFormsServiceProvider
class MyTranslatableBootFormsServiceProvider extends TranslatableBootFormsServiceProvider
{
/**
* Get Translatable's locales.
*
* #return array
*/
protected function getLocales()
{
// You can return a config key
// return config('yourconfig.locales');
// Or directly the array containing the languages
return ['en', 'fr', 'nl'];
}
}
Then, you will use this provider in your config/app.php instead of the original TranslatableBootFormsServiceProvider
Disclaimer:
I didn't try the code, you might have a bug, but you get the idea now how to find your way around Laravel packages.

Codeigniter load model in library

I am using codeigniter 2.1.3
I am trying to load a model from the library. Initially my code in the construct in the library looks like this
$this->CI=& get_instance(); $this->CI->load->database('default')
Then in one of my library methods
when I tried the line below it doesnt work
$this->load->model('model_name')
but when I tried this
$this->CI->load->model('model_name','',TRUE)
it works, anyone can explain what the instance of CI refers to and the 2 extra parameters when loading the model? Thanks in advance.
A library is not necessarily a part of the way CodeIgniter works.
It could be a homemade library, to solve a task that you want done in your CI application.
This means that if you want to use any of CI's helpers, models or other libraries, you need to do this through the CI instance. This is achieved by doing this:
public function __construct()
{
$this->CI =& get_instance();
}
By assigning the instance to your librarys member named CI, all CI related helpers, models and libraries can be loaded through $this->CI. By trying to do it only with $this you are only referring to the current library - not the CI instance.
To load your model correctly, in your library, $this->CI->load->model('model_name'); is enough. The second parameter allows you to access your model through a different object name. The third parameter is not necessary for loading models, but allows you to autoload the database driver.
If you want to access your model through the same member:
$respone = $this->CI->model_name->method();
I have very simple code that you should use to load model in library
<?php
class Custom_lib
{
private $_CI;
public function __construct()
{
$this->_CI = & get_instance();
$this->_CI->load->model('Dynamic_Model','dm');
}
function currentSession()
{
$session = $this->_CI->dm->fetchSingleData('id,session','session',array('is_active'=>1));
return $session;
}
}
I hope this code will help you
You can tell the model loading function to auto-connect by passing TRUE (boolean) via the third parameter, and connectivity settings, as defined in your database config file will be used:
$this->load->model('Model_name', '', TRUE);
You can more about this at the end of the page of this below link.
http://ellislab.com/codeigniter/user-guide/general/models.html

$this->load->db(); initialize in class constructor?

I am putting this code in the constructor for a model class, based on teh tutorial for CI, it states that if you put it there, the database connection can be used globally within that class afterwards. For some reason it's not working and the application crashes at that part of the code. My database configuration is fine since when i put it in the controller i'm able to get db info fine.
Are you doing that before or after the parent class's constructor?
public function __construct()
{
// placing it here fails: $this has no `load` property yet.
// $this->load->database(); <!-- NO WAY JOSÉ!
parent::__construct();
// placing it here should work as the parent class has added that property
// during it's own constructor
$this->load->database();
}
On the other hand, you could be even more explicit:
public function __construct()
{
// Doesn't matter where this goes:
// grab the controller directly
$CI =& get_instance(); // & is not strictly necessary, but still...
// force the loader to load the database.
$CI->load->database();
// directly assign it.
$this->db = $CI->db;
// continue on your merry way
parent::__construct();
}
I believe the explicit solution solved a number of problems in a PHP 4 project once, but it is technically overkill.
you dont need to initialize that . better configure it into
application - config - autoload.php file like this
$autoload['libraries'] = array('database');
The line of code to load the database object is:
$this->load->database();
The database object is then referenced with the name db like so:
$this->db->method_name();
As pointed out by the previous post, if you are going to use the database across multiple models, you should have the library autoloaded in your autoload.php config file.

Resources