Unable to run a db query within a php function - php

I have created a function in my views and have tried to make a query within the php function but i do not know I am getting and unexpected error which was never been seen in my entire career can anyone help me out to get rid from this error?
Severity: Error --> Using $this when not in object context /application/views/includes/create_calendar.php 51
This is my controller
class Booking extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper(array("form", "url"));
$this->load->library('session');
$this->load->database();
}
public function get_calendar() {
$this->load->view('includes/create_calendar');
}
}
This is the file in which I am trying to run a query views/includes/create_calendar.php
function getCalender($year = '',$month = '') {
$sql = $this->db->get('calendar');
if($day == $sql->row()->day_off) { $per_off = $sql->row()->per_off; }
echo "<p>".$day." Off</p>";
}

In CodeIgniter usage, if you need to use one of the classes that is available in the "super object", you must first get an instance of the super object:
$CI =& get_instance();
$CI->db->get('calendar');
This DB class may not even be loaded. If that's the case, then before you use db:
$CI->load->database();
To clarify, as soon as you go in that function, you've removed $this from the variable scope, like this simple test:
class Test {
public $foo = 'bar';
public function index() {
function baz(){
return $this->foo;
}
echo baz();
}
}
$t = new Test;
$t->index();
You could do something like the following, but that's really messy:
class Test {
public $foo = 'bar';
public function index() {
function baz($x) {
return $x->foo;
}
echo baz($this);
}
}
$t = new Test;
$t->index();
The best thing for you to do is find another cleaner way to do what you are doing. You wouldn't normally want calls to your database and functions in your views. It goes against what MVC is all about.

Related

Create methods in a php class dynamically, so to have access to $this

I have a class that executes eval statements within a (very large) loop. The eval statements are database stored code (mixed html & php) that needs to be processed. There is however is a serious performance issue because of this.
Instead of parsing the eval-statement every time in the loop, I would like to create a dynamic methods from the available eval-codes coming from the database within my class.
I thought of the following pseudocode so that the eval code is converted to a method:
class foo
{
private $test=3;
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset(${$func}))
{
${$func}=create_function('',$string);
}
${$func}();
}
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....'
However when running it I get the error message "Using $this when not in object context in ...". So obviously I didn't really create methods within the class.
So my question is:
How do I create a method for a class dynamically and assign code for the given method. Basically I want to be able to do:
$obj_foo->evalcode_001();
in the above example.
Help appreciated
PS I am using PHP5.4
If you can change $this->test inside string (or write extra preg_match) you can use:
<?php
class foo
{
public $test=3;
public $functions = array();
public function doloop()
{
for($i=0;$i<5;$i++)
{
$string="echo 50 * \$this->test.'<br>';";
$func="evalcode_001";
if(!isset($this->functions[$func]))
{
$string = str_replace('$this','$object', $string );
$this->functions[$func]= create_function('$object',$string);
}
$this->functions[$func]($this);
}
}
public function __call($name, $arguments) {
if (isset($this->functions[$name])) {
return $this->functions[$name]($this);
}
}
public function otherMethod() {
echo "test";
}
}
$obj_foo = new foo();
$obj_foo->doloop();//must output '150<br>150<br>150<br> .....
$obj_foo->evalcode_001();
$obj_foo->otherMethod();
However as other said I wouldn't like to use anything like that in my real script

PHP access property of individual method inside object

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.

Method Chaining and Class Inheritance

I think I have more or less managed to get a grasp on OOP/Inheritance, and the basics of method chaining I think I understood as well. However I am still confused about how to actually use some of it.
I wanted to do something that I've seen when working with Magento before:
In Magento, I've seen some sort of "selector-function" used in method chaining. It's a little hard to put into words, but it was something along the lines of:
$categoryName = Mage::getModel('catalog/category')->load($categoryId)->getName();
It's the load($categoryId) part that interests me, as in, a function that selects some instance of something and allows me to run a function on that specific instance.
Now, I am writing a module that allows me to configure certain promotions on our website. Seeing as we'll have many different promotions and I want them to be easily configurable and modifiable, I wanted to do something similar.
So, if I wanted to be able to do something like this:
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo $prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo $prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
How would the class definition for that have to look like?
This may be much more simple or much more complicated than I anticipate. In either case, thanks a lot!
Edit:
So I did some testing around with the info deceze gave me, but I'm still confused.
Bad naming and putting 2 classes in 1 file aside, here's what I did:
class file:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
$this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $name;
}
}
and the run file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
This gives me Fatal error: Call to a member function setName() on a non-object in /var/www/test/index.php on line 11.
But why? Shouldn't getPromo() give me back the object?
Thanks again..
Thanks to the great guys here, it works now. In case anyone were to pass by here with the same or a similar question, here's the final, working code:
Classes:
class Promotion {
private $__arr = array();
public function addPromo($name) {
$this->__arr[$name] = new Promo();
}
public function getPromo($name) {
return $this->__arr[$name];
}
}
class Promo {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Test file:
require_once 'class.php';
error_reporting(E_ALL);
$prm = new Promotion();
$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');
echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!
Method chaining is really simple, all it does is use one particular element of PHP's syntax:
When a function returns an object, you can directly continue with -> after that function.
The longhand version can be:
$bar = $foo->bar();
$baz = $bar->baz();
echo $baz;
$foo->bar() returns an object ($bar) which has a method baz(), and that method returns some value ($baz). This can be written in shorthand like so:
echo $foo->bar()->baz();
$foo->bar() still returns an object which has a method baz(), so you can directly call it without assigning it to an intermediate variable. Maybe this makes it more obvious:
echo ( $foo->bar() )->baz();
You're calling the baz() method on whatever $foo->bar() returns.
$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
As such, in your above case, all you need to do is to return an object which has the method setName from getPromo. I would assume getPromo is supposed to return some object of, say, the Promo class. If the Promo class has a method setName, you're all set.
If you want to chain methods you just need to always return the object like this
class Chain {
public function firstChain() {
//do something
return $this;
}
public function secondChain() {
//do some stuff
return $this;
}
}
Than when you have an instance of the class you do like this:
$obj = new Chain();
$obj->fistChain()->secondChain();

Pass the current class as parameter

I have a class like this:
// file /models/person.php
class Person
{
public function create_path()
{
self::log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
This is the way how Person is instanciated:
//file /tools/Builder.php
include('/models/Person.php');
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
As you note in Person class, I am calling the object in question with $this reference. But this is not correct because an error is showed:
Message: Undefined variable: this
I suppose that $this reference point to other object or it is unable to work because the object is created from another script. Also, I tried to use self because there was not problem calling methods with that, but as parameter I get:
Message: Use of undefined constant self - assumed 'self'
So, can you guide me to the right direction?
I tested your code out for myself, with a few minor changes. It appears to work properly.
Changed self::log() to $this->log()
Added global function path_helper (I have no idea what this does)
PHP
function path_helper(Person $object)
{
var_dump($object);
}
class Person
{
public function create_path()
{
$this->log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
$Build = new Builder();
$Build->build();
Result
trying to create a path
object(Person)[2]
Your code is correct and your going in the right direction.
You should call the log method like this:
$this->log();
because using self:: is reserved for static methods.
Also, try calling the path_helper function like this:
path_helper(self);
Hope I could help you. Couldn't test it, but it should work.

Create and use anonymous object in PHP

Say I have a simple class and I create it and call a function on it like this:
class tst
{
private $s = "";
public function __construct( $s )
{
$this->s = $s;
}
public function show()
{
return $this->s;
}
}
$t = new tst( "hello world" );
echo "showing " . $t->show() . "\n";
Is there any syntax or workaround that will allow me to instantiate an instance of tst and call the show() function without assigning the object to a variable? I want to do something like:
echo new tst( "again" )->show();
I don't want to declare my functions as static as I want to use them in both of the above examples.
You can't do what you want exactly, but there are workarounds without making things static.
You can make a function that returns the new object
function tst( $s ) {
return new tst( $s );
}
echo tst( "again" )->show();
To answer your question:
public static function create( $s )
{
return new tst($s);
}
public function show()
{
return $this->s;
}
The above will allow you to do tst::create("again")->show(). You can rename create as you like.
Agile Toolkit uses this approach everywhere. It uses add() method wrapper which is defined for global object ancestor. Here is some real-life code:
$page
->add('CRUD')
->setModel('User')
->setMasterField('admin',false);
This code creates 'CRUD' view, puts it on the page, creates and links with Model_User class instance which receives additional condition and default value for boolean 'admin' field.
It will display a CRUD control on the page with add/edit/delete allowing to edit all users except admins.
Here is code to describe concept:
class AbstractObject {
public $owner;
function add($class){
$c=new $class;
$c->owner=$this;
return $c;
}
}
class Form extends AbstractObject {
function dosomething(){
return $this;
}
}
class OtherForm extends Form {}
$object->add('Form')->dosomething()->owner
->add('OtherForm'); // etc
I think it's awesome and very practical approach.
p.s. I have to note new syntax for exceptions:
throw $this->exception('Something went bad');
using $this links exception to the object, which is at fault, which also can set default class for exception.

Categories