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.
Related
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.
im using laravel 5.
I need to call a controller function but this should be done in another controller.
I dont know how to do this
public function examplefunction(){
//stuff
}
And i have a Route for this function, so at
public function otherfunctioninothercontroller(){
// I need examplefunction here
}
how Can i do this?
1) First way
use App\Http\Controllers\OtherController;
class TestController extends Controller
{
public function index()
{
//Calling a method that is from the OtherController
$result = (new OtherController)->method();
}
}
2) Second way
app('App\Http\Controllers\OtherController')->method();
Both way you can get another controller function.
If they are not in the same folder, place use namespace\to\ExampleClass; on top of your file, then you are able to instantiate your controller.
You can simply instantiate the controller and call the desired method as follows
FirstController.php:
namespace App\Http\Controllers;
class FirstController extends Controller {
public function examplefunction() {
// TODO: implement functionality
}
}
SecondController.php:
namespace App\Http\Controllers;
class SecondController extends Controller {
public function test() {
$object = new FirstController();
$object->examplefunction();
}
}
Now, after i've answered the question, i would like to add the following comment:
Controllers are classes, all rules that applies to normal classes can be applied to them
However, instantiating a controller directly inside another controller to call a desired method signifies a problem in your design for the following 2 reasons:
A controller cannot obtain an instance of another controller directly
Controller should contain as little business logic as possible, and if possible none
The closest possible solution to what you want (WITHOUT BREAKING MVC) is to make an HTTP request to the route that points to the desired method (using cURL, for example) and read the response as the returned data
But this still doesn't make much sense in this scenario because after all you're making an HTTP request from a method in a controller in your project on your server to a method in a controller in your project on your server, seems like unnecessary overhead, right ?
As i said earlier, a controller should contain as little business logic as possible because the logic should stay inside specialized classes (commonly known as Service Classes), and when a processing is requested the controller simply delegates the job of processing to the appropriate service class which does the processing and returns the results to the controller which in turn sends it back as a response
Now imagine if you've the following scenario:
We've got an application that consists of 3 functionalities:
A user can register an account from web application
There's a mobile application that talks to an API to register a user
There's an admin panel, which he can use to add new user
Obviously you need to create 3 controllers, but those controllers contains repeated logic, would you copy/paste the code everywhere ?
Why not encapsulate this logic inside a service class and call it from the controller when needed ?
Let's say I have Controller1 and Controller2. I want to call a function of Controller1 from inside a function placed in Controller2.
// Controller1.php
class Controller1 {
public static function f1()
{
}
}
And on the other controller:
// Controller2.php
use App\Http\Controllers\Controller1;
class Controller2 {
public function f2()
{
return Controller1::f1();
}
}
Points to be noted:
f1() is declared static
A call to a controller from inside another controller is a bad idea. There is no sense of meaning of controllers then. You should just redirect to web.php to save safe whole architecture like this:
class MyController {
public function aSwitchCaseFunction(Request $requestPrm){
...
//getting path string from request here
...
switch($myCase){
case CASE_1:
return redirect()->route('/a/route/path');
....
}
}
}
I'm having Codeigniter object scope confusion.
Say I load a model in a controller:
$this->load->model('A');
$this->A->loadUser(123); // loads user with ID 123
// output of $this->A now shows user 123
$this->load->model('B');
$this->B->examineUser ();
// output of $this->A now shows user 345
class B extends Model
{
public function examineUser ()
{
$this->load->model('A');
$this->A->loadUser(345); // loads user with ID 345
}
}
I would have thought that $this->A would be different from $this->B->A but they are not. What is the best solution to this issue? It appears the ->load->model('A') in the examineUser () method does nothing because it was loaded in the controller. Then the call to loadUser () inside that method overwrites the stored properties of $this->A. This seems like a bugfest waiting to happen. If I needed global models, I would have use static classes. What I wanted was something scoped pretty much locally to the model object I was in.
Is there a way I can accomplish this but not go way outside of CI's normal way of operating?
Followup/related:
Where do most people put there "->load->model" calls? All at the beginning of a controller action? I figured it would be easier -- though perhaps not excellent programming from a dependency injection perspective -- to load them in the model itself (construct or each method).
Whenever you use the Loader Class ($this->load->), it will load the object into the main CI object. The CI object is the one you keep referring to as $this->. What you've done is load model A twice into the CI object.
Essentially, all object loaded using the Loader class goes into a single global scope. If you need two of the same type, give them different names, as per $this->load->model('A','C'). I don't know of any way around it unless you revert to using bog-standard PHP.
In my team's code, we generally load the models in the controller's constructor, then load the data to send to the view in the function, often _remap().
This is not how the loader works sadly. CodeIgniter implements a singleton pattern, which will check to see if the class is included, instantiated and set to $this->A then will be ignored if loaded again. Even if you are inside a model, $this->A will be referenced to the super-instance via the __get() in class Model. Alis it, or just do:
class B extends Model
{
public function examineUser ()
{
$user = new A;
$user->loadUser(345); // loads user with ID 345
}
}
Here's what I've decided to do, please comment if you have advice:
I've extended the CI Loader class:
<?php
class SSR_Loader extends CI_Loader
{
function __construct()
{
parent::__construct ();
}
/**
* Model Retriever
*
* Written by handerson#executiveboard.com to create and return a model instead of putting it into global $this
*
* Based on original 2.0.2 CI_Loader::model ()
*
*/
function get_model($model)
{
if (empty ($model))
{
return;
}
$name = basename ($model);
if (!in_array($name, $this->_ci_models, TRUE))
{
$this->model ($model);
}
$name = ucfirst($name);
return new $name ();
}
}
Do any CI guru's see a problem with that before I invest time in changing my code a bit to accept the return obj, ala:
// in a controller:
public function test ($user_id=null)
{
$this->_logged_in_user = $this->load->get_model ('/db/users');
$this->_viewed_user = $this->load->get_model ('/db/users');
$this->_logged_in_user->load($this->session->userdata ('user.id'));
$this->_viewed_user->load($user_id);
}
I could also do private $_logged_in_user to make it available in the controller but positively force it to be limited to just the current controller and not spill anywhere else, or I could just do $_logged_in_user = $this->load->get_model ('/db/users'); and limit it to just the current method, which is probably what I'll do more often.
This seems like a pretty straightforward way to "fix" this issue (I say "fix" b/c it's not really a bug, just a way of doing things that I think is a bad idea). Anyone see any flaws?
I have two controllers a and b.
I would like to call a method of controller a from a method of controller b.
Could anyone help explain how I can achieve this?
This is not supported behavior of the MVC System. If you want to execute an action of another controller you just redirect the user to the page you want (i.e. the controller function that consumes the url).
If you want common functionality, you should build a library to be used in the two different controllers.
I can only assume you want to build up your site a bit modular. (I.e. re-use the output of one controller method in other controller methods.) There's some plugins / extensions for CI that help you build like that. However, the simplest way is to use a library to build up common "controls" (i.e. load the model, render the view into a string). Then you can return that string and pass it along to the other controller's view.
You can load into a string by adding true at the end of the view call:
$string_view = $this->load->view('someview', array('data'=>'stuff'), true);
test.php Controller File :
Class Test {
function demo() {
echo "Hello";
}
}
test1.php Controller File :
Class Test1 {
function demo2() {
require('test.php');
$test = new Test();
$test->demo();
}
}
Very simple way in codeigniter to call a method of one controller to other controller
1. Controller A
class A extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_a()
{
}
}
2. Controller B
class B extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_b()
{
require_once(APPPATH.'controllers/a.php'); //include controller
$aObj = new a(); //create object
$aObj->custom_a(); //call function
}
}
I agree that the way to do is to redirect to the new controller in usual cases.
I came across a use case where I needed to display the same page to 2 different kind of users (backend user previewing the page of a frontend user) so in my opinion what I needed was genuinely to call the frontend controller from the backend controller.
I solved the problem by making the frontend method static and wrapping it in another method.
Hope it helps!
//==========
// Frontend
//==========
function profile()
{
//Access check
//Get profile id
$id = get_user_id();
return self::_profile($id);
}
static function _profile($id)
{
$CI = &get_instance();
//Prepare page
//Load view
}
//==========
// Backend
//==========
function preview_profile($id)
{
$this->load->file('controllers/frontend.php', false);
Frontend::_profile($id);
}
I posted a somewhat similar question a while back, but regarding a model on CI.
Returning two separate query results within a model function
Although your question is not exactly the same, I believe the solution follows the same principle: if you're proposing to do what you mention in your question, there may be something wrong in the way you're coding and some refactoring could be in order.
The take home message is that what you're asking is not the way to go when working with MVC.
The best practice is to either use a Model to place reusable functions and call them in a controller that outputs the data through a view -- or even better use helpers or libraries (for functions that may be needed repeatedly).
You can do like
$result= file_get_contents(site_url('[ADDRESS TO CONTROLLER FUNCTION]'));
Replace [ADDRESS TO CONTROLLER FUNCTION] by the way we use in site_url();
You need to echo output in controller function instead of return.
You can use the redirect() function.
Like this
class ControllerA extends CI_Controller{
public function MethodA(){
redirect("ControllerB/MethodB");
}
}
Controller to be extended
require_once(PHYSICAL_BASE_URL . 'system/application/controllers/abc.php');
$report= new onlineAssessmentReport();
echo ($report->detailView());
You can use the redirect URL to controller:
Class Ctrlr1 extends CI_Controller{
public void my_fct1(){
redirect('Ctrlr2 /my_fct2', 'refresh');
}
}
Class Ctrlr2 extends CI_Controller{
public void my_fct2(){
$this->load->view('view1');
}
}
very simple
in first controllr call
$this->load->model('MyController');
$this->MyController->test();
place file MyController.php to /model patch
MyController.php should be contain
class MyController extends CI_Model {
function __construct() {
parent::__construct();
}
function test()
{
echo 'OK';
}
}
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.