How to test controllers with CodeIgniter PART 2? - codeigniter

I am having difficulties testing Controllers in Codeigniter:
I use Toast but when I invoke my Home Controller class I get an exception that "db" is not defined. Has anybody an idea how to test this 1-1?
Thanks
class Home_tests extends Toast {
function __construct() {
parent::__construct(__FILE__);
// Load any models, libraries etc. you need here
}
function test_select_user() {
$controller = new Home();
$controller->getDbUser('foo#gmail.com','password');
assert($query->num_rows() == 0 );
}
}

As others have mentioned, CI doesn't let you call a controller from another controller. The short reason is that controllers always create response headers (even when you don't load any views or call the output class), and you aren't allowed to send two sets of HTTP headers to the browser.
While coding Toast, I tried to hack CI to allow this, but it takes some very hairy hacking of the Loader, and I came to the conclusion that you really shouldn't put any heavy logic in your controllers anyway. IMO, for proper MVC modularity, that stuff belongs in your models, libraries and helpers (which can all be unit tested with Toast).

You might need to edit your database connectivity settings in ../system/application/config/database.php

Related

Input validation in MVC

I need a little help regarding design of MVC .
Most of the tutorials of MVC and CODEIGNITER are doing input validation in controller. Is it a good practice ?Suppose we implement REST or SOAP API then we are going to have different controllers, and for all those controllers I need to replicate my code. Later if any of the validation rule is changed, it will get rippled into all controllers. Shouldn't all the validation should be inside Model instead of Controller ?
One more thing I would like to ask. As I am trying to keep my functions as cohesive as possible, I am getting one to one relation between functions of model and controller. Is it ok or I am doing things wrong ?
Regarding doing input validation in Controller
Ans. Yes, that is the generally accepted practice in most MVCs. However, during the past few years, due to the advent of AJAX frameworks and more adoption of JavaScript, many UI validations get done in UI itself(called client-side validations). These are generally displayed as javascript alert boxes and do not allow user to go ahead unless he fixes these errors. So, I would say Controllers/View helpers are de-facto places where validations are done but you should consider client-side validations wherever feasible. It also saves you trips to the server.
If you expose the same as functionality as SOAP/REST
Ans. Now-a-days you can annotate the same controller methods to make them work as web service endpoints. So, your controllers can service both web-based requests and also SOAP/REST requests.
But one note of caution - your form-beans/backing beans should be very well designed. I have seen code where hibernate model objects are used as form-backing objects. This makes it tricky when you generate a WSDL out of the form-backing objects as hibernate model objects may have many linked entities and one ends up with very complex xml structures in the request/response.
But still, if you design your backing-beans as fine-grained, i.e. not having complex objects, then you should be comfortably placed in using your existing controller/controller methods as web service endpoints for both SOAP/REST.
Regarding the validations being inside Model layer
Ans. You can use this thumb rule to determine where to place which validations -
Business validations should happen in models/services
complex client validations, which are not feasible in client-side, should happen in controllers/view helpers
UI validations (formatting/empty checks) should happen via client-side/javascript validations
Regarding one to one relation between functions of controller and model/service
Ans. Its fine. Just remember to have one controller method talk to its respective model method. And if multiple models are needed to service a request, then that model method should act as an aggregator of information from multiple models i.e. the controller should contact its main model and the main model should contact other models.
Is it a good practice? In my experience yes.
One thing to keep in mind is that any given controller can display an number of different pages. For example, consider a "Dashboard" which could have multiple tasks each of which requires its own page.
A rough pseudo-codeish "Dashboard" controller might look like this:
class Dashboard extends CI_Controller {
public function __construct(){
parent :: __construct();
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->load->model('somemodel_model');
}
public function index(){
//displays a task selection page with links to various tasks
}
public function admins(){
//some kind of interface to display and edit admin level users
}
public function users(){
//CRUD for dashboard users
}
}
With this controller the task selection page is opened with baseurl/dashboard, adminstrator's page with baseurl/dashboard/admins and user CRUD with baseurl/dashboard/users. Because each of these share the same Class, code needed by all/many of these pages (like validation) can be implemented in the constructor and/or with private methods. You probably already know all this. Keep in mind that AJAX responders can also reside in a controller using the same technique.
In regards to keeping the validation rules DRY and easing the work required for changes to rules CI can store sets of rules in a config file for easy reuse in multiple situations. Read about it.

How to load more than one controller in another controller in CodeIgniter

How to load more than one controller in another controller in CodeIgniter. The below code is i'm using. But it doesn't working. Only the controller which specified at first was work the second one is not working.
class A extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->controller('B');
$this->load->controller('C');
}
}
You shouldn't be loading other controllers. Each request should be handled by a single controller. If you require common behaviour you have the following options:
/application/core/MY_Controller.php and extend that class
Move the behaviour to a model
Move the behaviour to a library or helper
If you are unfamiliar with the MVC pattern, this forum post might help you. It's from an old thread, but the principles still apply.
There are various methods to do that.
One of them: you can try this.
//Load the controller you want
$this->load->library('../controllers/controller_name');
//and can call functions of that controller
$this->controller_name->function_name();
I hope this is helpful!

Access controller method from inside a model

How do I access a controller method from inside a model?
You don't.
Although it is technically possible, if you think that you need to, it suggests a flaw in your application's design.
The Controller layer is the backbone of you application and meant to handle requests from the user, talk to the Model layer, and stitch together the output in the View. Your Model layer should be blind to the Controller and View, but deal with data manipulation only. This is an over-simplified explanation of the MVC pattern (you can find resources for that elsewhere).
Your Codeigniter models should be reusable from any controller, and not dependent on them. There are many solutions to solve whatever problem it is that you have: You can pass data into a model in a number of ways, or you can use the result of a call to a model's method to perform an action in your Controller.
You can use like this:
class some_model extends Model
{
function getController()
{
$controllerInstance = & get_instance();
$controllerData = $controllerInstance->getData();
}
}

CodeIgniter - where to put functions / classes?

Am having problems understanding where classes should be kept in CI. I am building an application that describes / markets mobile phones.
I would like for all of my functions (i.e. getphone, getdetails etc.) to reside in one class called Mobile - I understand that this file should be called Mobile.php and reside in the controllers folder.
Can I then have multiple functions inside Mobile.php? E.g.
public function getphone() {
xxx
xx
xx
}
public function getdetails() {
xxx
xx
xx
}
Or do I need to put each function in its own class?
I'd really appreciate looking at some sample code that works. I've been going through the documentation and google for a few hours, and tried all sorts of variations in the URL to find a test class, but without much luck! I've even messed around with the routes and .htaccess...
All I am trying to achieve is the following:
http:///model/HTC-Desire/ to be re-routed to a function that accepts HTC-Desire as a parameter (as I need it for a DB lookup). The default controller works fine, but can't get anything to work thereafter.
Any ideas?
Thanks
Actually it works like this:
Controllers and Models go to their perspective folders as you know it
If you want to create functions that are not methods of an object, you must create a helper file. More info here :
http://codeigniter.com/user_guide/general/helpers.html
Now if you want to create your own datatypes (classes that don't extend Models and Controllers), you add them to the library folder. So if let's say you want to create a class "Car" you create this file:
class Car{
function __construct(){}
}
and save it in the libraries folder as car.php
To create an instance of the Car class you must do the following:
$this->load->library('car');
$my_car = new Car();
More information on libraries here:
http://codeigniter.com/user_guide/general/creating_libraries.html
Yes, you can have as many functions in a controller class as you'd like. They are accessible via the url /class/function.
You can catch parameters in the class functions, though it's not advisable.
class Mobile extends CI_Controller{
public function getPhone($phoneModel=''){
echo $phoneModel;
//echo $this->input->post('phoneModel');
}
}
http://site.com/mobile/getPhone/HTC-Rad theoretically would echo out "HTC-Rad". HOWEVER, special characters are not welcome in URL's in CI by default, so in this example you may be met with a 'Disallowed URI characters" error instead. You'd be better off passing the phone model (or any other parameters) via $_POST to the controller.
Classes can exist both as Controllers and Models, as CodeIgniter implements the MVC pattern. I recommend reading more about that to understand how your classes/functions/etc. can best be organized.
Off the top of my head, Pyro CMS is an application built with CodeIgniter and the source code is freely available. I'm sure there are others.
I think it's best you handle it from one perspective, that is; create a utility class with all your functions in it.
The answer to the question of where to put/place the class file is the "libraries" folder.
This is clearly stated in the documentation. Place your class in the libraries folder.
When we use the term “Libraries” we are normally referring to the
classes that are located in the libraries directory and described in
the Class Reference of this user guide.
You can read more on creating and using libraries Creating Libraries — CodeIgniter 3.1.10 documentation
After placing the newly created class in the libraries folder, to use just simply load the library within your controller as shown below:
$this->load->library('yourphpclassname');
If you wish to receive several arguments within you constructor you have to modify it to receive an argument which would be an array and you loading/initialization would then be slightly different as shown below:
$params = array('type' => 'large', 'color' => 'red');
$this->load->library('yourphpclassname', $params);
Then, to access any of the functions within the class simply do that as shown below:
$this->yourphpclassname->some_method();
I hope this answers your question if you have further question do leave a comment and I would do well to respond to them.

Code Igniter: Put in separate controllers or one?

So far, I create one controller for a site section with a method for each page - most are static pages, not requiring much logic or a model.
But where some of those pages are complex in functionality and need their own model, do I need to break them off into their own controllers? or is there a way to keep them in the one controller and load the model per method... probably the wrong thing to do
Totally agree with jondavidjohn's answer. I suggest just doing what works for you for now, and don't worry too much about overhead or doing the "correct" thing. You'll shortly realize what you need to do and how to be organized, and as far as overhead - Codeigniter is pretty lean, don't worry about optimization at this point - just get everything to work the way you want.
Take your first Codeigniter project and make it the best you can, but just consider it a throw-away app. Each time you work with it you'll learn more about how to use it, and especially if you keep reading and asking questions.
To answer your literal question: No, there's nothing wrong with loading the model per method. In fact, it can be "better" than loading in the __construct of your Controller, because it ensures you only load exactly what you need. So don't worry about it.
So far, I create one controller for a site section with a method for each page - most are static pages
There's nothing wrong with this, but to make things easier, you can use the same method for each of your static pages, and keep your urls the same. Something like this:
class Pages extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function index($page)
{
$this->load->view("pages/$page");
}
}
// config/routes.php
$route['page/(:any)'] = 'pages/index/$1';
This would map the url /page/my_first_page to the Page controller and call index() with the argument my_first_page. Then you can use this for all your static pages without dynamic data. You can take this a lot further, but it's an example of one option you can choose to avoid writing a new method for every static page.
Because Codeigniter is so convention-less, it does lead to questions of opinion like this.
In general though I would always advise that more modularity is better than less modularity, and you can never over-organize.
Just because something isn't "wrong" doen't make it best.
Only you can decide in the end, because you will be the one to maintain it.
You can load the model per method. It's not bad practice to do that.
$this->load->model('your_model');
Models typically aren't too intensive to load. You shouldn't worry too much about loading models unless you are trying to save ever single bite.
its good to use specific controller for each page , so that the application becomes light weight, and also need to create its on model. So the application expand its functionality it becomes easy to develop :
class Location extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->library('session');
}
public function index()
{
$data['title'] = "Hello world";
$this->load->view('locale_view', $data);
}
}

Resources