I have a Class
<?php
class cms{
private $dataset;
private $columns;
private $configs;
public function __construct(){
global $frw, $dbg;
$this->configs =array();
}
public function __get($key){
if(array_key_exists($key, $this->configs)==true){
return $this->configs[$key];
}else{
throw new Exception('Unable to get value from configuration. '.$key);
}
}
public function __set($key, $value){
if(array_key_exists($key,$this->configs)){
throw new Exception('Unable to set configuration. '.$key);
}else{
$this->configs[$key] = $value;
}
}
public function exists($key){
if(isset($this->configs[$key])){
return true;
}else{
return false;
}
}
public function load(){
}
}
?>
$cms = new $cms;
I need to have a variable set on the page that instatiates the object and is available globally throughout each page (for duration of session). I do not want a session variable and I'd like not to use a global. Is there a way of passing the $dataset between pages and calling $cms->dataset in an xajax load. I keep thinking that I should be able to set a variable $dataset = $cms->__get('dataset');
Declare $dataset as public right now private $dataset is not accessible out side the class
public $dataset;
will be accessible outside the class
$cms->dataset
Related
I have a class that requires a variable that is defined out of the scope of it. So i tried using global but, this causes this error:
syntax error, unexpected 'global' (T_GLOBAL), expecting function (T_FUNCTION)
I am unsure if I have put it in the wrong place or using the global keyword incorrectly.
My code looks like this:
$data = new testClass();
class System
{
private $values;
global $data;
public function __construct()
{
}
public function test()
{
return $data->get();
}
}
$system = new System();
echo $system->test();
So i was wondering how do I get the $data variable to be defined in my class? My use of global seems to be incorrect, I also put the global declaration in the __contrust() function but that didn't work either.
Define the global variable within the function instead of the class:
public function test()
{
global $data;
return $data->get();
}
EDIT: Alternate idea:
class System
{
private $values;
private $thedata;
public function __construct($data)
{
$this->thedata = $data;
}
public function test()
{
return $this->thedata->get();
}
}
$data = new testClass();
$system = new System($data);
echo $system->test();
So i was wondering how do I get the $data variable to be defined in my class? My use of global seems to be incorrect, I also put the global declaration in the __contrust() function but that didn't work either.
If you really want to use bad global construction, you should do like this:
class System
{
private $values;
// removed global from here
public function __construct()
{
}
public function test()
{
// added global here
global $data;
return $data->get();
}
}
But OOP principles recommend us to use composition, not global variables. So you can pass the $data into your another class via constructor or via setter. Here's some code implementing both approaches:
class testClass {
public function get()
{
echo __CLASS__.'::'.__FUNCTION__;
}
}
class System
{
private $values;
private $data;
public function __construct(testClass $data = null)
{
if ($data) {
$this->data = $data;
}
}
public function setData(testClass $data)
{
$this->data = $data;
}
public function test()
{
return $this->data->get();
}
}
$data = new testClass();
// via constructor
$system = new System($data);
// or via setter
$system = new System;
$system->setData($data);
echo $system->test();
You could pass $data when you instantiate the class and then assign it in the constructor, which will make it available to all the methods of the class.
class System {
public $data;
public function __construct($data) {
$this->data = $data;
}
public function index() {
echo $this->data;
}
}
$data = 'foo';
$system = new System($data);
echo $system->index();
outputs 'foo';
First things first... This could just be a simple "bad PHP syntax" issue. Look for forgotten ; or in my case... Forgetting that functions actually need the word function : )
I am trying to understand how to efficiently create a new class object and set the variables directly.
I have a class:
class element_model
{
public $sType;
public $properties;
}
I have a controller in which the following function is defined:
public function create_element($sType, $properties)
{
$oElement_model = new element_model($sType, $properties);
return new element_model($sType, $properties);
}
But this does not returns a new element_model with properties set, it just returns an empty object.
It does not, however, throw an error.
What is the reason the function above does not work?
You have to pass to the constructor of the class, in PHP you should have a method in the class __construct :
class element_model
{
public $sType;
public $properties;
public function __construct($type, $property)
{
$this->sType = $type;
$this->properties = $property;
}
}
Then you can access them (note the variables are public)
$elem = new element_model($sType, $properties);
$elem->sType;
Although in some cases it is better to encapsulate vars (declare them private):
class element_model
{
private $sType;
private $properties;
public function __construct($type, $property)
{
$this->sType = $type;
$this->properties = $property;
}
public function getType()
{
return $this->sType;
}
public function getProperty()
{
return $this->properties;
}
}
Then you can access the variable through a getter
$elem = new element_model($sType, $properties);
$elem->getType(); //and
$elem->getProperty();
You must create a __construct function in your class that accepts the parameters and sets your variables. Like this:
class element_model{
.
.
.
public function __construct($type,$properties)
{
$this->sType = $type;
$this->properties = $properties;
}
}
The __construct function will be called when you create the object.
But if you want to be extra cool in programming, just define your properties as private and create getter and setter functions to access the variables of your object
private $sType;
public function getSType(){
return $this->sType;
}
public function setSType($value){
$this->sType = $value;
}
I've 3 classes. [1]Singleton [2]Load [3]Dashboard . In Load class there is one method called 'model()'. Where i'm initializing data for singleton object by using this code.
$obj = Singleton::getInstance();
$obj->insertData('email', 'mail#domain.com');
Again, from Dashboard class there is one method called 'show()' from where i'm trying to print the Singleton object data. But, here i can see all the data of Singleton object except the data which has been initialized by 'model' method of 'Load' class.
Here is my full code...
<?php
//---Singletone Class---
class Singleton
{
// A static property to hold the single instance of the class
private static $instance;
// The constructor is private so that outside code cannot instantiate
public function __construct() {
if(isset(self::$instance))
foreach(self::$instance as $key => &$val)
{
$this->{$key} = &$val;
}
}
// All code that needs to get and instance of the class should call
// this function like so: $db = Database::getInstance();
public static function getInstance()
{
// If there is no instance, create one
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Block the clone method
private function __clone() {}
// Function for inserting data to object
public function insertData($param, $element)
{
$this->{$param} = $element;
}
}
//---LOAD class---
class Load
{
function __construct()
{
$obj = Singleton::getInstance();
$obj->insertData('country', 'INDIA');
}
function model()
{
$this->name = 'Suresh';
$obj = Singleton::getInstance();
$obj->insertData('email', 'mail#domain.com');
}
function msg()
{
return('<br><br>This message is from LOAD class');
}
}
$obj = Singleton::getInstance();
$load = new load();
$obj->load = $load;
//---Dashboard Class---
class Dashboard extends Singleton
{
function __construct()
{
parent::__construct();
}
function show()
{
echo "Default data in current Object";
echo "<br>";
print_r($this);
echo $this->load->msg();
$this->load->model();
echo "<br><br>Data in current Object after post intialization";
echo "<br>";
print_r($this);
}
}
$dashboard = new dashboard();
$dashboard->show();
If your singleton was truly a singleton then the update would have worked. I'm suspecting that you may have multiple instances of the singleton class that is initialized.
Edit:
Also its not a good idea to inherit from a true singleton class.
You need to remove the inheritance that Dashboard has on Singleton
Edit:
Best practice on PHP singleton classes
I don't like your direct access to an object like an array. This one is a better approach [see here]:
You should call it like this:
$obj = Singleton::getInstance();
$load = new Load();
$obj->insertData( 'load', $load );
Implementation of Singleton:
class Singleton
{
// A static property to hold the single instance of the class
private static $instance;
// my local data
protected $_properties;
// You might want to move setter/getter to the end of the class file
public function __set( $name, $value )
{
$this->_properties[ $name ] = $value;
}
public function __get( $name )
{
if ( ! isset( $this->_properties[ $name ] )) {
return null;
}
return $this->_properties[ $name ];
}
// No need to check, if single instance exists!
// __construct can only be called, if an instance of Singleton actually exists
private function __construct() {
$this->_properties = array();
foreach(self::$instance as $key => &$val)
{
$this->_properties{$key} = &$val;
}
}
public static function getInstance()
{
if (!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
// Function for inserting data to object
public function insertData($param, $element)
{
$this->_properties{$param} = $element;
}
// Block the clone method
private function __clone() {}
}
We have a class that holds a public array called $saved that contains lots of data required to share between methods (example below)...
class Common {
public $saved = array();
public function setUser($data) {
$this->saved['user_data'] = $data;
}
public function getUserID() {
return $this->saved['user_data']['id'];
}
}
There are literally thousands of lines of code that work like this.
The problem is that new instance of classes that extend Common are being made within some methods so when they access $saved it does not hold the same data.
The solution is to make $saved a static variable, however I can't change all of the references to $this->saved so I want to try and keep the code identical but make it act static.
Here is my attempt to make $this->saved calls static...
class PropertyTest {
private $data = array();
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
return null;
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
}
class Common {
public $saved;
private static $_instance;
public function __construct() {
$this->saved = self::getInstance();
}
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new PropertyTest();
self::$_instance->foo = array();
}
return self::$_instance->foo;
}
}
This doesn't quite work when setting a variable it doesn't seem to stay static (test case below)...
class Template extends Common {
public function __construct() {
parent::__construct();
$this->saved['user_data'] = array('name' => 'bob');
$user = new User();
}
}
class User extends Common {
public function __construct() {
parent::__construct();
$this->saved['user_data']['name'] .= " rocks!";
$this->saved['user_data']['id'] = array(400, 10, 20);
}
}
$tpl = new Template();
print_r($tpl->saved['user_data']);
$this->saved is empty when User gets initialized and doesn't seem to be the same variable, the final print_r only shows an array of name => bob.
Any ideas?
First of all, I have to say that, IMO, it is not that good to use an instance's property as a class's property ($saved is not declared as static but its value is shared with all instance).
Here is a working version http://codepad.org/8hj1MOCT, and here is the commented code. Basically, the trick is located in using both ArrayAccess interface and the singleton pattern.
class Accumulator implements ArrayAccess {
private $container = array();
private static $instance = null;
private function __construct() {
}
public function getInstance() {
if( self::$instance === null ) {
self::$instance = new self();
}
return self::$instance;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
class Common {
public $saved = null;
public function __construct() {
// initialize the "saved" object's property with the singleton
// that variable can be used with the array syntax thanks to the ArrayAccess interface
// so you won't have to modify your actual code
// but also, since it's an object, this local "$this->saved" is a reference to the singleton object
// so any change made to "$this->saved" is in reality made into the Accumulator::$instance variable
$this->saved = Accumulator::getInstance();
}
public function setUser($data) {
$this->saved['user_data'] = $data;
}
public function getUser() {
return $this->saved['user_data'];
}
}
class Template extends Common {
// you can redeclare the variable or not. Since the property is inherited, IMO you should not redeclare it, but it works in both cases
// public $saved = null;
public function __construct() {
// maybe we can move this initialization in a method in the parent class and call that method here
$this->saved = Accumulator::getInstance();
}
}
I think there are a number of issues with this implementation that could well come back to bite you. However, in your current implementation your contructing a new instance (albeit through a static call) every time.
Instead use getInstance() as your singleton hook, and make your __construct private, as you'll only be accessing it from with the context of the Common class.
Like so:
class Common {
public $saved;
private static $_instance;
private function __construct() {
}
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new self();
... any other modifications you want to make ....
}
return self::$_instance;
}
}
And don't ever run parent::_construct(), instead always use the getInstance() method.
You might also want to ditch the idea of extending this singleton class. This is really a bad antipattern and could cost you a number of issues in the long run. Instead just maintain a Common class that other classes can read / write to. As its a singleton you don't need to worry about injection.
I seem to have solved the problem, by making $this->saved a reference to a static variable it works...
class Common {
private static $savedData = array();
public $saved;
public function __construct() {
$this->saved =& self::$savedData;
}
}
I have a php singleton session class as follows.
class Session {
static private $_instance = NULL;
private function __construct()
{
session_start();
}
/**
* Prevents the class from being cloned
* #return NULL
*/
private function __clone() { }
/**
* Returns the singleton instance of this class
* #return Session
*/
public static function getInstance()
{
if (!self::$_instance) {
self::$_instance = new Session();
}
return self::$_instance;
}
public function __get($key) {
if (isset($_SESSION[$key])) {
return $_SESSION[$key];
}
return NULL;
}
public function __set($key, $value)
{
$_SESSION[$key] = $value;
}
public function __isset($key) {
return isset($_SESSION[$key]);
}
public function __unset($key) {
unset($_SESSION[$key]);
}
}
I can create an object as follows
$session = Session::getInstance();
$session->name = 'some name';
I can also get the value like
echo $session->name;
The problem is, i want to pass an array to this object and it is not working. for example, i wan to set something like
$_SESSION['user']['data'] = array('name'=>'some name',"empId"=>'123');
I am trying like this.
$session->['user']['data'] = array('name'=>'some name',"empId"=>'123');
but it is not working. Could you please suggest what is wrong.
The workaround in this case would be to use:
public function &__get($key) {
if (isset($_SESSION[$key])) {
return & $_SESSION[$key];
}
return NULL;
}
You need to modify the __get() method, because an assignment like
$session->user['data'] = ...
will actually retrieve the [user] key, and then try to assign a new subarray [data] to that temporary array result.
Also note that $session->['user']['data'] is invalid syntax. You either need $session->user['data'] or $session->{'user'}['data'].
Anyway, I think it is probably not a good idea to use a wrapper if you often want to do assignments like that. (I do actually have something very similar.)
$session->user = array('data' => array('name'=>'some name',"empId"=>'123'));
Make sure you don't overwrite anything else in user you want to keep