I've never worked with Zend Framework before, but I've worked with others (CodeIgniter, Kohana, etc). Right now I was asked to just show a view that wasn't existing so I started looking into the documentation and examples I could find and I've always found examples that use the Model part of the MVC, but in this case I just need to load a view and I can't figure out how to do that. I have this:
File: "BookController":
require_once("Initiate.php");
class BookController extends Initiate {
public function init() {
parent::init();
}
public function bookAction(){
#$client = Zend_Auth::getInstance()->getIdentity();
$view = new Zend_View();
echo $this->view->render('book.phtml');
#$this->view->assign("book", $client);
#echo $this->view->render('book.phtml');
}
the view is called "book.phtml" and is found in /application/views/scripts/bookapi/
What am I missing?
Given that eveything is setup correctly with MVC, your Controller should extend Zend_Controller_Action:
class BookController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->funnyText = 'This is a funny text.';
}
}
Then, in your application/views/scripts/book/ folder, there has to be a index.phtml. Which could look like that:
<p>
<?php echo $this->funnyText; ?>
</p>
That's it, nothing more required.
Btw. doesn't make sense to have a controller called book and then also an action called book
you don't have to manage view yourself there is an Action Controller Helper called View Renderer it does your job for you all you need to follow is its naming convention i.e if your controller name is 'BookController' then its view file should be located at views/scripts/book/boo.phtml .
Assuming BookController extends Zend_Controller, it should automatically setup the view and you shouldn't have to render it. Your view file should be in /application/views/scripts/book/book.phtml. Follow the quick start for more information.
Related
I need help with using sub directory controllers in CodeIgniter 4.
I just can't make it work for some reason.
This is the URL for example: www.example.com/admin/dashboard
In the controllers folder, I created a folder named Admin, and a file named Dashboard.php.
I used this code in Dashboard.php:
namespace App\Controllers;
class Dashboard extends BaseController
{
public function index()
{
}
}
I tried changing the class name to AdminDashboard, Admin_Dashboard, pretty much every logical name but every time I get a 404 error, saying:
Controller or its method is not found:
App\Controllers\Admin\Dashboard::index
I know the file itself gets loaded successfully, but I think I don't declare the classname correctly and it keeps throwing me those 404 errors.
The documentation of CI4 isn't providing any information about what the classname should be called unfortunately...
UPDATE #1
I managed to make it work by changing few things:
namespace App\Controllers\Admin;
use CodeIgniter\Controller;
class Dashboard extends Controller
{
public function index()
{
}
}
But now it won't extend the BaseController which has some core functions that I built for my app.
Any ideas to how to make it extend BaseController?
I must admit that I don't have much knowledge about namespacing yet, so that might be the reason for my mistakes.
As I imagined, the problem was that I didn't learn about namespacing.
I needed to point the use line at the BaseController location.
namespace App\Controllers\Admin;
use App\Controllers\BaseController;
class Dashboard extends BaseController
{
public function index()
{
}
}
Now www.example.com/admin/dashboard/ goes directly to that index function, as intended.
php spark make:controller /Subfolder/ControllerName
$routes->add('/(.+?)_(.+?)/(.+?)$', 'subdir\\\\$1_$2::$3');
$routes->add('/(.+?)_(.+?)$', 'subdir\\\\$1_$2::index');
I was able to map with this setting.
The route mapping could be as simple as:
$routes->group('admin', static function ($routes) {
$routes->get('dashboard', 'Admin\Dashboard::index');
});
This is a beginner question, but I searched for an hour and couldn't find an answer.
I am trying to write a simple data query which I included in my HomeController
<?php
class HomeController extends BaseController {
public function showWelcome()
{
return View::make('hello');
}
}
$programs=DB::table('node')->where('type', 'Programs')->get();
$programs is undefined so I am guessing that my query didn't work but I have no idea how to debug it. I tried installing firebug and phpbug and chromphp tools but they don't seem to show anything. My apache log doesn't show anything either. Am I missing something? How do I debug this?
You can't use an expression outside of a method when using a class, instead you need to put it inside a method like:
class HomeController extends BaseController {
public function getPrograms()
{
$programs = DB::table('node')->where('type', 'Programs')->get();
// pass the $programs to the programs view for showing it
return View::make('programs')->with('programs', $programs);
}
}
So, for example, if you have a route like this:
Route::get('/programs', 'HomeController#getPrograms');
Then you may use an URL like: example.com/programs to invoke the getPrograms method in the class HomeController.
Probably this answer doesn't help much but I think you should learn the basics (PHP Manual) first so read books and articles online and check the Laravel website to read the documentation.
You can pass the result of that query to the view like so:
class HomeController extends BaseController {
public function showWelcome()
{
$programs = DB::table('node')->where('type', 'Programs')->get();
return View::make('hello', array('programs' => $programs));
}
}
And in your view you will have access to the $programs variable.
I don't know If i'm missing the point, but can't you use the "dd($programs)" to check what is or not is inside the variable?
I have been reading an article for many times and yet, I can't still understand some parts.
Link for the article : Model-View-Confusion part 1: Why the model is accessed by the view in MVC
The code below is the one I think I am confused on.
class ListView extends View {
public $model;
public $template;
public $listTemplate;
public $errorTemplate;
public $itemName = 'items';
public function output() {
$result = $this->model->findAll();
if (count($result) > 0) {
$this->template = $this->getTemplate($this->listTemplate);
$this->template->addSet($this->itemName, $result);
} else {
$this->template = $this->getTemplate($this->errorTemplate);
}
return $this->template->render();
}
}
And the controller looks like this :
class UserController extends Controller {
public $viewName = 'ListView';
public function showList() {
$this->view->model = $this->model->user;
$this->view->listTemplate = 'UserList.tpl';
$this->view->errorTemplate = 'ErrorNoUsers.tpl';
}
}
As I can understand the template was assigned to a result of a method inherited from the View named getTemplate passed with a method from the View again named listTemplate
like this $this->getTemplate($this->listTemplate)
What I am confused on is that the $template suddenly had a method, which means it becomes a class . right here $this->template->addSet($this->itemName, $result); and `$this->template->render();
Do you have any idea what happened right there?
Firstly, full disclosure: I'm the author of that article.
It wasn't intended to be a complete code solution but an example of the benefits of applying a full MVC separation of concerns instead of the PAC pattern which is claimed to be MVC by most of the PHP community. How it works behind the scenes is beyond the scope of the article. However, what it was supposed to be demonstrating is that the View should encapsulate the template. In that example the template object could be a Smarty Template, a Twig instance or anything.
In hindsight I shouldn't have named the variables which reference file names "template". The confusion you have is understandable: $this->listTemplate; is a reference to the file containing the template code, and $this->template; is an instance of a template object (could be smarty, twig, anything else) that loads the file referenced in listTemplate.
I'll have a look at amending it to be clearer. I wrote that two years ago and there's several things I'd word differently and explain slightly better in the examples if I wrote it again.
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.