Codeigniter organizing controllers structure - codeigniter

Let's take for example a small social network site. One of modules are also Quizzes. Quizzes module have the following sections:
-Create quize
-Edit quize
-Quize view
-Browse quizes
-Send quize to friend
I am wondering what would be the best way in this case. One of option is to create for each module section another controller.
controllers/create_quize.php
controllers/edit_quize.php
controllers/quize_view.php
controllers/browse_quizes.php
controllers/send_quize.php
Another way would be to create single controller for entire module with many functions. None of options are ok. In first way, this could mean to have more than 30 controllers in my controllers folder (having in mind that quizess is just one of many modules). Second option is not ok because a single file will have many functions and won't be easily scanned to developer.
I was also thinking to create many controllers, but organizing them into subfolders. Anyway condeigniter doesn't have this option without modification.
Tnx!

You only need a single controller for your quizzes. Your quiz controller might look like this :
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Quiz extends CI_Controller {
function __construct()
{
parent::__construct();
}
function index()
{
// Index page. List all quizzes here, perhaps as an replacement to /browse
// /quiz/
}
function create()
{
// Create a new quiz
// /quiz/create
}
function edit($quiz_id)
{
// Edit quiz with $quiz_id
// /quiz/edit/1
}
function browse()
{
// Index page. List all quizzes here, perhaps
// /quiz/browse
}
function send($quiz_id)
{
// Send/share page
// /quiz/send/1
}
}
CodeIgniter is a Model-view-controller framework. You may want to review how it's structured: http://codeigniter.com/user_guide/

Related

Laravel: Grab data from the Controller from inside a view composer

Atm I'm creating this view composer for fun. It is collecting .js filenames and then passing it to the layout to be linked. The filenames used depend on the current page. For example a lower ranked page like Slides, doesn't include ajax requests used in UserManagement. Please don't ask me why I would do this xD. Im planning to validate requests anyway. Just being bored.
Anyways, as I'm quite new to laravel I'm still looking for more efficient ways to do things.
Atm Im accessing the file names staticly. The Controller now looks like this
class Controller extends BaseController
{
public static $js_file_names = [];
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
In the pagecontroller I construct the filenames:
class SlidesController extends Controller
{
public function __construct()
{
parent::$js_file_names = ['ccs', 'ajax-updates'];
}
And finaly I retreive them inside the registered Viewcomposer like this:
(during development $use_filenames has all files as default)
public function __construct()
{
$filenames = Controller::$js_file_names;
if( !empty($filenames) )
$this->use_filenames = $filenames;
var_dump($this->use_filenames);die;
}
It all seems to be working fine, but the big question is, is there a better way to access controller data from inside a viewcomposer? Every time I try to google this, I get results like 'passing data to views' etc, which is not rly the problem.
Update:
Another idea I had is to store all the filenames to be used in an array inside the viewcomposer itself, and check if the current page exists in that array. This would keep the controllers cleaner.
Using a view composer doesn't really make sense in this situation. Since your controllers already 'know' which files they intent to share, you may as well just pass them to the view like so:
class SlidesController extends Controller
{
public function __construct()
{
View::share('user_filenames', ['ccs', 'ajax-updates']);
}
}
A composer is more for sharing concrete elements such as collections of users, a service provider or some other class instance, for example.

CodeIgniter URI Routing: remove method name index from URL

I am working with CodeIgniter (V:2.2.6) and I have a simple class User with some basic methods like create, update, edit, delete and index. For the index function, I am using an argument $user (which is the second URI segment) in order to display some information regarding that user. So the default URL looks like:
/user/index/john
to display some information about the user 'john'.
Now, I want to remove the term 'index' from the URL, so that it looks like:
/user/john
For that purpose I have added the following rule in routes.php.
$route['user/(:any)'] = "user/index/$1";
It serves the purpose, but it prevents accessing other functions like /user/create and goes inside /user/index automatically. To solve this problem, I can not see any other way except manually adding routing rules like
$route['user/create'] = "user/create";
for each method of the User class, which is not cool at all. So, please can anyone suggest me a better way of routing under the current circumstances?
Here are my codes:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class User extends CI_Controller {
public function index($user = '') {
echo "index!";
}
public function create() {
echo 'create!';
}
}
Note: I have gone through the CodeIgniter documentation for URI Routing and another similar question here, but could not figure out a promising solution. And please don't suggest for CodeIgniter version update.
I'm not sure, if this is the answer you like, but i think it should work.
Just put this function in your user controller.
public function _remap($method)
{
if (method_exists($this, $method))
{
$this->$method();
}
else
{
$this->index($method);
}
}

Get data generated on another controller

I have a simple logic problem. I'm starting on use CodeIgniter and I'm understand the Controller concept now. The view, for instance, is used only to generate content (not pre-proccess data), controller to get all infos need to view. Fine.
My problem is: I have a poll that is called as /poll/1 from an iframe, and I like to print it in other moment on another controller. This path is relatives to Poll::index(1) (logically talking) and I'm on Content::index().
I don't found explanation for cases like that on the CI UserGuide.
How I do?
Thanks.
Edit: I'll do an example code:
class Blog extends CI_Controller {
function index(){
// Do some prints
// Executes Poll::index(1), but store on some string
// Do some prints
}
}
class Poll extends CI_Controller {
function index($id){
// Do some prints
}
}
The idea is that: /poll/1 works and /blog too (but this second will print more content, with the poll).
hummm interesting i think using ob_start() might just work for you, if it was me i would rather use a ajax call to display poll data
here is the code.
class Blog extends CI_Controller {
function index(){
// Do some prints
// Executes Poll::index(1), but store on some string
ob_start();
Poll::index(1)
// You can now use this $output value to display or store in db or store in session,
// but remember CI session can only hold upto certain length as it uses cookie
$output = ob_get_contents();
ob_end_clean();
// Do some prints
}
}
class Poll extends CI_Controller {
function index($id){
// Do some prints
}
}
One way which is my favorite is use one as a super class so class Poll extends blog. This allows your poll to take advantage of your blog methods. Then you can use any parent methods and load the proper views in which ever class#method you want.

How skinny should controllers, and how fat should models be?

Exactly how skinny should a controller be? I understand putting all of the business logic inside the models, but what about other things.
For example, say I was writing a blog site where each user can have multiple posts. Currently, the user would create posts by visiting the posts controller and running the create action. Here is a little sample of what would happen currently.
class Controller_Post extends Controller {
function action_create() {
if ( ! empty($_POST)) {
$post = new Model_Post;
$post->user_id = $this->logged_in_user->id;
$post->values($_POST);
if ( ! $post->create()) {
echo 'Error';
}
else
{
echo 'Saved';
}
}
}
}
My question is, what would stop me from putting the above logic in the user model, like so.
class Model_User extends Model {
function create_post($post) {
$post = Model::factory('post')->values($post);
$post->user_id = $this->id;
if ( ! $post->create()) {
return FALSE;
}
else
{
return TRUE;
}
}
}
If it were done this way, the controller would be even smaller than what I put. It makes more sense to me because the user is the one creating the post, so I think it should be in the user model as opposed to the controller.
If it helps, Im using the Kohana framework.
Thanks
Controllers should be directing traffic. Models are for where your business logic goes, so in general your second example would be "correct mvc".
Basically what a controller should be doing is requesting input, telling models to change state (they do the actual state change themselves), and determining which view to display (if any).
I have many controllers which simply are like so:
class Controller_Foobar extends Controller
{
public function action_index() {}
}
And if they need to process $_POST input, they grab that data, and send it off to the model, then the view.
Keeping all that logic inside your models lets you easily reuse it, and it's more maintainable and testable.

Codeigniter common templates

Let's say that I have a website that has 100 different pages. Each page uses a common header and footer. Inside the header is some dynamic content that comes from a database.
I'd like to avoid having to have code in every single controller and action that passes this common code into the view.
function index()
{
// It sucks to have to include this on every controller action.
data['title'] = "This is the index page";
data['currentUserName'] = "John Smith";
$this->load->view("main_view", data);
}
function comments()
{
// It sucks to have to include this on every controller action.
data['title'] = "Comment list";
data['currentUserName'] = "John Smith";
$this->load->view("comment_view", data);
}
I realize that I could refactor the code so that the common parts are in a single function and the function is called by the action. Doing so would reduce SOME of the pain, but it still doesn't feel right since I'd still have to make a call to that function every time.
What's the correct way to handle this?
One way I have been doing this is to extend the default controller class. You can read up on extending classes with MY_Controller in the user guide. Inside this extended class you can include something that you ALWAYS want to do, like render the page header template before the main content, or authorise a users access etc.
class MY_Controller extends Controller {
function __construct()
{
parent::Controller();
//code to always do goes here
echo 'Always print this comment';
$this->load->view('partials/template_start');
}
}
Then you can have your normal controller class extend THIS class by using
class MyControllerNameHere extends MY_Controller {
function __construct()
{
//setup here
}
function index()
{
echo 'Only print this bit when this method is called';
$this->load->view('partials/MYPAGENAMEHERE');
}
}
There are other ways of doing this, I use a mixture of the above and William's Concepts Codeigniter Template library. Do a bit of searching - there are a few solutions for you.
I had a similar situation. I created an 'includes' folder, and in there put a file that had the repetitive code from my controllers. Then in the controllers just include('/path/to/includeFile.php');
Don't know if it's the "correct" way, but it works well for me.
I ran across this after a search of their site. http://codeigniter.com/wiki/Header_and_footer_and_menu_on_every_page/ I'll review this page and its links, then post my thoughts.

Resources