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 some doubts about how controller works in CodeIgniter.
1) In Spring MVC I have a controller class with some annoted method, each method handle a specific HTTP Request (the annotation defines the URL handled by the method) and return the name of the view that have to be shown.
Reading the official documentation of CodeIgniter it seems me that the logic of this framework is pretty different: https://www.codeigniter.com/userguide3/general/controllers.html#what-is-a-controller
So it seems to understand that in CodeIgniter is a class that handle a single URL of the application having the same name of the class name. Is it correct?
So I have this class:
class garanzieValoreFlex extends CI_Controller {
.....................................................
.....................................................
.....................................................
function __construct() {
parent::__construct();
$this->load->helper(array('form', 'url'));
$this->load->library(array('form_validation','session'));
}
public function reset() {
$this->session->unset_userdata("datiPreventivo");
$this->load->view('garanziavalore/garanzie_valore_questionario_bootstrap',array());
}
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);
}
public function back() {
$this->load->model('Direct');
$flagDeroga = "true" ;
$this->session->userdata("flagDeroga");
$data = $this->session->userdata("datiPreventivo");
$this->load->model('GaranzieValoreFlexModel');
//$this->load->view('garanziavalore/garanzie_valore_questionario_bootstrap',$data);
$this->load->view('garanziavalore/index_tornaIndietro_bootstrap',$data);
}
.....................................................
.....................................................
.....................................................
}
So, from what I have understand, basically this controller handle only the HTTP Request toward the URL: http://MYURL/garanzieValoreFlex.
So from what I have understand the method performed when I access to the previous URL is the index() that by this line:
$this->load->view('garanziavalore/index_bootstrap',$data);
show the garanziavalore/index_bootstrap.php page that I found into the views directory of my prohect (is it a standard that have to be into the views directory?)
Is it my reasoning correct?
If yes I am loading the view passing to id also the $data variable that I think is the model containing the data that can be shown in the page, this variable is retrieved by:
$data = $this->session->userdata("datiPreventivo");
What exactly does this line?
The last doubt is related the other back() method that I have found in the previous controller: is it a method of CodeIgniter CI_Controller class or something totally custom defined by the developer that work on this application before me?
A controller can handle more than one URL and the class garanzieValoreFlex is an example of such a class.
The URL http://MYURL/garanzieValoreFlex will call the index method.
The URLs http://MYURL/garanzieValoreFlex/back and http://MYURL/garanzieValoreFlex/reset will call the back() and reset() methods of the class respectively. These two function are custom additions to the extended class CI_Controller.
Codeigniter (CI) URLs follow the pattern example.com/class/function/argument/
The function and argument segments are optional.
When a URL uses only a class name such as example.com/class then CI will look for and call the index() method if it exists. If index() does not exist you will get 404 Page Not Found display.
Your reasoning about $this->load->view('garanziavalore/index_bootstrap',$data); is correct. It is standard to put such files in the views directory. Optionally, subdirectories of views can be used as in /views/garanziavalore/.
CI uses a file structure that associates different classes (libraries) with certain paths. Controllers, Models and View classes are stored in their respective folders. Then the loader class will know exactly where to start looking for any given "type" of class. For instance, the call to $this->load->view('garanziavalore/index_bootstrap',$data); tells the loader class to get the file index_boostrap.php from the /application/views/garanzivalore/ directory. The code $this->load->model('GaranzieValoreFlexModel'); tells the loader to use the file GaranzieValoreFlexModel.php in /application/models/.
Find documentation of the loader class here.
The line of code
$data = $this->session->userdata("datiPreventivo");
is calling the userdata method of the session class (library). Think of session data as an array. If the array was defined this way. (This is only pseudo-code for what is accomplished).
$userdata = array(); //empty array structure
The call $this->session->userdata("datiPreventivo") is in effect returning the value of $userdata["datiPreventivo"].
Your reasoning is wrong. I would really recommend you to read the official codeigniter tutorials so that you may understand how the MVC works:
Below are the links
Codeigniter 2:
http://www.codeigniter.com/userguide2/
Codeigniter 3:
http://www.codeigniter.com/user_guide/
CI controllers handles different urls. If you create a function called index in a controller, it will be loaded automatically when the controller is accessed. For your case, http://MYURL/garanzieValoreFlex should access the function.
To access any other function, you will need to http://MYURL/garanzieValoreFlex/**MyFunction**
(Read more http://www.codeigniter.com/user_guide/general/urls.html?highlight=url#codeigniter-urls) The back function is a user defined function.
Related
I am newbie to codeigniter.my problem is let suppose my baseurl is
www.xyz.com
Now I have function like this
class Front extends MY_Controller {
public function index()
{
$this->__front_template('index');
}
public function about()
{
$this->__front_template('about-us');
}
Now if I have to call about I call like
www.xyz.com/front/about
But I need to call like
www.xyz.com/about
How can I do that ?
You can use codeigniter URI routing
Typically there is a one-to-one relationship between a URL string and its corresponding controller class/method. The segments in a URI normally follow this pattern:
Codeigniter URL Work as
example.com/class/function/id/
So you must route for this type. in application/config/routes.php add code like
$route['about'] = 'Front/about';
it works .!
You cannot call about directly as per your architecture, because of the following reason.
In CodeIgniter we have URL divided as:
http://www.example.com/controller_name/function_name
If the function you are trying to call is index function that above can be written as: http://www.example.com/controller_name/
So, in order to call about directly you need to create a separate controller for it with the name about and you can write about code in index function. And your requirement will be fulfilled.
There are other complex ways to, but as you have mentioned you are newbie. so this will be best.
If you want a more efficient way, look at the documentation:
https://www.codeigniter.com/userguide3/general/routing.html
In my current implementation of the MVC design pattern (demonstrated using PHP and CodeIgniter):
Let's say I have a "page" located at "www.mysite.com/blue/page" that is ultimately generated by the following (greatly simplified) files:
/libraries
session_lib.php
/controllers
/red
/white
/blue
page.php
/models
/red
/white
/blue
funky_class.php
page_model.php
/views
/red
/white
/blue
page.php
And here's an easy to understand controller:
// FILE: /controllers/blue/page.php
// Get some paramaters from URL
$params = $this->input->get();
// Use a library to do some stuff with these params with a session
$this->load->library('session_lib');
$this->session_lib->store_in_session($params);
// Use a very page specific class to do some funky stuff with the params
$this->load->model('blue/funky_class');
$funkified_params = $this->funky_class->funkify($params);
// Pass params to a model
$this->load->model('blue/page_model');
$data['output_from_db'] = $this->page_model->get_some_output_from_db($funkified_params);
// Send to view
$this->load->view('blue/page', $data);
And now the question...
What is the best procedure for these "funky" little page specific classes that don't interact with the database? In this example I store the little class with the models, and in some cases might just add additional methods inside the model class to do the funky stuff. Is this good practice? Or should the library and funky class both go inside the model so the controller is even skinnier (however the model might be used in other places without the need for sessions and funkiness)?
I would use a helper.
When a helper is loaded, that function will be available in the global scope so you can call it anywhere.
They're great for small, stand-alone functions that do only one thing that is not necessarily related to code in a model or library
Helpers especially excel for me when converting things between one format or another (slugify, convert_timezone, change_query_string) or doing little tasks that you don't want to think about (force_ssl, is_image, uri_string)
funkify() seems like an appropriate helper function that may prevent a lot of repeated code.
Here's the codeigniter documentation page on them: http://ellislab.com/codeigniter/user-guide/general/helpers.html
If you're in a situation where the helper function is so specific it will be only used in one place, you can still use a helper. Name the helper after your controller, page_helper.php for example.
page_helper.php
function funkify($params) {
// do funky stuff
return $funky_params;
}
then in your controller:
class Page extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('page');
}
public function page() {
// do stuff
$funky_params = funkify($params);
// do more stuff
$this->load->view('blue/page', $data);
}
I have no excuse for it, but sometimes if I am in a situation where I need a razor specific function that will only be used on one location (say, a controller) ever, I will put it right in the controller's file. You can paste a function outside of the class definition and it will act like a helper and be available globally (as long as that controller is loaded). You can also define functions inside of a view. Yucky, but possible. I don't like to do it often because it's unusual and not expected (by myself or other developers)
I’m learning CI coming from a non MVC OOP in-house framework, so I’m still confused on a bunch of things, I don’t always understand what is normal OO programming VS. things that done the code igniter way. Anyway I’ll try to explain my problem:
I have one controller, called Admin which extends CI_Controller.
I made a class (let’s say custom class meaning is something I made not part od CI) I put that class in the library folder, that class extends CI_Controller as well (that extension allowed me to have load method and some other CI methods).
From my Admin controller, I’m loading my custom class (named “ComponiPannello” since I’m italian ), this way:
$parameters = array('baseUrl' => $this->baseUrl);
$this->load->library('ComponiPannello', $parameters);
everything works perfectly my “ComponiPannello” does hits job and returns something I need for my Admin view.
Now I wanted to load a model right after that class, because I need to pass more info to the Admin view, those info are stored in the DB, I have a specific model to pull those extra info, so I added a few lines and the code looks as follow:
$parameters = array('baseUrl' => $this->baseUrl);
$this->load->library('ComponiPannello', $parameters);
$setup = $this->componipannello->return_data();
$this->data = array_merge($this->data, $setup);
$this->load->model('categories_model');
$this->data['categories'] = $this->categories_model->get_categories();
were $this->data is what I’m passing to the Admin’s view.
Few more info:
as I said both Admin controller and my custom class ComponiPannello extends CI_Controller
in ComponiPannello I have this constructor:
function _construct($params) {
parent::_construct();
$this->load->library('session');
$this->baseUrl = $params['baseUrl'];
}
if I move the $this->load->model part before the $this->load->library I get no errors everything works and returns the correct data, but I would like to learn what I’m doing.
if I keep it as I have it the error I get is the following:
Fatal error: Call to a member function get_categories() on a non-object in ... on line ...
I hope I was able to explain my issue in a way that is clear enough for you to help me, thanks in advance for the time spent.
Luke
Your problem is probably coming about because you are loading another controller as a library, when in fact, it is not a library.
You can load libraries, helpers, etc from a library like this:
$CI =& get_instance();
From within your library, instead of $this->load->helper() to load a helper you would now use $CI->load->helper().
More info on this is available in the CI documentation: http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html
Whay u use database object in ur library?
Utilizing CodeIgniter Resources within Your Library.
To access CodeIgniter's native resources within your library use the get_instance() function. This function returns the CodeIgniter super object.
Normally from within your controller functions you will call any of the available CodeIgniter functions using the $this construct:
$this->load->helper('url');
$this->load->library('session');
$this->config->item('base_url');
etc.
$this, however, only works directly within your controllers, your models, or your views. If you would like to use CodeIgniter's classes from within your own custom classes you can do so as follows:
First, assign the CodeIgniter object to a variable:
$CI =& get_instance();
$CI->load->helper('url');
$CI->load->library('session');
$CI->config->item('base_url');
etc.
This might be a bit hard to comprehend so I apologize in advance if this is not clear enough.
I'm writing my own MVC framework and am once again stuck.
I am in the process of writing the controller classes for the framework. Basically this is how it works:
Instantiate class coreController which extends abstract class
coreController sets controller to be loaded by interpreting query string
query string values stored in variables
other variables assigned values
new controller is loaded
new controller checks if an action object needs to be instantiated.
new actioncontroller is loaded
action controller checks if it is the final object required.
action controller is returned as an object to be referenced during the rest of the script.
generic $controller->method() can be called and references final controller loaded.
Another overview:
coreController
pageController
pageControllerActionAdd
return as object to start
$controller->something(); //References pageControllerActionAdd
Esentially what I want to be able to do is be able enter a url like:
http://www.mywebsite.com/page/modify/
and have the script pull up the PageModifyController as a variable so I can execute it's methods.
If you can tell me a better method for what I am doing please go ahead. You don't have to write any code, just the idea would be great. It is just that the way I am currently doing is very confusing and hard to debug. I will end up with multiple nested objects and I don't like the concept of that.
I've been reading a lot of other source code and found that it too can be quite sophisticated.
I actually created a framework that works along the lines you are trying to implement. I think what you are missing is a RoutingHandler class. Routing is the physical manipulation of the URL, which tells your application which Controller to load, and which Action to run.
In my world I also have Modules, so the basic routing scheme is
Module -> Controller -> Action
These three items map to my URI scheme in that fashion. Variables can be appended also like so...
http://www.domain.com/module/controller/action/var1/val1/var2/val2
So, what happens after the URI is parsed, and control is passed over to the appropriate controller and action? Let's make some code up to demonstrate a simple example...
<?php
class indexController extends Controller {
protected function Initialize() {
$this->objHomeModel = new HomeModel;
$this->objHeader = new Header();
$this->objFooter = new Footer();
$this->objHeader
->SetPageId('home');
}
public function indexAction() {
$this->objHeader->SetPageTitle('This is my page title.');
}
// other actions and/or helper methods...
}
?>
In the Initialize method, I'm setting some controller-wide stuff, and grabbing an instance of my Model to use later. The real meat is in the indexAction method. This is where you would set up stuff to use in your View. For example...
public function randomAction() {
$this->_CONTROL->Append($intSomeVar, 42);
}
_CONTROL is an array of values that I manipulate and pass onto the View. The Controller class knows how to find the right template for the View because it is named after the Action (and in a sibling directory).
The Controller parent class takes the name of the action method and parses it like so...
indexAction -> index.tpl.php
You can also do some other fun stuff here, for example...
Application::SetNoRender();
...would tell the Controller not to render inside a template, but just complete the method. This is useful for those situations where you don't actually want to output anything.
Lastly, all of the controllers, models, and views live inside their own Module directory like so...
my_module
controllers
indexController.class.php
someotherController.class.php
:
:
models
HomeModel.class.php
:
:
templates
index.tpl.php
someother.tpl.php
:
:
I can have as many Modules as I need, which means I can separate functionality out by Module and/or Controller.
I could go on, but I'm writing this from memory, and there are some wrinkles here and there, but hopefully this gives you food for thought.
can anyone tell me how do i access model from view in codeigniter?
Load a model on the controller
$this->load->model('yourmodel');
Assign this model to a var like this
$data['model_obj'] = $this->yourmodel;
and assign this data array to your view template
Use $model_obj object on the view template for calling model methods
$model_obj->some_method()
Hope this helps ...
See the thread:
View Calling a Model
By the way why do you need to access the model from the view, you can send the model data to the view from the controller too which is the usual and better approach.
As a good note, keep your processing logic out of the view, you should use controller instead.
CodeIgniter's $this->load->model() returns absolutely nothing. Look at it: system/libraries/Loader.php.
This will output absolutely nothing:
$model = $this->load->model('table');
print_r($model);
And this next example will give you the fatal error Call to a member function some_func() on a non-object:
$model = $this->load->model('table');
$model->some_func();
It doesn't matter whether that function even exists, $model is not an object.
The thing to do is have a method in your model that returns data, then call that function and pass the results to your view file:
$this->load->model('table');
$data = $this->table->some_func();
$this->load->view('view', $data);
PS: How is the only answer you've accepted the absolute wrong thing to do?
You can use following code:
$ci = &get_instance();
$ci->load->model('your_model');
$ci->your_model->your_function();
Note: You have to call your model in your controller. Its working fine
In cases when you want to access a model function from within a shared view , you don't have to load the needed model in every controller that will call that view. you can load the model inside the view itself by using the following code :
$ci =&get_instance();
$ci->load->model(model_name);
$ci->model_name->function_name();
in older versions of codeigniter the following code used to work :
$this->load->model('model_name');
model_name::function();
but when tested on CI 3.1.9 it throw the following error
Message: Undefined property: CI_Loader::$model_name_model
Note: I use this technique in template views (sidebar, menus ...etc) which is not used everywhere in my application , if you want to access a model from anywhere in your application considre loading this model globally by adding it to the autoload array in application/config/autoload.php
Since $model is not an object, you can make a call to the model "table" using "::" scope resolution operator, which can call the function of the class itself without any object instance.
$this->load->model('table');
table::some_funct();
Note: you also need to make the function "some_funct" static inside your model "table".
Hey. You can access from view to models the same mode as you access on its controller. Remember that the view access to models that import its controller.
in the original UML I've seem for MVC architecture, view calls methods in model..
http://www.as3dp.com/wp-content/uploads/2010/02/mvc_pope_krasner.png
..but in practice with PHP apps, because there is no persistence to track state changes in objects between requests (or at least not efficiently), I find it better to keep all model method calls in controller and pass the result to view if possible.
you can add your model's name to config -> autoload model
$autoload['model'] = array('model_name');
this success for me
You can access basicly a method from view in codeingiter.
public function index()
{
$this->load->model('persons');
$data['mydata'] = $this->persons->getAllSessionData();
$this->load->view('test_page', $data);
}
in view
print_r ($mydata);
my function returned an array.