So I tried to create a library in which I can get some "global" data from one of my data tables (site name, logo, favicon, etc).
This is my current library:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Settings {
//holds the CI instance
//var $ci;
protected $ci;
//the array the settings will be stored as
public $settings = array();
//
public function __construct()
{
//load CI instance
$this->ci =& get_instance();
//fire the method loading the data
$this->get_settings();
}
public function get_settings()
{
$this->ci->load->model('settings_model');
$this->settings = $this->ci->Settings_model->get_list();
return $this->settings;
}
}
?>
This library should access to my method get_list() on my Settings_model and so far it seems to be able to do so (keep reading).
This is my settings model:
function __construct()
{
parent::__construct();
$this->table = 'ci_settings';
}
public function get_list()
{
$query = $this->db->get($this->table);
return $query->result();
}
Now to use the data which comes from the database in my views without having to declare them in all my controllers, I just have to do this(I did something similar with my menu library so I know it should work):
<?php echo $this->settings['website_name'] ?>
Here is the PROBLEM, my library is being able to access to my model which seems fine(I suppose), the problem comes when it tries to access to the get_list method itself; is apparently having some issues returning the data as this is the error that I get:
Should not this be possible just like this?.. what I'm trying is to have global variable for logo, website name, etc... I'm sure it should not be that hard but I'm having a really big pain in the *** trying to figure out a solution.
Any idea where is my error?,
Thanks in advance.
Try with ->settings_model-> with S in lowercase, but why ?
CI save the instance of your model internally like a property of the object CI that you have with function get_instance()
Remember: class properties are case sensitive
Related
in codeigniter I have my main controller:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Main extends CI_Controller
{
public function index()
{
$this->load->library('../controllers/forum');
$obj = new $this->forum();
$obj->test();
}
}
And the controller I'm trying to access:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Forum extends CI_Controller
{
function __construct()
{
echo "testing1";
$this->load->library('session');
parent::__construct();
$this->load->database();
$this->load->model('model_forum');
}
public function index(){
}
public function test(){
echo "testing2";
$this->data['forums'] = $this->model_forum->getForums();
$this->load->view('homepage', $this->data);
}
}
Everything is fine with my model_forum.php file, because it works if I put all the code in Main controller. But if I'm trying to access Forum controller, nothing works, only "testing1" echo goes through. Picture of error:
Anyone has any idea what I'm doing wrong? I'm new to PHP and codeigniter so I'm struggling a little bit. Thanks in advance.
You can't load a controller from a controller in CI - unless you use HMVC or something.
You should think about your architecture a bit. If you need to call a controller method from another controller, then you should probably abstract that code out to a helper or library and call it from both controllers.
UPDATE
After reading your question again, I realize that your end goal is not necessarily HMVC, but URI manipulation. Correct me if I'm wrong, but it seems like you're trying to accomplish URLs with the first section being the method name and leave out the controller name altogether.
If this is the case, you'd get a cleaner solution by getting creative with your routes.
For a really basic example, say you have two controllers, controller1 and controller2. Controller1 has a method method_1 - and controller2 has a method method_2.
You can set up routes like this:
$route['method_1'] = "controller1/method_1";
$route['method_2'] = "controller2/method_2";
Then, you can call method 1 with a URL like http://example.com/method_1 and method 2 with http://example.com/method_2.
Albeit, this is a hard-coded, very basic, example - but it could get you to where you need to be if all you need to do is remove the controller from the URL.
You could also go with remapping your controllers.
From the docs: "If your controller contains a function named _remap(), it will always get called regardless of what your URI contains.":
public function _remap($method)
{
if ($method == 'some_method')
{
$this->$method();
}
else
{
$this->default_method();
}
}
Okay. So I have been stumping myself on where I have gone wrong with this. I am not-so-new to PHP but I am also no expert, although I am getting more and more used to OOP. I have recently got into CodeIgniter 3. I like it, I use it, it's pretty simple to grasp in the beginning.
However, I am in the learning stage where I cannot successfully pass dynamic data, from the database into the controller using a Model.
And just as an FYI: I am using MY_Controller as my Base Controller, and have set a $data object to pass variables application wide. I know my problem is not due to the use of MY_Controller, because when I use static $this->data['KEY'] = 'VALUE'; or $this->data array('KEY' => 'VALUE');, my variables get passed into my views. So MY_Controller is functional.
My problem resides in creating a Settings_model. Its sole purpose is to take data from a database table settings and extrapolate certain columns of data, such a/an: application title, background color, etc.
So. On to my question/s, and what I have tried to do to fix this.
First, here is my MY_Controller:
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Controller extends CI_Controller
{
public $data;
public function __construct() {
parent::__construct();
$this->data = array(
'app_title' => $this->settings_model->get_title('$title'),
'meta_author' => APP_AUTHOR
);
}
}
And here is my Settings_model:
defined('BASEPATH') OR exit('No direct script access allowed');
class Settings_model extends CI_Model
{
public $title = '';
public function __construct() {
$this->load->database();
}
public function get_title($title) {
$this->db->select('app_title');
$this->db->from->('settings');
$this->db-where('app_title', $title);
return $this->db->get()->row('app_title');
}
}
My Problem
When using the sytnax above. i am able to see my applications output in the browser. Everything is rendered properly, all the static variables I've assigned in MY_Controller work. Everything is good ... except, the $app_title variable (which is in my views, and assigned in MY_Controller) does not load the data from the database, as the model instructed. As well as does not produce any error, warning or notice.
What I've tried
Man i tell you I have tried everything. i have tried inserting the query into MY_Controller directly and not using a Model (which I know is not proper MVC, but I wanted to try), like so:
MY_Controller Using Straigh Query, no model
$this->data = array(
'app_title' => $this->db->query('GET app_title FROM settings'),
'meta_author' => APP_AUTHOR
);
And the one time i got somewhere, error/notice wise was when i altered the Settings_Model, like so:
Altered Settings Model
defined('BASEPATH') OR exit('No direct script access allowed');
class Settings_model extends CI_Model
{
public $title = '';
public function __construct() {
$this->load->database();
}
public function get_title($title) {
$this->db->select('app_title');
$this->db->from->('settings');
$this->db-where('app_title', $title);
// Before it was this:
return $this->db->get->row('app-title');
// But I changed it to this
return $this->db->get()->row()->app_title;
}
}
But that syntax above gave me the error in this Image of a non Object Error
I do not know what I am doing wrong.
Now the question/s
Why when i use the first approach of the settings_model, using return $this->db->get()->row('app_title'); does it show all of my applications output in the browser, but everywhere the $app_title variable is called, it itself displays no value from the database, via MY_Controller and Settings_model?
Why when i use the second approach of the settings_model, using return $this->db->get()->row()->app_title; does it produce the Trying to get property of Non Object error in the image i linked to above?
What on earth am I doing wrong? I know I am still on the early learning stages of OOP, and Models, etc. But I must be missing something, I know something is not right.
Any and all help is greatly appreciated and welcomed. I thank everyone for their input.
EDIT 1: Thanks to #Mirceac21 for asking. I am autoloading the settings_model in config/autoload.php.
EDIT 2: I have now switched the var $data to public $data in MY_Controller as #Mirceac21 suggested. Still the same error but he is correct about not using var there.
Okay, so I figured it out. With the help of #Mirceac21. I change the var $data to public $data in MY_Controller.
Then in the Settings_model, I took out the WHERE clause and it worked. Here is the new working code below:
MY_Controller
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Controller extends CI_Controller
{
// $data object used for $this->data
public $data;
public function __construct() {
parent::__construct();
/*
* The $data array('KEY' => 'VALUE') variable sets are used
* in other Controller Classes that extend MY_Controller.
*/
$this->data = array(
'app_title' => $this->settings_model->get_title('$title'),
'meta_author' => APP_AUTHOR
);
}
}
Then in the Settings_model I made the following changes, remove ->where('app-title', $title);. Like so:
defined('BASEPATH') OR exit('No direct script access allowed');
class Settings_model extends CI_Model
{
public $title = '';
public function __construct() {
$this->load->database();
}
public function get_title($title) {
$this->db->select('app_title');
$this->db->from->('settings');
// I removed the following where->(); and it now loads the dynamic data
// $this->db-where('app_title', $title);
return $this->db->get()->row('app_title');
}
}
Now everything works as planned. I knew it was something simple and stupid 9for lack of better words). Thank you to #Mirceac21 for your input.
I have user library currentLang that detect current language of web site.
Also there is model that does request and gets data from.
Request is based on current language.
This is library currentLang was set in autoload.
Problem is that is loaded at first all models in Codeigniter, after libraries.
Therefore when I open web site I get empty page, because query is done without params from library.
What I must to change in this way?
It doesn't matter which one is loaded first, As long as you're able to inject the current language id in the CodeIgniter instance, You'll be fine.
Example:
// Library
class CurrentLang {
// A variable that will hold the CodeIgniter object.
protected $CI;
public function __construct () {
$this->CI = get_instance();
$this->set_language();
}
protected function set_language () {
// Some code to determine which language to set (your logic goes in determine_language method in this class)
$Language = $this->determine_language();
// then we inject the language id in the instance as follows.
$this->CI->CurrentLanguageId = $Language->id;
}
}
// Model
class Some_model extends CI_Model {
public function get_posts () {
$q = $this->db
->where('language_id', $this->CurrentLanguageId)
->limit(10)
->get('posts');
return $q->result();
}
}
Please keep in mind in CodeIgniter 3x the first letter in a library name should be capitalized.
I'm about to write my own library in codeigniter to check if the logged in user is an admin or not. To do that I need to compare a value with the value of the typeAccount in the DB.
Because I'm still learning the MVC pattern I had a question about this before starting to write my library.
Can I load a model in my library? Or should I communicate directly to my DB in my library? Or is there a better way to approach this?
Yes, you can load your model to into your library, simply add CI.
class Validator
{
private $CI = null;
function __construct()
{
$this->CI =& get_instance();
}
public function validate_merchantaccount_status($param)
{
//Code Here
$this->CI->load->model('merchantaccount_model');
$res_merchant = $this->CI->merchantaccount_model->get_list($param);
}
}
Dont forget to make your model.
Since the library is some kind of logic, you can see it as a piece of the Controller.
The Controller usually just loads a Model to use it.
So yes just load the Model from CodeIgniter instead of connecting to the database yourself.
Makes your code more DRY too.
Make you models
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class My_model extends CI_Model
{
/// Here the code
}
And then in controller use
$this->load->model('my_model');
Ant i think that is best approach :)
I have been using CI for two years now. One thing that really annoys me is the use of &get_instance(). Although it is halpful while we are inside library , helper , presenters , model etc. But everytime loading it is cumborsome. If you forget loading it somewhere and simply use $this->blah->blah() instead of $CI->blah->blah() this makes too much trouble and if you are working online you face the client who is complaining that he sees the error. I have seen in the laravel that you does not need to load the instance anywhere throughout the application. This is because laravel is autoloading all the libraries and models and both are available anywhere in the application. But this seems to me disadvantage why loading classes that are not required in some particular places. This tells me Codeigniter is flexible but still i want an alternative where i dont want to use &get_instance(). Any idea or suggestion ? Please.
In your model or Core model or library
//class MY_Model extends CI_Model
//class SomeLibrary
class Some_model extends CI_Model {
private $_CI;
public function __construct() {
parent::__construct(); //for model or core model
$this->_CI =& get_instance();
}
//if you called attributs who does not exist in that class or parent class
public function __get($key)
{
return $this->_CI->$key;
}
//if you called methods who does not exist in that class or parent class
public function __call($method, $arguments)
{
call_user_func_array(array($this->_CI, $method), $arguments );
}
public function test() {
var_dump($this->some_controller_key);
var_dump($this->some_lib_loaded);
}
}
*NOT TESTED YET
Inspired by an piece of code from the awesome Flexi Auth
//from a Model to keep access of CI_Controller attributs
public function &__get($key)
{
$CI =& get_instance();
return $CI->$key;
}
I was shocked when I saw that ^^
To explain the &__get, i think when you will call this magic method a second time PHP will do not execute it again, but will take his result from the first call.