PHP access property of individual method inside object - php

Trying to get the property inside a function so not sure how to do it.
Here is my class:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Data extends CI_Controller {
public $data;
public function __construct() {
parent::__construct();
$this->load->model('months');
$this->load->driver('cache');
}
}
public function graph1() {
$this->data = $this->months->get_months();
$this->layout->view('graph1', $this->data);
}
So trying to get value of $data inside graph1() in another class, for example:
$object = new Data();
print_r($object->data);
This gives me a blank output, how can i make the $data value have the database result set?

Before dumping your object data, call your graph method to actually get the data. i.e.
$object = new Data();
$object->graph1();
print_r($object->data);
You could also call graph1 from your constructor like:
public function __construct() {
parent::__construct();
$this->load->model('months');
$this->load->driver('cache');
$this->graph1();
}
That way you would be able to actually use:
$object = new Data();
print_r($object->data);
If this solves your problem, I suggest you should read up OOP concepts. Regards.

I will show the real solution that works with the web application and unit testing.
Change this on data controller to:
public function graph1() {
$this->data = $this->months->get_months();
$this->layout->view('graph1', $this->data);
}
To:
public function graph1() {
$this->data = $this->months->get_months();
$this->layout->view('graph1', $this->data);
return $this->data;
}
The return won't cause problems with the layout and views. And will return the correct data to the unit test:
public function testgraph1() {
$object = new Data();
$out = $object->graph1();
print_r($out);
$this->assertArrayHasKey('11', $out);
}
So the other answer is incorrect, and will cause issues with the layout when graph1() is called in the constructor. I don't need to read about OOP but would suggest the person who answered incorrectly to read about web applications and unit testing.

Related

CodeIgniter can not access global variable in controller

I have already tried lots of ways. add library, add config file, add a controller, just add in same controller.........etc.
This also have same problem:
(this is add in same controller)
<?php
class Test extends CI_Controller{
public $data = array();
public function __construct(){
parent::__construct();
//if call add_data() here, it is work
}
function add_data(){
$arraya = array('a'=>'aa', 'b'=>'bb');
$this->data = $arraya;
}
function index(){
$this->add_data();
}
function want_print(){
print_r($this->data);
}
}
?>
if I call add_data in index, i cannot get any data in want_print()....
if I call add_data in the construct, i can get data in want_print()..
Please anyone help me solve this problem?
I don't want to call it in construct because i will not call it every time...
You can set the data in your want_print() function like this:
function want_print() {
$this->index();
print_r($this->data);
}

Codeignieter data is not initialized in index function

I am trying to initialize data in index function of controller, so that initialized data can be used in subsequent functions of controller. But the problem is data is not being displayed when I am trying to access it from other function. All of this is just to follow a sort of object oriented pattern.
Here is my code.
class Dashboard extends CI_Controller
{
private $account_data; /*Declaration*/
private $profile_data;
function __construct() {
// code...
}
function index() /*Here I am initializing data*/
{
$this->load->model('db_model');
$this->account_data = $this->db_model->get_row();
$this->profile_data = $this->db_model->get_row();
$this->load->view('user/dashboard');
}
function function account_details()
{
print_r($this->account_data); // This displays nothing
}
/*other function...*/
}
Idea is to get data once and use it for other functions and if data is updated again calls a function to initialize it.
But it is not working out. Please help me. Also suggest if I am following right approach.
Thanks for your time.
index method is not initializer, its default page/sub_method,
if you call the "*account_details*" in url as index.php/dashboard/account_details the index wont be called.
try put the code on constructor,
class Dashboard extends CI_Controller
{
private $account_data; /*Declaration*/
private $profile_data;
function __construct() { /*Here I am initializing data*/
parent::CI_Controller(); // Thank you Sven
$this->load->model('db_model');
$this->account_data = $this->db_model->get_row();
$this->profile_data = $this->db_model->get_row();
}
function index()
{
$this->load->view('user/dashboard');
}
function function account_details()
{
print_r($this->account_data); // This displays nothing
}
/*other function...*/
}
Note : don't the models or other computations on __construct() if you don't need on all methods of this controller.
create a private method like "model_initializer()" put this codes on this scope, and the call it in your other methos as $this->model_initialize(); if you need.
Thanks yo Sesama Sesame for note,

Codeigniter: Where to put the variable from a url

I am developing a stats site in Codeigniter locally. I have a url like localhost/sitename/player/show_profile/PlayerName
I currently have the following:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Player extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('player_model');
$player_name = $this->uri->segment(3);
}
public function index()
{
echo "index";
}
public function show_profile($player_name)
{
$data['player_stats'] = $this->player_model->get_stats( $player_name );
$this->load->view('player/player_stats', $data);
}
}
?>
This works, but my question is regarding the $player_name variable. I have $player_name = $this->uri->segment(3); in the __construct so it's available to all of the class methods. Is this the way I should be doing it?
Is this safe?
Fist of all, there is no point in assigning the variable in the constructor because it's going to get overwritten. When you pass CI a url like localhost/sitename/player/show_profile/PlayerName, anything passed the method (i.e. PlayerName) get's set as the parameters. Therefore, your variable in
public function show_profile($player_name){
is already set when you get to your method code.
Secondly, I agree with Peter's:
protected $player_name;
for making it globally accessible in the controller. BUT, I don't agree with setting it in the constructor. If you have another method in this controller that passes a variable in that spot, you're going to get the wrong data in there. Set it in the method you called:
public function show_profile($player_name){
$this->player_name = $player_name;
$data['player_stats'] = $this->player_model->get_stats( $player_name );
$this->load->view('player/player_stats', $data);
}
What you could do is define a class variable called $player_name and in the constructor set this to segment(3).
class Player extends CI_Controller
{
protected $player_name;
public function __construct() {
parent::__construct();
$this->load->model( 'player_model' );
$this->player_name = $this->uri->segment( 3 );
}
public function index() {
echo "index";
}
public function ( show_profile ) {
$data['player_stats'] = $this->player_model->get_stats( $this->player_name );
$this->load->view( 'player/player_stats', $data );
}
}
This way will be able to access the $play_name variable anywhere in the class.
You could also check to see if it's set using the $this->uri->uri_to_assoc(n) method and check to see if the key/value isset() http://codeigniter.com/user_guide/libraries/uri.html.
Peter

Simple PHP Class Question regarding methods

I have a simple question regarding PHP Classes.
Multiple times I have seen other class-frameworks etc use method calls like.
$post->data->text();
I like this functionality, rather than just doing something like this.
$post->dataReturnAsText();
But i'm not quite sure how they created this functionality to have perhaps a 'sub-method'? Hope someone can point me in the right direction....
The example you provide has nothing special:
<?php
class Post{
public $data;
}
class Data{
public function text(){
}
}
$post = new Post;
$post->data = new Data;
$post->data->text();
However, you've probably found it in the context of method chaining (very popular in JavaScript libraries):
<?php
class Foo{
public function doThis(){
return $this;
}
public function doThat(){
return $this;
}
}
$foo = new Foo;
$foo->doThis()->doThat()->doThis();
In this case, data is simply a attribute of the class, and it contains another object:
class data
{
public function text()
{
}
}
class thing
{
public $data;
}
$thing = new thing();
$thing->data = new data();
$thing->data->text();
its probably a just that the "data" is a a public property of $post containing an object wth a text property for example :
class Textable {
public $text;
function __construct($intext) {
$this->text = $intext;
}
}
class Post {
public $data;
function __construct() {
$data = new Textable("jabberwocky");
}
}
this will allow you to do :
$post = new Post();
echo( $post->data->text ); // print out "jabberwocky"
of course the right OOP way is to make the property private and allow access useing a getter function but that besides the point...

Going from the Controller to the View

I am working on creating my own very simple MVC and I am brainstorming ways to go from the controller to the view. Which involves sending variables from a class to just a plain old PHP page.
I am sure that this has been covered before, but I wanted to see what kind of ideas people could come up with.
//this file would be /controller/my_controller.php
class My_Controller{
function someFunction(){
$var = 'Hello World';
//how do we get var to our view file in the document root?
//cool_view.php
}
}
Some kind of hashtable is a good way to do that. Return your variables as association array which will fill all the gaps in your view.
Store your variables as a property in your controller object, then extract them when rendering
class My_Controller {
protected $locals = array();
function index() {
$this->locals['var'] = 'Hello World';
}
protected function render() {
ob_start();
extract($this->locals);
include 'YOUR_VIEW_FILE.php';
return ob_get_clean();
}
}
You can define those magic __get and __set methods to make it prettier
$this->var = 'test';
I'm also developing my own simple MVC and the most simple way to do it is ...
class My_Controller
{
function someFunction() {
$view_vars['name'] = 'John';
$view = new View('template_filename.php', $view_vars);
}
}
View class
class View
{
public function __construct($template, $vars) {
include($template);
}
}
template_filename.php
Hello, <?php echo $vars['name'];?>
I highly recommend you to take a look at PHP Savant http://phpsavant.com/docs/
I'd checkout Zend_View and how it accomplished view rendering.
You can get the source of View and AbstractView on github - unfortunaly I don't find the current repository (in svn) that easy to browse.
Essentially the view variables are contained in a View object (which your controller would have access to), then the template (plain old php document) is rendered inside that object. That method allows the template access to $this.
It would be something like:
<?php
class View
{
public function render()
{
ob_start();
include($this->_viewTemplate); //the included file can now access $this
return ob_get_clean();
}
}
?>
So in your controller:
<?php
class Controller
{
public function someAction()
{
$this->view->something = 'somevalue';
}
}
?>
And your template:
<p><?php echo $this->something;?></p>
In my opinion this pattern allows you much flexibility with the view.
I created my own MVC for the free PHP course I'm conducting for a handful of people wanting to get better at PHP.
By far the best way to do this is to use the Command + Factory pattern.
E.g.
interface ControllerCommand
{
public function execute($action);
}
In each controller:
class UserController implements ControllerCommand
{
public function execute($action)
{
if ($action == 'login')
{
$data['view_file'] = 'views/home.tpl.php';
}
else if ($action == 'edit_profile')
{
$data['view_file'] = 'views/profile.tpl.php';
$data['registration_status'] = $this->editProfile();
}
return $data;
}
}
From your main front controller:
$data = ControllerCommandFactory::execute($action);
if (!is_null($data)) { extract($data); }
/* We know the view_file is safe, since we explicitly set it above. */
require $view_file;
The point is that every Controllercommand class has an execute function and that returns its view and any data for that view.
For the complete MVC, you can access the open source app by emailing me at theodore[at]phpexperts.pro.

Categories