I began use RedbeanPHP and Codeigniter. In Codeigniter manual written, that if you transmit object from controller to view - properties of object become arrays.
I try get array ( object of redbeanphp ) in view from controller.
For example :
class Welcome extends CI_Controller {
public function index() {
$this->load->library('rb');
$post = R::dispense('post');
$post->title = 'HI';
$post->text = 'Hello World';
$post->count = 5;
$this->load->view('welcome_message',$post);
}
}
I don't understand, how I must appeal to variable of array ?
<p><?php echo $????['title'] ;?></p>
You could pass the variables for the templates as an array.
$this->load->view('welcome_message', array('something' => $post));
Then you can access it as $something in your template
title is your key- so it itself becomes a variable in the view.
just use it like a normal variable-
<p><?php echo $title ;?></p>
Related
I'm writing now an app, which is supposed to be as simple as possible. My controllers implement the render($Layout) method which just does the following:
public function render($Layout) {
$this->Layout = $Layout;
include( ... .php)
}
I don't really understand the following problem: in my controller, I define a variable:
public function somethingAction() {
$someVariable = "something";
$this->render('someLayout');
}
in the php view file (same I have included in the render function) I try to echo the variable, but there is nothing. However, if I declare my action method like this:
public function somethingAction() {
global $someVariable;
$someVariable = "something";
$this->render('someLayout');
}
and in my view like this:
global $someVariable;
echo $someVariable;
it does work. Still it is annoying to write the word global each time.
How can I do this? I'd rather not use the $_GLOBAL arrays. In Cake PHP, for example, there is a method like $this->set('varName', $value). Then I can just access the variable in the view as $varName. How is it done?
From the PHP Manual on include:
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
When you do
public function somethingAction() {
$someVariable = "something";
$this->render('someLayout');
}
the $someVariable variable is limited to the somethingAction() scope. Calling your render() method will not magically make the variable available in render(), because the render() method has it's own variable scope. A possible solution would be to do
public function somethingAction() {
$this->render(
'someLayout',
array(
'someVariable' => 'something'
)
);
}
and then change render() to
public function render($Layout, array $viewData) {
$this->Layout = $Layout;
include( ... .php)
}
You will then have access to $viewData in the included file, given that you are not trying to use it in some other function or method, e.g. if your included file looks like this:
<h1><?php echo $viewData['someVariable']; ?></h1>
it will work, but if it is looks like this:
function foo() {
return $viewData['someVariable'];
}
echo foo();
it will not work, because foo() has it's own variable scope.
However, a controller's sole responsibility is to handle input. Rendering is the responsibility of the View. Thus, your controller should not have a render() method at all. Consider moving the method to your View class and then do
public function somethingAction() {
$view = new View('someLayout');
$view->setData('someVariable', 'something');
$view->render();
}
The render() method of your View object could then be implemented like this:
class View
…
$private $viewData = array();
public function setData($key, $value)
{
$this->viewData[$key] = $data;
}
public function render()
{
extract($this->viewData, EXTR_SKIP);
include sprintf('/path/to/layouts/%s.php', $this->layout);
}
The extract function will import the values of an array in the current scope using their keys as the name. This will allow you to use data in the viewData as $someVariable instead of $this->viewData['someVariable']. Make sure you understand the security implications of extract before using it though.
Note that this is just one possible alternative to your current way of doing things. You could also move out the View completely from the controller.
Using global you're implicitly using the $_GLOBALS array.
A not recommended example, because globals are never a good thing:
function something() {
global $var;
$var = 'data';
}
// now these lines are the same result:
echo $_GLOBALS['var'];
global $var; echo $var;
Why don't you use simply the $this->set function?
public function render($Layout) {
$this->Layout = $Layout;
include( ... .php)
}
public function somethingAction() {
$this->set('someVariable', "something");
$this->render('someLayout');
}
// in a framework's managed view:
echo $someVariable;
I'm sorry not to know your framework in detail, but that makes perfectly sense.
Actually how it's done: There is a native extract function, that loads an associative array into the current symbol table:
array( 'var0' => 'val0', 'var1' => 'val1')
becomes
echo $var0; // val0
echo $var1; // val1
That's most likely 'what happens'.
I have a question. Ive made some mvc'ish structure for my website.
I want to be able to use my variables inside my view without assigning them.
Let me explain by an example, here's a small part of my controller :
class members extends controller{
public function _construct()
{
parent::__construct();
}
public function index()
{
$test = 'test variable';
$data['test2'] = 'test variable 2';
view::setTemplate('header');
view::setTemplate('homepage', $data);
view::setTemplate('footer');
}
}
in the setTemplate() function of my view class, I use extract($data) and then I include the view file. This way I can echo $test2 and get 'test variable 2' as output, as expected.
However, is there a way to make the view 'remember' the first $test variable without having to add it to the setTemplate function ?
DISCLAIMER: THIS CODE HAS NOT BEEN TESTED
You can use variable variables to define the variables within the setTemplate method and include the view directly from there.
<?php
function setTemplate($view, $data) {
if(is_array($data)){
foreach($data as $var => $val){
$$var = $val;
}
}
include('views/'.$view.'.php');
}
?>
I use an homemade MVC system, in which Views access the model by being within the context of a method, and therefore able to access $this.
Example of a view, included dynamically :
...
<div>
Hello <?= $this->user->name ?>
</div>
...
Now, I have some code that I would like to factorize into functions, with some extra parameters.
For example :
function colored_hello($color) {
?>
<div style="background-color:<?= $color ?>">
Hello <?= $this->user->name ?>
</div>
<?
}
The problem is that I do not have access to $this, since the function is not a method.
But I do not want to spoil my model or controller with presentation stuff.
Hance, I would like to be able to call this function dynamically, as a method.
Like aspect oriented programming :
# In the top view
magic_method_caller("colored_hello", $this, "blue")
Is it possible ?
Or do you see a better way of doing it ?
Take a look at Closure::bindTo
You'll have to define/call your functions slightly differently, but you will be able to access $this from inside your object.
class test {
private $property = 'hello!';
}
$obj = new test;
$closure = function() {
print $this->property;
};
$closure = $closure->bindTo($obj, 'test');
$closure();
Pass $this as a property, but in all seriousness: you shouldn't really have functions in your view files.
it is a bit a hack but you can use debug_backtrace() to get the callers object. But I think you can only public values:
function colored_hello($color) {
$tmp=debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
$last=array_pop($tmp);
$caller = $last['object'];
print_r($tmp);
print_r($last);
print_r($caller);
?>
<div style="background-color:<?= $color ?>">
Hello <?= $caller->user->name ?>
</div>
<?
}
(code is not testet but it gives you a hint :-) )
You could alternatively pass it into the function:
function coloured_hello($object, $color) {
//Code
$object->user->name;
}
How can I reuse data passed from controller in a view ?
controller's function
public function display()
{
$data=ReadIntoDate();
$this->load->view('display',$data);
}
I would like to use $data in display.php in view. Thank you
You should pass an associative array.
So if you do it like this:
public function display()
{
$data['something'] = ReadIntoDate();
$this->load->view('display', $data);
}
You can call the data in the view like:
<h1><?php echo $something; ?></h1>
Hope it helped.
$data must be an associative array.
Controllter:
$data['blah'] = 'something';
view:
echo $blah;
I want to pull all info about a file from a files table, but that table's structure might change.
So, I'd like to pull all the field names from the table and use them to generate the class variables that contain the information, then store the selected data to them.
Is this possible?
Yes you can, see php overloading.
http://php.net/manual/en/language.oop5.overloading.php
Quick Example: ( Not this isn't great usage )
<?php
class MyClass{
var $my_vars;
function __set($key,$value){
$this->my_vars[$key] = $value;
}
function __get($key){
return $this->my_vars[$key];
}
}
$x = new MyClass();
$x->test = 10;
echo $x->test;
?>
Sample
<?php
class TestClass
{
public $Property1;
public function Method1()
{
$this->Property1 = '1';
$this->Property2 = '2';
}
}
$t = new TestClass();
$t->Method1();
print( '<pre>' );
print_r( $t );
print( '</pre>' );
?>
Output
TestClass Object
(
[Property1] => 1
[Property2] => 2
)
As you can see, a property that wasn't defined was created just by assigning to it using a reference to $this. So yes, you can define class variable from within a class method.