My method is
public function topmenu($parentsid=null){
$this->layout =false;
$category_tree = $this->Categorymaster->find('all',array('order'=>'Categorymaster.lft ASC','conditions'=>array('Categorymaster.parent_id'=>$parentsid)));
echo '<ul class="sub-menu" role="menu">';
foreach($category_tree as $parentval){
echo '<li>'.$parentval['Categorymaster']['name'].'</li>';
$id = $parentval['Categorymaster']['id'];
$haschild = $this->Categorymaster->children($id, true);
if (!empty($haschild)) {
$this->topmenu($id);
}
}
echo '</ul>';
$this->set(compact('category_tree'));
$this->render('topmenu');
}
I get output from controller
I am trying to use a foreach loop in my topmenu.ctp file but as cakephp
is mvc it gives error at the lines
$haschild = $this->Categorymaster->children($id, true);
if (!empty($haschild)) {
$this->topmenu($id);
}
so how can it use topmenu() method in .ctp file so that i can show it in my menu or any other alternative.
First of all its never a good practice to call controller method directly in ctp (view) file.
If you still want to do this, try to call like this:-
Controller name::(scope resolution operator) function name(parameters).
Note:-Make sure that your method is public.
Related
I know that you can use extract() to achieve this however my circumstances are as followed:
I am building a very small basic MVC framework for personal projects and I have this in my controller:
public function index(){
$data = [
'title' => 'Welcome'
];
$this->view('pages/index', $data);
}
As you can see this passes the data array into the view and you can echo it like:
echo $data['title'];
But I want to echo it like echo $title; I know that extract() can do this but that means I have to manually put extract($data); at the top of every page which isnt the end of the world but I was just curious if there was a way it could be done automatically? I have tried to use extract by putting it inside the view function but that did not work. I have also tried to use extract by putting it in the header file that is required_once in index.php (thus making the header file a static header thats always required) but neither has worked so any advice would be great.
Here is the code for the view function as requested:
public function view($view, $data = []){
if(file_exists('../../views/'.$view.'.php')){
require_once '../../views/'.$view.'.php';
} else {
die('View does not exist');
}
}
Simple that is it ,use compact and extract function
index method
public function index(){
$title='Welcome';
$this->view('pages/index', compact('title'));
}
Wiew method
public function view($view, $data = []){
extract($data);
if(file_exists('../../views/'.$view.'.php')){
require_once '../../views/'.$view.'.php';
} else {
die('View does not exist');
}
}
In html
<h1> hello <?php echo $title; ?></h1>
Here is where I went wrong, I put extract in the view method before and it didn't work.
However the advice here was to put it in the view function and I now understand that I put the extract function after require_once '../../views/'.$view.'.php'; I just put extract before that line of code and it is now working!
I have created my own little PHP framework for fun, however, I am having trouble passing variables from bootstrap to the views....
if I put an echo,print_r,var_dump my target variable in the bootstrap, the output is displayed in the browser before the tag... yet the target var in bootstrap.php is not available in the view, it is coming up as "" even though at the top of the page it is being output correctly....
Somethings I noticed from similar questions:
- The target variable is not being over written
- The include target path is correct and the file exists
- The file is only being included one time (include_once is only fired once)
Any ideas are greatly appreciated, I am pulling my hair out over here lol...
Source Code
https://gist.github.com/jeffreyroberts/f330ad4a164adda221aa
If you just want to display your site name, I think you can use a constant like that :
define('SITE_NAME', "Jeff's Site");
And then display it in your index.tpl :
<?php echo SITE_NAME; ?>
Or, you can send your variables to the view by extending a little bit your JLR_Core_Views :
class JLR_Core_Views
{
private $data;
public function loadView($templatePath, $data = array())
{
$this->data = $data;
$templatePath = JLR_ROOT . '/webroot/' . $templateName . '.tpl';
if(file_exists($templatePath)) {
// Yes, I know about the vuln here, this is just an example;
ob_start();
include_once $templatePath;
return ob_get_clean();
}
}
function __get($name)
{
return (isset($this->data[$name]))
? $this->data[$name]
: null;
}
}
Then, you can call your template like that :
$view = new JLR_Core_Views();
$view->loadView("index", array("sitename" => "Jeff's Site"));
And here is your index.tpl :
<?php echo $this->siteName; ?>
Below is another example of what you can do.
First, you create this class in order to store all the variables you want :
<?php
class JLR_Repository {
private static $data = array();
public function set($name, $value) {
self::$data[$name] = $value;
}
public function get($name) {
return (isset(self::$data[$name]))
? self::$data[$name]
: null;
}
}
?>
Then, when you want to store something in it :
JLR_Repository::set("sitename", "Jeff's Site");
And in your index.tpl :
<?php echo JLR_Repository::get("sitename"); ?>
try using the 'global' keyword - http://php.net/manual/en/language.variables.scope.php
I am writing a program that basically does stuff with a database, I am having trouble with some of the functionality though, this is what it is supposed to do
public function clist() {
$this->load->model('list_model');
$fields = $this->list_model->listcli();
if ($fields === $this->list_model->listcli()) {
$fieldl = $fields;
$this->load->view('clientlist');
$this->clientlist->display_clients($fieldl);
}
}
This loads the model which looks like this:
public function listcli()
{
$this->db->list_fields('clients');
}
}
Then runs the model function listcli so that it will list all the fields in the clients database and puts the value into $fields I then call it fieldl and load a view that will show the data, the view looks like this:
<html>
<body>
<p> sup </p>
<?php
function display_clients($fieldl)
{
?>
<html>
<body>
<p> sup2 </p>
<ul>
<?php
foreach ($fieldl as $l) {
?>
<li>
<?php echo $l;?>
</li>
<?php
}
}
Then calls the function inside the view and passed the data from $fieldl into it.
but I am getting the error " Call to a member function display_clients() on a non-object in /codeigniter/src/application/controllers/clientlist.php on line 40"
line 40 is
$this->clientlist->display_clients($fieldl);
Can you help? Please and thank you.
(I know this kind of question has been asked before but they are always very specific to the code at hand so doesn't help me, I am really new to CodeIgniter so if you can keep any answer relatively simple I will be grateful).
I needed to use the second parameter possible to pass my data over into the view, not my own makeshift solution for it, CI accepts an object as a second parameter for the CI_Loader::view()
Why can't you prepare the list in the controller and pass it to view via $data array?
$my_list = '<ul>';
foreach ($fieldl as $l) {
$my_list .= '<li>'.$l.'</li>';
}
$my_list .= '</ul>';
$data['my_list'] = $my_list;
then you can access it in view as $my_list. Just echo it where you need it.
EDIT:
AS per your own answer, yes - exactly. Using example above you would pass the $data to view as the second parameter:
$this->load->view('my_view',$data);
Then in the View, you access $data['my_list'] as $my_list, $data['foo'] as $foo etc.
Where should we process mysql queries in CodeIgniter application?
For example in a simple project we do like this :
for controller:
class Blog extends CI_Controller {
function posts(){
$data['query'] = $this->blog_model->index_posts();
$this->load->view('blog_view', $data);
}
}
and in view :
<?php
while ($post = mysql_fetch_object($query)):
?>
<div>
<p><?= $post->body; ?></p>
</div>
<?php endwhile; ?>
But, if we want to do something with body of post before print where should it be done?
For example, I want to write a function that formats the body of post and pass the body to it before doing echo.
Where should it be placed according to CoeIgniter's structure and recommended practices? (best option)
in the controller? (if so , how to use it)
in the view?
write a helper?
other approaches ?
Here's what is recommended:
Controller:
function posts() {
$this->load->model("blog_model");
$data['rows'] = $this->blog_model->index_posts();
$this->load->view("blog_view", $data);
}
Model: (blog_model.php)
function index_posts() {
$this->load->database();
$query = $this->db->get('your_table');
$return = array();
foreach ($query->result_array() as $line) {
$line['body'] = ... do something with the body....
$return[] = $line;
}
return $return;
}
View: (blog_view.php)
<?php foreach ($rows as $line): ?>
<div>
<p><?php echo $line['column']; ?></p>
</div>
<?php endforeach; ?>
Basically what happens is your model returns a multidimensional array that is passed the view and processed using a foreach() loop.
Good luck!
If you want to reuse that function create a helper. If you want this function only once put it in your controller and call from that controller.
Models are just for accessing database or maybe in few other cases, but mostly just for accessing things in database or editing, deleting etc. and sending the result to controller for further processing.
In your case I would stick with helper.
E.g. you will create a file top_mega_best_functions.php and put it inside helpers folder.
Than you write ther e.g. something like
function red_text($input) {
echo '<span style="color: red;">';
echo $input;
echo '</span>';
}
Then load the helper in your autoloader file or load before using.
And use in your view or controller like
$blablabla = "This text will be red";
red_text($blablabla);
I am using Kohana 3.2 and I am having problems calling the ouput of a controller in another controller.
What I want...
In some pages I have got a menu, and in others I don't. I want to use make use of the flexability of the HMVC request system. In the controller of a page I want to call another controller which is responsible for the creation of the menu.
What I have a the moment:
file menu.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Menu extends Controller
{
private $_model = null;
public function __construct(Request $request, Response $response)
{
parent::__construct($request, $response);
$this->_model = Model::factory('menu');
}
public function action_getMenu()
{
$content = array();
$content['menuItems'] = $this->_model->getMenuItems();
// Render and output.
$this->request->response = View::factory('blocks/menu', $content);
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
}
}
somepage.php
public function action_index()
{
$this->template->title = 'someTitle';;
$contentData['pageTitle'] = 'someTitle';
$contentData['contentData'] = 'someData';
#include the menu
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
$this->template->content = View::factory('pages/somePage', $contentData);
$view = $this->response->body($this->template);
$this->response->body($view);
}
If I uncomment the following line in menu.php, I see the menu rendered:
//echo '<pre>'; print_r($this->request->response->render()); echo '</pre>'; die();
So I guess that part is alright. The problem is in the following line in somepage.php:
$menuBlock = Request::factory('menu/getMenu')->execute();
This gives me back a response object. Whatever I do, I do not get the output in $this->template->menu.
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
What must I do to have $this->template->menu contain the view, so I can use it correctly?
I hope this all makes sense. This is the way I would like to do it, but maybe I am completely on the wrong track.
I would do it this way:
class Controller_Menu extends Controller
{
public function action_build()
{
// Load the menu view.
$view = View::factory('navigation/menu');
// Return view as response-
$this->response->body($view->render());
}
}
In your controller get the menu as follows:
// Make request and get response body.
$menu = Request::factory('menu/build')->execute()->body();
// e.g. assign menu to template sidebar.
$this->template->sidebar = Request:.factory('menu/build')->execute()->body();
I would not use the __construct method in your controllers. Use before() instead, this is sufficient for most of the problems (for example auth):
public function before()
{
// Call aprent before, must be done here.
parent::before();
// e.g. heck whether user is logged in.
if ( !Auth::instance()->logged_in() )
{
//Redirect if not logged in or something like this.
}
}
I found the answer to my problem in less than an hour after asking.
I just forgot to put it here.
In somePage.php change :
$menuBlock = Request::factory('menu/getMenu')->execute();
$menuData = array('menu' => $menuBlock);
$this->template->menu = View::factory('pages/menu')->set('menu',$menuData);
To:
$this->template->menu = Request::factory('menu/getMenuBlock')->execute()->body();
And in menu.php change:
$this->request->response = View::factory('blocks/menu', $content);
To:
$request = View::factory('blocks/menu', $content);
$this->response->body($request);
I hope this will help someone else.