should I make a class for every page in Codeigniter - php

Mostly this question is not about programming, it's like the how to use question.
and as I said above, should i make a class for every page in codeigniter? Or I can make function's for every page? if both is right, which one is better?

If you want to make sections/pages like.. "/widgets/view/1" or "/widgets/edit/1" or "/widgets/delete/1" your code would be:
class Widgets extends CI_Controller {
public function view($id)
{
//Go get widget by id $id
}
public function edit($id)
{
}
public function delete($id)
{
}
}

Please check CI Routing http://ellislab.com/codeigniter/user_guide/general/routing.html
You can use 1 controller class with 20 functions for each page or you can have 4 controllers with 5 pages etc...

It depends on the complexity and similarity of your pages. If they are really alike, it could be a waste to create lots of classes, but in general I would create a class per page at least.

Related

PHP late static bound referencing

Situation
In this web app I am building there is a "bootstrap" sequence that defines (through constants) and initiates an extended controller. Currently, the controller keeps track of assets (script files, css, etc.) that will be deployed at the later render stage through a series of static variables. I will simplify the code here, think of it as pseudo-PHP.
/* CONTROLLER CLASS */
class Controller {
protected static $aryScriptFiles = array();
public function __construct() {
/* Behaviour */
/* Some logic that identifies/calls Home_Controller method Index */
}
public static function Add_Script($strFileName) {
static::$aryScriptFiles[] = $strFileName;
}
}
/* HOME_CONTROLLER CLASS */
class Home_Controller extends Controller {
protected static $aryScriptFiles = array('default', 'carousel', 'etc');
protected function Index() {
/* Behaviour */
/* Load the view as an include. It is "part" of the User_Controller */
}
}
/* EXAMPLE_HELPER */
class Example_Helper {
public static function Test() {
/* THE NEXT LINE IS IMPORTANT FOR THE QUESTION */
$objController = CONTROLLER;
$objController::Add_Script('dominoes');
}
}
/* INDEX VIEW FILE */
<h1>Welcome!</h1>
<?php
echo get_class(); <-- Would echo 'User_Controller'
Example_Helper::Test();
/* Simplification of render process */
foreach(static::$aryScriptFiles as $strFileName) {
/* Render the HTML script tag */
}
?>
Flow
Ok, given the above there is a bootstrap that ends up calling User_Controller. For examples sake, I have simply defined them to let you know what state the script will follow.
$strControllerName = 'User_Controller';
define('CONTROLLER', $strControllerName);
$objController = new $strControllerName();
What you end up with is the aryScriptFiles array having 4 entries and this works great.
Problem
Before reading on, please note I do not want to use magic methods, globals or have to pass a reference of the controller name to the Helper function.
I would like to try and remove the line in the helper file that pulls the current controller name to a variable from the constant.
$objController = CONTROLLER; <-- I want this to shoo shoo
If I were to just try and use the following, the script file that gets added by aid of the Helper is part of the original Controller array as opposed to the Home controller.
Controller::Add_Script('dominoes'); <-- Will not be part of the Home_Controller array
Question
Please can I have some opinions from the SO community on what you feel the best approach to tackle this would be taking in to account that the controller name will differ? My primary objectives in this exercise are:
Keep the View file VERY simple
Keep the Helper files simple.
Avoid the need to add any code more than necessary to the Home_Controller
I'm currently thinking that one of the best options would be to host the "assets" within a seperate class, just want to know whether it is possible.
Thanks for reading.
First of all, think about your seperation of concerns. Should it really be the responsibility of a controller to manage assets?. Why did you made the method for adding assets static in the first place?
I do not want to use magic methods, globals or have to pass a reference of the controller name to the Helper function.
What are you expecting? If you try to force a class to depend on another class in a completely different scope and context your only option is to use ugly hacks to make your object globally accessible.
Dependency Injection to the rescue
Why should your helper know about what controller and how the controller is treated from the outside?
The only thing your helper should do is to operate with the controller (in your case). It should not try to magically detect what controller is being used. It should just take a controller and operate with it.
class Example_Helper {
public static function Test($controller) {
$controller::Add_Script('dominoes');
}
}
Example_Helper::Test($objController);
Since the addScript() method and the $aryScriptFiles property is static anyways, you could also just call the method in the helper on the parent controller. It would make no difference.
Also why do you want to talk to your controller from the view? The view should be "dumb" it should not be able to hold and operate with data except those that were passed to it by the controller.
Wouldn't it make more sense to add functionality to your controller or one of it's services that passes the required assets to your view, instead of forcing the view to get it's data from from the controller by itself?
I think there are a few logical flaws in your code here. Especially your usage of static properties and methods. If you could clarify that a bit I could go in detail a bit.
Apart from architectural concerns (assets should indeed be managed by a separate AssetManager) your problem can be relatively easily solved because of PHP's rather peculiar own architecture, specifically exposed through methods like get_called_class. This allows you to write code like this:
$assets = []; // Global for brevity of example
class Base {
static function addScript($script)
{
global $assets;
$myName = get_called_class();
$assets[$myName][] = $script;
}
}
class Derived extends Base {
public function __construct()
{
self::addScript('test');
}
}
$foo = new Derived();
var_dump($assets);
Which will then output the following:
array(1) {
["Derived"]=>
array(1) {
[0]=>
string(4) "test"
}
}
Note that using get_class instead of get_called_class would here show the array's name as Base instead of Derived, while Derived is what you need. This way you can embed helper functions in Controller, which automatically derive the class name and forward it to the central asset manager.

Can I call controller and model from view?

I have a problem with PHP/MVC.
This is my index controller.
<?php
class Index extends Controller {
function __construct() {
parent::__construct();
}
function index() {
$this->view->render('header');
$this->view->render('index/index');
$this->view->render('footer');
}
public function test(){
$this->model->test();
}
?>
And this, index model.
<?php
class Index_Model extends Model{
public function __construct() {
parent::__construct();
}
public function test() {
return $this->db->select('SELECT text FROM test');
}
}
}
How can I use this in "index view"?
Of course you can call controller and model methods from your views (if it wasn't possible then you'd need to put EVERYTHING in your view). The idea of MVC isn't complete separation (as some people wrongly think) but separation of the logic. This means that it is fine to pass data between the different parts of the MVC arch; the idea is that you want to try to make sure that the logic in each part is logic that is appropriate for that part.
Many people will over complicate this in search of some ideal which is just silly. I would get rid of the controller method all together and reference the model method directly in the view if all you are doing is grabbing some data to be displayed in the view. There is no reason to waste time and effort passing these results to the controller just to be passed back to the view. You will thank me for this advice once you make a truly large site and look at all of the effort you would have spent doing that (and then later maintaining all of it).
My philosophy is that a controller should be used for just that (controlling the application logic). If you want to display a sidebar with a list of the most recent post that has NOTHING to do with the controller so it shouldn't add any code to it. Save yourself some headache and call the model from the view. In the end your code is going to make more sense if you do.
In response to your question: You cannot use your controller method in the view because it doesn't return anything.

Creating functions in a quick way in codeigniter

As you know, in codeigniter a function name in a class becomes url like :
class Example extends CI_Controller {
function sayHello() {
echo "Hello";
}
}
To display the content of function simply you can show it by using:
www.mydomain.com/example/sayhello
My question is, instead of writing all my function names one by one, how can i form these functions using a loop or by fetching function names from database? For example, i have 100 function name in my database. is it possible to do it writing clear and short code or should i write all functions manually? Thanks...
This has nothing to do with creating functions. Your problem is routing. Solve that:
class University extends CI_Controller {
public function _remap( $university_name )
{
}
}
More info: http://codeigniter.com/user_guide/general/controllers.html#remapping

Global Vars in CodeIgniter

I want to save some global vars to use in the website, like current user id, current user lever, and so on. Where is the best place to do it, or is it possible?
Setting it into constants.php is not working since "$this" is not recognized there.
The principal reason why I want this is because i don't like using sessions (I consider writing strings like $this->session->userdata('session_name') not so practical, writing something like CURR_UID is more easy to do it and read as well)
It's possible, but it isn't the way that Codeigniter was designed. Sessions are really the place for this kind of thing (namely, stuff that persists from one page view to the next), but you could wrap the session calls up in a library for beauty's sake if you wanted. Something like this:
// in libraries/User.php
class User {
protected $ci;
public function __construct() {
$this->ci = &get_instance();
}
public function id() {
return $this->ci->session->userdata('user_id');
}
// etc, etc.
}
Once you've written a few more helpers like id(), you can use them to access the relevant variables elsewhere in your application:
$this->load->library('user');
echo 'Current user ID is: ' . $this->user->id();
What you can do in this case is create a class My_Controller extends CI_Controller. Sort out all the functionality that you would need before actually loading any of the specific controller functionality.
Then any subsequent class you create you can do: class Whatever extends My_Controller.
Edit: I forgot to mention you should put the My_Controller class within the Application > Core folder.

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.

Categories