combining multiple controllers into one view - php

I'm using codeigniter I have this BuildTemplate function in my [HOME] controller that authenticates a user. I have another controller called [AJAXCONT] that has a function called search() that returns data to populate my search table in the view. I would like to retrieve that controller's data from it's search function right after I generate the $top_bar_data view. How can I code this. Is my approach correct here?
private function BuildTemplate($view, $data) {
if($this->session->userdata('logged_in_faculty'))
{
$session_data = $this->session->userdata('logged_in_faculty');
$top_bar_data['Firstname'] = $session_data['Firstname'];
$top_bar_data['Lastname'] = $session_data['Lastname'];
$master_data['f_top_bar'] = $this->load->view('f_top_bar', $top_bar_data, true);
//I WANT TO RETURN ALL DATA IN THE AjaxCont controller returned by the search function HERE //
//$search_data = (all data from my search function in AJAXCONT controller )
// $master_data['search_results'] = $this->load->view('search_results', $search_data, true);
}
else
{
//If no session, redirect to login page
redirect('login', 'refresh');
}
return $this->load->view('master', $master_data, true);
}

You should move all your functions to models, controllers should only retrieve the data from the models and output it by loading views. CodeIgniter's controllers are only called by URI/Routing, you cannot call a controller or controllers methods from anywhere else.
Create a model to work with users, a second model that does what your search does. Then, from controller call those in the order you wish.

Related

Codeigniter redirect() not working as intended

I have started working with Codeigniter. So, I have two controller Tasks and Project. In my Task Controller I have a function to edit an existing task and after the task is edited I want to redirect to the Projects controller's display method which takes a parameter as the project_id associated with the task.
Here is my task controller:
public function edit($task_id,$task_project_id){
$this->form_validation->set_rules('task_name', 'Task Name','trim|required');
$this->form_validation->set_rules('task_description', 'Task Description','trim|required');
if ($this->form_validation->run() == FALSE){
$result=$this->task_model->get_task($task_id);
$data['task_name']=$result->task_name;
$data['due_on']=$result->due_on;
$data['task_description']=$result->task_description;
$data['id']=$task_id;
$data['task_project_id']=$task_project_id;
$data['main_view']="tasks/edit_task";
$this->load->view('layout/user', $data);
} else {
$data['task_project_id']=$task_project_id;
$data['task_name']=$this->input->post('task_name');
$data['due_on']=$this->input->post('due_on');
$data['task_description']=$this->input->post('task_description');
$data['id']=$task_id;
if ($this->task_model->edit($data)){
$this->session->set_flashdata('task_edited' ,'Task Edited Succesfully');
redirect(projects/display/$task_project_id); THIS SEEMS TO BE THE PROBLEM .
}else{
$this->session->set_flashdata('task_edited_failure' ,'Task Not Edited Succesfully');
redirect(projects/edit);
}
}
}
Here is my Projects Controller with its index and display function :
public function index()
{
$data['projects']=$this->projects_model->get_projects();
$data['main_view']="projects/home_view";
$this->load->view('layout/user.php',$data);
}
public function display($project_id){
$data['task']=$this->task_model->get_tasks($project_id);
$data['project']=$this->projects_model->get_project($project_id);
$data['main_view']="projects/display";
$this->load->view('layout/user.php',$data);
}
So, in my task controller I am trying to redirect to the projects controller's display method using redirect(projects/display/$task_project_id) as the Projects Controller's display function is display($project_id). But this is redirecting to me the Project controller's index function. What is wrong with the redirect ? I thought the URL structure in CI was controller/function/parameter1/parameter2.
You made mistake in writing redirect function. It should be like as below.
redirect('projects/display/'.$task_project_id);
redirect('projects/edit');
redirect($uri = '', $method = 'auto', $code = NULL)
redirect() function in codeigniter uses the url you define in your root. You can't directly jump to controllers.

Is using if else statement to load view based on parameters after controller and action part of url efficient or is there a better way of doing this

I can have the following urls
www.example.com/accounts/
www.example.com/accounts/signup
www.example.com/accounts/signup/validate
www.example.com/accounts/login
for each case, accounts becomes my controller, and index, signup, signup and login becomes my actions (or methods) respectively. I have to render different views based on what my actions are. Here is an example of what my code looks like
index
$url_segments = explode('/', $url);
$controller = !empty($url_segments[0]) ? $url_segments[0] : 'home';
array_shift($url_segments); // removes the controller name from array
$action = isset($url_segments[0]) && !empty($url_segments[0]) ? $url_segments[0] : 'index';
array_shift($url_segments); // removes the action name from array
$controller = ucfirst($controller);
$controller = new $controller($url_segments);
$controller->$action();
controller class
class Accounts{
private $url_segments;
public function __construct() {
$this->url_segments = $url_segments;
}
public function index() {
// index code here
}
public function login() {
// login code here
}
public function signup() {
if (!isset($this->url_segments[0])) {
// url entered was: example.com/signup
} else if (isset($this->url_segments[0]) && $this->url_segments[0] == 'validate') {
// url entered was: example.com/signup/validate
}
}
}
from how my code appeared above, it can be seen that as parameters keep adding after the controller and action part of the url I'll need to keep using conditional statements to run the proper code as in the case of /signup/ and signup/validate. Is this method of using conditional statement to load view based on parameters efficient or is there a better way of doing this.
I would recommend you to make use of a routing system like Symfony Routing. There you could add a new Route for every url and redirect them to your specific controller.
Example Route:
$routes = new RouteCollection();
$routes->add('/accounts_signup', route('POST', "/accounts/signup", 'App\Controller\AccountController:signup'));
return $routes;
This route would call the signup method in the AccountController calss when www.example.com/accounts/signup get called with a post request.
I recommend you to use something like this. Even if this might be a bit complicated for the beginning, after reading (and understanding) the docs this will safe you a lot of time and it will make your code more readable as well.

CakePHP not sure if it's the right thing

I have this controller: Resales, and I am in the Administrator controller and need to create a new Resale.. how should I do that?
first option:
Administrator form calls /resales/addResales
second option: Administrator has a method addResale that loads the Resale model and inserts it.
What should I do?
thanks
Administrator controller shouldn't be loading the Resales controller - that should be a model that both controllers use. You should load your Resales model into the Administrator controller in the $uses = array() property at the top of your controller file:
class AdministratorController extends AppController {
var $uses = array('Resale', //the rest of your models);
public function createResale() {
$this->Resale->create();
$this->Resale->set($this->data['Resale']);
$this->Resale->save();
}
}
Other options are that you could use Ajax to post the request for you, or you could use $this->requestAction() in your Administrator controller to use a processing function in your Resales controller:
// administrator controller
public function createResale() {
// define your data here
$result = $this->requestAction('resales/create', array($data_array));
}
Have a look at the manual for more information on requestAction:
http://book.cakephp.org/2.0/en/controllers.html
EDIT
You've just asked about views. In this case, there's no real need to create a view for createResale(), what you might want to do instead is set a Session flash message, then redirect back to your form. You will need to ensure you've included the Session helper at the top of your controller:
class AdministratorController extends AppController {
var $helpers = array('Session', // any others here);
Then you prevent the layout and render of views, do your thing and set a session flash with the results message:
public function createResale() {
// don't render a view or layout
$this->layout = '';
$this->render(false);
// process your request
$result = // do stuff... return true or false for result
$msg = $result ? 'Added successfully!' : 'Error adding resale!';
// set flash message
$this->Session->setFlash($msg);
// return to that form
$this->redirect(array('action' => 'formYouCameFrom'));
}
Now on your form, you'll simply do this:
echo $this->Session->flash();
... which will output the results.

Do Partial Views Need Separate Controllers if they Use Different Models?

I've created a series of partial views for a page in our Yii Framework site. Each partial view has it's own model because they call subsections of the main model class. Since each partial view has it's own model, do I need separate controller classes for each?
My loadModel portion of the User controller is as follows:
public function loadModel($id,$model_name='Users')
{
$model=Users::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
It is being called from this section of the User Controller:
public function actionProfile($id=''){
$user = Users::model()->find('username=:id', array
(':id' => Yii::app()->user->id));
if(!$id){
$id = $user->id;
if(!$id)
$this->redirect('login');
}
if( getUserSess('user_type') == 'Sitter') {
$this->render('profile_detail', array('user_id' => $id ));
} else {
$this->render('petowner_profile_detail',array(
'model'=>$this->loadModel($id),
));
}
}
I think I understand what you are trying to do. My answer would be no, you don't need separate controller actions for each partial view. I would create a view that then calls all the partial views. If you use gii to create your CRUD functionality you will see both the create and edit views call a partial view of the form. You would do this same thing only call multiple partial views in your view file. If you need different models just make sure your controller passes them to your main view file first so that it can then pass them on to the partial views. Hopefully that helps you out.
Here is the code if there is no relationship:
$partialUser = new PartialUser::model->findByAttributes(array('uid'=>$id)); //IF NOT UID PUT WHATEVER YOU HAVE THE COLUMN NAME
$this->render('petowner_profile_detail',array(
'model'=>$this->loadModel($id),
'partialUser' => $partialUser,
));
If you did have a relationship setup you could easily just do this:
$current_user = $this->loadModel($id);
$this->render('petowner_profile_detail',array(
'model'=> $current_user,
'partialUser' => $current_user->partialUser, //whatever you set the name of the relationship as in the model
));

Is a POST controller suitable in a php mvc?

I am creating a custom MVC style framework from scratch and am at the point where I need to implement the code to control what happens on POST.
At the moment I have a main index.php which acts as a controller and passes data to other controllers such as:
profilecontroller.class.php
forumcontroller.class.php
At the moment I see two options as to where the POST controllers can go ..
First Approach
Firstly for site wide posts such as login that can occur on any page I would use something like this in the very first index.php to redirect all POST to a specific POST controller that then sends the data to a model to be processed:
if($_POST)
//post controller, works on specific form id's
Alternate Approach
The other option I see would be to build the POST identifier into the model construction sections but I don't think this would be very manageable/wise as they'd always be checked and resulting in more loaded code?
Are there any good/simple examples out there?
I'm creating my mvc to be as light as possible so that's my reason for going from scratch.
In a RESTful setup, you would normally have a controller for an object, say news, and then actions such as add, edit, delete etc.
Within your actions, you should then assert what HTTP method should be used to access the method, if one should be. For example:
<?php
class NewsController extends AbstractController {
public function save() {
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
header('HTTP/1.1 405 Method Not Allowed');
die('Please use POST.');
}
// carry on knowing we're working with a POST request
}
}
Creating a separate controller for POST requests would, as you say, quickly becoming unruly and unmanageable.
If you're looking for a way of handling requests for different HTTP methods within different controller actions, then maybe check out ToroPHP. It's a lightweight (single file) router, where you map a request to a class that's referred to as a handler, and then that handler has methods for different HTTP methods. A quick example:
<?php
require 'lib/torophp/toro.php';
require 'classes/handlers/HomeHandler.php';
$toro = new ToroApplication(array(
array('/', 'HomeHandler')
));
$toro->serve();
And then your HomeHandler would look as follows:
<?php
class HomeHandler {
public function get() {
echo 'Hello, world!';
}
public function post() {
echo 'Try performing a GET request for the home page, buddy.';
}
// and so on...
}
Hope that helps.
This is my default Controller :
<?php
Class Controller_Home{
public $Registery = null;
final public function __construct($Registery){ $this->Registery = $Registery; }
final public function Init($Method=null){
# Quelle action on fait ?
if($Method){
$Split = explode('_', $Method);
$MethodName = 'Action';
foreach($Split as $Splitted){
$MethodName.= '_'.ucfirst($Splitted);
}
if(method_exists($this, $MethodName)){
$this->$MethodName();
} else {
echo '404';
die;
}
} else {
$this->Action_Default();
}
}
final public function Action_Default(){
$this->Registery->Import('Library.Account');
var_dump($this->Registery->Account);
echo 'Default Home';
}
}
As you can see, once you are in Action_Default, you can do whatever you want based on $_GET, $_POST, whatever you want ...
So with this code :
website.com/home/bob/ will use function Action_Bob inside the controller Home (Home::Action_Bob) ... if you see $_POST just put inside Action_Bob this
public function Action_Bob(){
if($_POST){
$this->Action_Bob_Post();
}
// continue
}

Categories