CodeIgniter - Model cannot access global variables in CodeIgniter - php

I'm trying to access global variables from a model. The global variable is set from a controller:
function sets(){
$value = $this->input->post('current_id');
$anywhere = array('current_id'=>$value);
$this->load->vars($anywhere);
}
But the model doesn't know the value of the current id:
$session_id = $this->load->get_var('current_id');

Unfortunately the CodeIgniter Model doesn't have access to the values that you're looking for. But there is hope! There are a few ways to go about having getting access to the parameters that are loaded from the request, choose your poison, but having a defined contract interface for your model is, in my opinion, something that makes writing code easier and less of a hassle to maintain down the line.
A reference to the CodeIgniter object can be grabbed like so:
$ci =& get_instance();
$session_id = $ci->load->get_var('current_id');
Of course this would be the nasty way to go about getting at your data. A better approach would be to pass it in to the model itself as a parameter. You're not going to be paying for much in doing so, and it gives you a contract signature on the method where you can point and say "Hey, this should be the current_id of the model:
function sets($session_id)
{
...
}
And, of course, you would just pass in the value you wish $current_id to be as an argument in that function call. This gives you the flexibility of not having to rely on the fact that you're populating the model from a POST HTTP request.

The CI_Model class doesn't have a Loader, so $this->load doesn't exist in a model.
$this->load->get_var() is for controllers to use. From the Loader documentation -
This is useful if for any reason a var is set in a library or another controller method using $this->load->vars().

Try this,
$ci =& get_instance();
$ci->load->get_var('current_id');
But my think, this isn't good idea.
You can use input->post() method on model or set variable with model function arguments.

Related

How to use global variables in codeigniter?

I am developing an application in codeigniter containing different modules e.g buyer, seller, public. All these modules use same header file. I want a global variable declared in buyer, seller and public controller so that when I load views of one module this variable should help customizing parts of header for seller depending upon its value. Same goes for buyer and public modules.
I want to ask what is the way to have a variable declared at controller scope and then use its value in its views. I have tried declaring and assigning its value in constructor but I get undefined variable error when loading the views. I also tried this way:
class Seller extends CI_Controller {
public $pagetype="seller";
public function __construct()
{
parent::__construct();
}
But I still get undefined variable error.
I can pass value of page type when loading view but I have to do that for each view, which is bad and cumbersome way because I have around 25-30 views in each controller.
Any help?
in your controller you can make data globally available in the view layer using this
$this->load->vars($data);
where $data is an array of key => values. you could put this in your constructor, or parent constructor
Consider making your own class - look into Singleton or Registry design patterns... but also read this: What is so bad about singletons?
you could assign the main CodeIgniter object to a variable and then use load->get_var($key) to get the view variable.
function something() {
$ci =& get_instance();
$myvar = $ci->load->get_var(‘myvar);
}

Global helper function capable of accessing Zend objects

Currently I'm using a view-helper to help my debugging process. Basically I call this function and it checks if 1: I'm logged in as a developer by checking a Zend_Session_Namespace variable and 2: if the application is run in debug_mode using Zend_Registry. If both of them are true I show a number of different debug variables and any parameters I give the helper as input.
Originally this function was only intended to check that I got the right info in the objects assigned to the view, but I quickly discovered that it was useful in other places as well. At the moment the function works in controllers using $this->view, and I guess I could technically use something along new Zend_View(); or Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); to get a view-object in my models, but that is just plain ugly even if it's only for debugging.
So my question is: How can I rebuild this helper into a global function (usable in models, views and Controllers) and still be able to use the Zend_Session_Namespace and Zend_Registry objects, while (as far as possible) maintaining the MVC structure.
I think if you made a static class or a singleton class, you could have all of the desired functionality without breaking your MVC structure at all.
Consider the following simple class with one static function:
<?php
class My_DebugHelper
{
public static function dump()
{
$ns = new Zend_Session_Namespace('the_namespace'); // the namespace you refer to with the developer flag
$debug_mode = Zend_Registry::get('debug_mode');
if (!isset($ns->isDeveloper) || !$ns->isDeveloper || !$debug_mode) {
return;
}
foreach(func_get_args() as $arg) {
Zend_Debug::dump($arg);
}
}
protected function __construct() {}
protected function __clone() {}
}
This code gives you:
The ability to call from anywhere in your application (model, controller, helper, view etc)
All of the protections to prevent it from being executed when called out of context
A simple base that you can expand upon
Depending on your needs, at least one thing you could do is make it static so it could store some of the information rather than access it each call, or add additional methods or specialized parameters so you could pass a Zend_View object to it if necessary and have data injected into the view.
You could call it from anywhere in your application and pass one or more values to dump:
My_DebugHelper::dump($someVar, $this->view, $model->getCustId());
I'm not sure how/what your view helper displays data currently, but hopefully that will help you merge your view helper into the generic class that you can call anywhere.

Can a site user pass their own arguments to model functions?

Are functions inside of models directly accessible by users?
Can a user pass arguments directly to a function in a model? Or, do arguments have to be passed through php?
In otherwords:
I have a model called notifications and in there a function called get_notifs($user)... I use the controller to call the function like the get_notifs($_SESSION['user_id']) (which is encrypted). I don't want someone to be able to call get_notifs() with anything but their $_session as a argument. What is the best solution?
Am I already okay?
Should I rename get_notifs() to
_get_notifs()?
Should I check the
$_SESSION['user_id'] in the method
itself?
Or, is there another better solution
than any of these?
I have a controller: ajax.php which loads the model notification
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
$this->load->model('notification');
$this->load->model('search');
}
function get_notifs()
{
$me = $this->session->userdata('user_id');
if ($e = $this->notification->get_notif($me))
{
...........
}
else{
echo "nothing was found wtf?";
}
.........................................................
model: notification.php
function get_notifs($user){
......
}
Your code is perfectly fine!
Am I already okay?
I Think so
Should I rename get_notifs() to _get_notifs()?
No, it's a public method so no need to make it look private.
Should I check the $_SESSION['user_id'] in the method itself?
No, this is the controller's job
Or, is there another better solution than any of these?
You only need a solution to a problem, and i don't see a problem here
it sounds liek your application may be used by people other then yourself, i.e the public developers, why would you want enforce developers to code things your way, that's going to make them upset at your application.
CI Only routes requests to a controller, the user cannot access a model or library or any other class, the route goes like so: /controller/method/param
the first segment will only ever load a controller file, the second will call the method in the param, passing any other variables such as param to that method.
Source: http://codeigniter.com/user_guide/overview/appflow.html
As you can see from the flow chart above, only the controller has access to the model's
If you'll only use it while in a session the best way would be this:
function get_notifs(){
if(!isset($_SESSION['user_id'])){
return false;
}
$user = $_SESSION['user_id'];
/* Your code here */
}
There's no point of requiring an argument when you'll only use the function with one specific variable which is also available globaly.
Edit: I don't know why you're using functions in your models. Doesn't make any sense, do you mean methods?

Class methods and instance methods in codeigniter, how can I use them?

I am very new to codeigniter but understand OOP and MVC as I do a lot of Rails development. One thing I haven't figured out yet is how to write a class level method in codeigniter and access it in a controller. For example, I have
<?php
class User_model extends Model {
function user_model()
{
parent::Model();
}
public static function get_total_users_count(){
$results = $this->db->query("SELECT * FROM bhr_users GROUP BY userid");
if($results){
return $results->num_rows();
}
return 0;
}
}
?>
I think what I have done here is established a class level method for my model that I should be able to call with User_model::get_total_users_count() Now in my controller which a previous programmer called "Welcome" I have something like:
<?php
class Welcome extends Controller {
function Welcome()
{
parent::Controller();
$this->load->model('bhr_model');
$this->load->model('user_model');
}
function index()
{
$invite = $this->uri->segment(3);
if($invite == 'invitefriends') {
$pagedata['invitefriends'] = $invite;
} else {
$pagedata['invitefriends'] = '';
}
$pagedata['numberofpeople'] = User_model::get_total_users_count();
$this->load->view('default_page', $pagedata);
}
}
The above method call to get_total_users_count does not work because it says because I am using the db method on a class level function in get_total_users_count. In other words $this has no db method when I reference a class.
So now my question is a bit more theoretical. I always thought that instance methods should only be used when a method is acting on a specific instance of an class. Makes sense, right? However, get_total_users_count is acting on all "users" and counting them. It just seems like that should be a class level method. Do you agree? If do, do you know how I can access the database from withing the framework inside a class level function?
Thanks!
Since you are not instantiating User_model, you must get the CI instance, then use that for your db queries.
Inside get_total_users_count():
$ci_ins =& get_instance();
$ci_ins->db->query();
You can make your class as a helper so it will not be load as a instance. Only the code will be included so you can just call it as:
$sample = class_name::method();
CodeIgnighter works is by instantiating your models as you load them. What Thorpe Obazee said is the correct codeIgnighter way to use your Model.
What you are asking is if you can use a static method as you'd expect in most circumstances, which just isn't how CI works.
To accomplish what you're after, mives points out get_instance() which is the correct way to get at the main CI object. I use that way myself to do what you're doing.
get_total_user_count is more of a function for a user table gateway.
User model should have things like getUsername and getLastLogin.
User Table Gateway should have things like findUserById, createNewUser, and getTotalUserCount
$pagedata['numberofpeople'] = $this->user_model->get_total_users_count();
That's the CI way.

Passing parameters to controller's constructor

I have a controller which has several methods which should all share common informations. Let's say my URI format is like this:
http://server/users/id/admin/index
http://server/users/id/admin/new
http://server/users/id/admin/list
http://server/users/id/admin/delete
I need to retrieve some informations from the database for id and have them available for all methods instead of writing a line in each of them to call the model. How can I do this?
class users extends Controller {
private $mydata = array();
function users()
{
parent::Controller();
....
$this->mydata = $this->model->get_stuff($this->uri->segment(2));
}
function index()
{
$this->mydata; //hello data!
}
Here I simply hardcoded the array (which probably is a really bad idea). Nevertheless you can store the data in a codeigniter session if you need to. Codeigniter can store this data in a cookie (if it's total is less than 4kb) otherwise you can store bigger blobs of data in the database (see the docs on how to do this).
See: http://codeigniter.com/user_guide/libraries/sessions.html
Subsection: Saving Session Data to a Database
Here's some session exercise:
$this->session->set_userdata('mydata', $mydata);
....
$mydata = $this->session->userdata('mydata');
If this cannot be solved from CodeIgniters Hook mechanism, you could override the constructor method in your controller and call your own. Judging from their SVN repository you'd probably would do something like
class YourController extends Controller
{
function YourController()
{
parent::Controller();
$this->_preDispatch();
}
function _preDispatch()
{
// any code you want to run before the controller action is called
}
Might be that the call to preDispatch has to be before the call to parent. Just try it and see if it works. I didnt know they still use PHP4 syntax. Ugh :(
Based on your url structure, and the fact that codeignitor uses a MVC pattern, I'm assuming you're using mod_rewrite to format the url path into a query string for index.php. If this is the case, the value of "id" should be available at $_REQUEST['id'] at any point in the execution of the script...

Categories