This may be of help to some. I was looking for a way to have a wrapper class with subclasses.
From the subclasses, I wanted to be able to call functions (and even pass arguments to those functions) from other subclasses, using the wrapper class as a bridge.
My solution:
---------------------
class parser
{
var $class;
function parser()
{
$this->class = array();
}
function LoadClass($className)
{
$this->class[$className] = new $className;
}
function RunFunction($className, $functionName, $functionArgs=array() )
{
call_user_func_array( array( &$this->class[$className], $functionName) , $functionArgs);
}
function GetVarValue($className, $varName)
{
return $this->class[$className][$varName];
}
}
class test
{
var $myvar;
var $name;
function test()
{
$this->myvar = 1;
$this->name = "Shaun";
}
function runme($name=null)
{
if ($name !== null)
{
echo "Hi " . $name;
}
else
{
echo "Hi " . $this->name;
}
}
}
class test2 extends parser
{
function runme()
{
parent::LoadClass("test");
parent::RunFunction("test", "runme", array("name" => "Bob") );
}
}
Usage:
-----------
$parser = new parser;
$test = new test;
$test2 = new test2;
$test2->runme(); // outputs Bob
Clases y Objetos (PHP 4)
Table of Contents
- extends
- Constructores
- Operador de Resolución de Contexto (::)
- parent
- Seriación de objetos, objetos en sesiones
- Las funciones mágicas __sleep y __wakeup
- Las referencias al interior del constructor
- Comparación de objetos
class
Una clase es una colección de variables y funciones que trabajan con estas variables. Las variables son definidas con var y las funciones con function. Una clase es definida usando la siguiente sintaxis:
<?php
class Carrito {
var $items; // Ítems en nuestro carrito de compras
// Agregar $num artículos de $artnr al carrito
function agregar_item($artnr, $num) {
$this->items[$artnr] += $num;
}
// Tomar $num artículos de $artnr del carrito
function retirar_item($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} elseif ($this->items[$artnr] == $num) {
unset($this->items[$artnr]);
return true;
} else {
return false;
}
}
}
?>
Esto define una clase llamada Carrito que consiste de una matriz asociativa de artículos en el carrito y dos funciones para agregar y eliminar elementos del carrito.
NO es posible separar la definición de una clase en varios archivos. Asimismo NO es posible separar la definición de una clase en bloques PHP diferentes, a menos que la separación sea al interior de una declaración de método. Lo siguiente no funciona:
<?php
class prueba {
?>
<?php
function prueba() {
print 'Bien';
}
}
?>
Sin embargo, lo siguiente es permitido:
<?php
class prueba {
function prueba() {
?>
<?php
print 'Bien';
}
}
?>
Las siguientes notas de precaución son válidas para PHP 4.
El nombre stdClass es usado internamente por Zend y es reservado. No puede tener una clase con el nombre stdClass en PHP.
Los nombres de función __sleep y __wakeup son mágicos en las clases PHP. No puede tener funciones con estos nombres en cualquiera de sus clases a menos que desee usar la funcionalidad mágica asociada con ellas. Vea más información a continuación.
PHP reserva todos los nombres de función que comienzan con __ como mágicos. Se recomienda que no use nombres de función con __ en PHP a menos que desee usar alguna funcionalidad mágica documentada.
En PHP 4, sólo se permiten inicializadores constantes para variables var. Para inicializar variables con valores no-constantes, necesita una función de inicialización que sea llamada automáticamente cuando un objeto es construido a partir de la clase. Tal función es llamada constructora (vea más información a continuación).
<?php
class Carrito {
/* Ninguna de estas expresiones funciona en PHP 4. */
var $fecha_hoy = date("Y-m-d");
var $nombre = $primer_nombre;
var $duenyo = 'Fred ' . 'Jones';
/* Aunque, las matrices que contienen valores constantes funcionan */
var $items = array("VCR", "TV");
}
/* Así es como debe declararse. */
class Carrito {
var $fecha_hoy;
var $nombre;
var $duenyo;
var $items = array("VCR", "TV");
function Carrito() {
$this->fecha_hoy = date("Y-m-d");
$this->nombre = $GLOBALS['primer_nombre'];
/* etc. . . */
}
}
?>
Las clases son tipos, es decir, son planos usados para variables reales. Necesita crear una variable del tipo deseado con el operador new.
<?php
$carrito = new Carrito;
$carrito->agregar_item("10", 1);
$otro_carrito = new Carrito;
$otro_carrito->agregar_item("0815", 3);
?>
Esto crea los objetos $carrito y $otro_carrito, ambos de la clase Carrito. La función agregar_item() del objeto $carrito es llamada para agregar 1 item del artículo número 10 al $carrito. Se agregan 3 items del artículo número 0815 al $otro_carrito.
Ambos, $carrito y $otro_carrito, tienen funciones agregar_item(), retirar_item() y una variable items. Estas son variables y funciones diferentes. Puede pensar sobre los objetos como algo similar a las directorios en un sistema de archivos. En un sistema de archivos es posible tener dos archivos LEAME.TXT diferentes, siempre y cuando estén en directorios diferentes. Tal y como con los directorios, en donde es necesario escribir las rutas de nombres completas para llegar a cada archivo a partir del directorio del nivel superior, es necesario especificar el nombre completo de la función que desea llamar: en términos de PHP, el directorio de nivel superior sería el espacio de nombres global, y el separador de ruta sería ->. De tal modo que los nombres $carrito->items y $otro_carrito->items hacen referencia a dos variables diferentes. Note que la variable se llama $carrito->items, no $carrito->$items, es decir, un nombre de variable en PHP solo tiene un único signo de dólar.
<?php
// correcto, un solo $
$carrito->items = array("10" => 1);
// inválido, ya que $carrito->$items se convierte en $carrito->""
$carrito->$items = array("10" => 1);
// correcto, pero puede o no ser lo que se busca:
// $carrito->$mivar se convierte en $carrito->items
$mivar = 'items';
$carrito->$mivar = array("10" => 1);
?>
Al interior de una definición de clase, no se conoce el nombre bajo el que el objeto será accesible en su programa: en el momento en que la clase Carrito fue escrita, no se conocía si el objeto se llamaría $carrito, $otro_carrito, o algo diferente más adelante. Por lo tanto, no es posible escribir $carrito->items al interior de la clase Carrito. En su lugar, para poder acceder a sus propias funciones y variables desde el interior de una clase, es posible usar la pseudo-variable $this, la cual puede leerse como 'mi propio' o 'el objeto actual'. Por lo tanto, '$this->items[$num_art] += $num' puede leerse como 'agregar $num al contador $num_art de mi propia matriz de items', o 'agregar $num al contador $num_art de la matriz de items al interior del objeto actual'.
Note: Usualmente, la pseudo-variable $this no es definida si el método en el que se encuentra es llamado estáticamente. Sin embargo, esta no es una regla estricta: $this se define si un método es llamado estáticamente desde el interior de otro objeto. En este caso, el valor de $this es aquél del objeto que hace la llamada. Esto se ilustra en el siguiente ejemplo:
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this se define (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this no se define.\n";
}
}
}
class B
{
function bar()
{
A::foo();
}
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>El resultado del ejemplo seria:
$this se define (a) $this no se define. $this se define (b) $this no se define.
Note: Existen algunas funciones interesantes que manejan clases y objetos. Puede que quiera echar un vistazo a las Funciones de Clase/Objeto.
Clases y Objetos (PHP 4)
03-Apr-2008 04:55
22-Oct-2007 03:01
A little expanssion on the original shopping cart example.
It may look inherit to advance class user but to a beginer it will be helpful.
<?php
class Cart {
var $items; // Items in our shopping cart
// Add $num articles of $artnr to the cart
function add_item($artnr, $num) {
$this->items[$artnr] += $num;
}
// Take $num articles of $artnr out of the cart
function remove_item($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} elseif ($this->items[$artnr] == $num) {
unset($this->items[$artnr]);
return true;
} else {
return false;
}
}
function print_item($artnr) {
$blah=$this->items[$artnr];
return $blah;
}
}
?>
<?php
$cart = new Cart;
$cart->add_item("10", 5);
$cart->add_item("10", 3);
$cart->remove_item("10", 1);
echo $cart->print_item("10");
$another_cart = new Cart;
$another_cart->add_item("0815", 3);
?>
Added a print_item() function that returns the number of items in the shopping cart class for a specific item, for later manipulation as a variable.
28-Aug-2007 03:55
class casting (type casting to an extended class) workaround. Useful to use functionality in an extended class on an instance of a base class (especially when the BaseClass file needs to be small and the extended class functions are huge). Tested to work on public, protected and private vars in PHP5.
---
class ABaseClass
{
private $T1;
protected $T2;
public $T3;
public function CopyFrom( )
{
// If this class had parents then you will want to implement and use parent::$CopyFrom( ). If not, then private members in the parent class will not be copied.
return get_object_vars( $this );
}
protected function CopyInto( $VarArr )
{
// If this class had parents then in order to copy the private values we must implement and use parent::CopyInto( $VarArr ).
$TempArr = get_class_vars( __CLASS__ );
foreach( $TempArr as $VarName => $Var1 )
{
$this->$VarName = $VarArr[ $VarName ];
}
}
}
class AnExtendedClass extends ABaseClass
{
public function __construct( $theBaseClassInstance )
{
$this->CopyInto( $theBaseClassInstance->CopyFrom( ) );
}
public function LongFunctionIntheFileWithTheExtendedClass( )
{
// Bla Bla Bla
}
}
---
$BaseInstance = new ABaseClass();
...
$ExtendedInstance = new AnExtendedClass( $BaseInstance );
$ExtendedInstance->LongFunctionIntheFileWithTheExtendedClass( );
19-Aug-2007 07:29
You may asign classes to arrays:
<?php
class foo
{
function test_foo()
{
echo "test_foo 1 2 3<br />";
}
}
class bar
{
function test_bar()
{
echo "test_bar 1 2 3<br />";
}
}
$classes = array();
$classes['foo'] = new foo();
$classes['bar'] = new bar();
$classes['foo']->test_foo();
$classes['bar']->test_bar();
?>
Output:
test_foo 1 2 3
test_bar 1 2 3
13-Apr-2006 05:31
I took the above examples and extented them slightly to also allow you to run any function in the subclass without having to first declare it in the main class.
Enjoy
<?php
class mainClass
{
/*
* Class loading function.
*
*
*
*
*/
var $module;
function LoadClass($loadModule)
{
$this->module = new $loadModule; // this is much better
}
function RunFunction($FunctionName)
{
$this->module->$FunctionName();
}
function ListFunctions()
{
}
// function out()
//{
// $this->module->out();
// }
}
class subclass
{
function out()
{
echo "Worked";
}
function NewFunction()
{
echo "<br>Good Lord<br>";
}
function ThirdFunction()
{
echo "<br>eh....<br>";
}
}
echo "Start of class manulapations<br>";
//$loadModule = new subclass;
$mainclass=new mainClass;
$mainclass->LoadClass("subclass");
//$mainclass->out();
$mainclass->RunFunction('NewFunction');
//$mainclass->ThirdFunction();
echo "End of class manulapation<br>";
?>
09-Feb-2006 02:57
PHP Allow to extend a class in a dinamic way into a object and only affects that object not the others of the same class.
I was developing a persistence class and i found this:
<?php
class MyClass {
var $Prop1;
// Into the constructor i create a propertie that was not declared before.
function MyClass() {
$this->Prop2 = "This was not declared but now exists into the object";
}
function setProp($PropName, $PropValue) {
$this->$PropName = $PropValue;
}
}
$MyObj = new MyClass();
$MyObj->setProp("Prop1", "This was declared and now has value");
$MyObj->setProp("Prop3", "This was declared by setProp() method.");
$MyObj->Prop4 = "This was declared out of the class definition";
echo "Prop1: ".$MyObj->Prop1." <br />\r\n";
echo "Prop2: ".$MyObj->Prop2." <br />\r\n";
echo "Prop3: ".$MyObj->Prop3." <br />\r\n";
echo "Prop4: ".$MyObj->Prop4." <br />\r\n";
?>
This could be very useful, but very dangerous too, take care.
02-Feb-2006 05:30
In case you would like to interrupt object construction on some condition and return false for further checking:
<?php
class Foo
{
// Constructor
function Foo()
{
/* Some inits here */
$someval=false;
if ($someval===false)
{
return false;
}
}
}
$obj=new Foo(); // This won't work and will return partially initialised object instead of false
class Bar
{
// Constructor
function Bar()
{
/* Some inits here */
$someval=false;
if ($someval===false)
{
$this=false;
return;
}
}
}
$obj2=new Bar(); // This will work as expected and return false
?>
Hope this helps some people.
20-Oct-2005 08:46
This class method allows you to take a nice associative array of parameters into your class when the number of parameters gets unmanagable and/or has lots of default-value parameters.
It is so useful I suggest putting on a general base class (I call mine Object) so all your descendents can use it.
-----------------------------------------------------
Code:
-----------------------------------------------------
function setClassVars( &$parameter_array )
{
$class = get_class($this);
$class_vars = get_class_vars($class);
/*
* check that each of the passed parameters are valid before setting the
* appropriate class variable.
*/
foreach ( $parameter_array as $var => $value ){
if ( array_key_exists( $var, $class_vars ) ){
$this->$var = $value;
}
else{
$this->raiseError(
'setClassVars: class variable "' .
$var .
'" does not exist on class "' .
$class . '"'
);
}
}
}
-----------------------------------------------------
for example:
A complicated, messy, class method Before:
-----------------------------------------------------
render(
&$business_object,
$on_change=false,
$on_blur=false,
$options=false
$name
){
$this->business_object = $business_object;
$this->name = $name;
$this->on_blur = $on_blur;
$this->options = $options;
<code>
}
-----------------------------------------------------
A nice clean method After:
-----------------------------------------------------
render(
&$parameter_array
){
$this->setClassVars($parameter_array);
<code>
}
-----------------------------------------------------
Example call:
-----------------------------------------------------
$parameter_array =
array(
'business_object' => $business_object,
'name' => $field_name,
'on_change' => 'form.submit()',
'on_blur' => 'javascript:validate()',
$options =>
array(
'1' => 'None Selected',
'2' => 'Blue',
'3' => 'Red'
)
);
$my_object->render( &$parameters );
-----------------------------------------------------
Now isn't that easier to read AND maintain. Now you can change your API without the hassle of amending every call to the method! You no longer have to worry about where the default params are or even the order of your params.
I hope someone else who has been swearing at their code finds this useful ;-)
10-Oct-2005 09:18
My way to implement a singleton in PHP4. I think it's the most convenient one since it works transparently using the constructor. Thanks to S.Radovanovic for his idea with referencing the class' variables, posted on http://www.php.net/manual/en/language.variables.scope.php
<?php
/* Singleton. Every instatiation returns the "same" object.
*
* for this to work, ALWAYS create objects with $object =& new class().
* The reference operator doesn't do any harm in general and is
* necessary for singletons.
*
* You also need to declare all the class' variables with "var" for
* a singleton subclass. But that should always be a rule of good
* design :)
*
* call parent::singleton() first in your subclass constructor.
*
* Of course, the subclass constructor should check if the object is already
* initialized before doing any initialization.
*/
class singleton
{
function singleton()
{
// static associative array containing the real objects, key is classname
static $instances=array();
// get classname
$class = get_class($this);
if (!array_key_exists($class, $instances))
{
// does not yet exist, save in array
$instances[$class] = $this;
}
// PHP doesn't allow us to assign a reference to $this, so we do this
// little trick and fill our new object with references to the original
// class' variables:
foreach (get_class_vars($class) as $var => $value)
{
$this->$var =& $instances[$class]->$var;
}
}
}
?>
04-Oct-2005 05:10
It appears that one must use eval if calling a static function where the name of the class is in a variable:
echo $class::staticfunc();
gets you a "parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM" (in PHP 4.4.0)
while
echo eval("return $class::staticfunc();");
behaves as desired.
Contrast this limitation with `->`which will accept a variable on both sides -- e.g., $myClass->$myFunc() -- and, of course, new $myClass is perfectly happy. The expression myClass::$myFunc() also works.
28-Sep-2005 10:45
to Menno Vanderlist:
And why bother to use eval?
<?php
class mainClass
{ //mainClass
var $module;
function mainClass($loadModule)
{ // load modules
//eval("\$this->module = new $loadModule;");
$this->module = new $loadModule; // this is much better
}
function out()
{ //print out of loaded module
$this->module->out();
}
}
?>
Functionality is the same, without the overhead when using eval().
11-Feb-2005 11:11
If you have a class hierarchy as this:
<?php
abstract class A{
//construct ommited
public function load(){
$this->_load();
}
protected abstract function _load();
}
class B extends A{
protected function _load(){
echo "loaded";
}
}
$b = new B();
$b->load();
?>
you encountered that you will have a 'calling an abstract method' in the line with '$this->_load'. To avoid this, just make another reference to $this and then call the method you'd want, this way:
<?php
abstract class A{
//construct ommited
public function load(){
$aux_this=&$this;
$aux_this->_load();
}
protected abstract function _load();
}
class B extends A{
protected function _load(){
echo "loaded";
}
}
$b = new B();
$b->load();
?>
04-Feb-2005 09:56
Didn't see this anywhere obvious, so I'm posting it here. To access a memeber of an array with another variable you use $arr[$name]
To access a class method or property, you use $obj->{$name} You can also use the return value of a function.
<?php
class Test {
function methodName(){
echo 'works!';
}
}
function getName(){
return 'methodName';
}
$t = new Test();
$t->{getName()}();
//works!
?>
23-Jan-2005 05:32
Although the php 4.2.2 parser and variable storage are case-sensitive, classes + class-function + function declaration *storage* are not.
To example this, consider the following:
[note: constructor is `sendfile()', not `SendFile()' nor `sendFile()']
<?php
class SendFile {
// variables declared here
function SendFile() {
// function defined here
}
function sendFile() {
// function defined here
}
function sendfile() {
// function defined here
}
} // end class SendFile
?>
This was eventually illuminated by:
<?php
print_r( get_declared_classes());
?>
...in which a snippet of the result is:
Array
(
[0] => stdClass
[1] => __PHP_Incomplete_Class
[2] => Directory
[3] => DomNode
[4] => DomDocument
[5] => DomParser
...
[24] => sendfile
)
Specifically, it appears that php has used initial-caps for all of it`s own (internal) classes, but that all user-classes are stored lower-cased, as are class + ordinary functions.
Written in the hope of saving someone else time & grief from this interesting `feature'.
22-Jan-2005 04:44
Just found this interesting "gotcha";
If you implement a class with no member variables, calling the constructor does NOT produce an object. This can be a source of (great) consternation when producing classes which need no data storage.
Essentially if your class has no data members, all its methods are ONLY available statically, this can be a pain if defining object hierarchies with abstract base classes...
Example:
class A
{
function A()
{
$i = 0; // not an empty constructor!
}
function fn()
{
return "A";
}
}
$obj_a = new A();
$obj_a == null
$obj_a->fn(); will generate an error
A::fn(); works
Simply putting a "var $status=0;" in the class suddenly makes your object instantiatable.
This is certainly a "quirk" in an OO implementation, possibly a bug, definitely worth watching out for...
05-Dec-2004 11:52
While it is possible to use the names of existing PHP functions for class method names (not that you *should*, however sometimes there's really only one good name for a method even if it's taken..), you cannot use the names of language constructs like list(), echo, print etc, and appearantly also not of eval().
But you probably shouldn't be using PHP functionnames anyway :-)
05-Sep-2004 06:11
An example of how to pass an object back into its own class for direct use.
(thisClass.php)
<?php
class thisClass{
var $var1;
function thisClass($value)
{$this->var1 = $value;}
function set_var1($value)
{$this->var1 = $value;}
function get_var1()
{return $this->var1;}
function showVar()
{echo "<p>var1 = ".$this->var1."</p>";}
function callShowVar($object)
{$object->showVar();}
function copyObject($object)
{$this->var1 = $object->get_var1();}
}
?>
(test.php)
<?php
require_once('class.php');
$thisObject = new thisClass(3);
$thatObject = new thisClass(1);
$thatObject->callShowVar($thisObject); //outputs "var1 = 3"
$thisObject->showVar(); //outputs "var1 = 3"
$thatObject->showVar(); //outputs "var1 = 1"
$thatObject->copyObject($thisObject);
$thatObject->showVar(); //outputs "var1 = 3"
?>
31-Aug-2004 03:22
We can't split the class declaration in multiple PHP section but we can exit php tag in a function . ex :
<?
class plop {
function plop() {
$this->whatever = "bar";
}
function foo() {
?>
<pre>foo returns <?=$this->whatever?></pre>
<?
}
};
$a = new plop;
$a->foo();
?>
will print : foo returns bar
PHP Version 4.3.8-9
20-Jul-2004 02:04
Say you have a factory method that needs to put data into an object before the constructor is called. This might be necessary, for example, if the factory class establishes a connection to a database and the manufactured object uses that connection in the constructor.
Do something like this:
<?php
function &factory($class /* ... */) {
// 1) get an object shell
$obj = new stdClass();
// 2) "type cast" it to the desired class
$tmp = explode(':', serialize($obj));
$tmp[1] = strlen($class);
$tmp[2] = '"' . $class . '"';
$obj = unserialize(implode(':', $tmp));
// 3) copy construct the manufacturer into the manufacturee
$obj->copyFrom($this);
// 4) call the real constructor
$args = func_get_args();
array_shift($args); // skip the class
call_user_func_array(array (&$obj, $class), $args);
return $obj;
}
?>
NOTE: The Editor's note in the "simon dot li at hongkong dot com" entry is misleading; it only works because the class names "foo" and "bar" are the same length. In general, you must change the first and second entries in serialized array as done above.
Also NOTE: This typecasting business works if you have a function that takes an arbitrary number of arguments and you want to pass those arbitrary arguments into a constructed class. You can't just use call_user_func_array() in that case because 'new' is an operator, not a function.
06-Jul-2004 11:50
Regarding defining class variables:
The 'var' statement can NOT take Heredoc definitions, i.e. the "<<<MARKER" stuff (these may be somehow 'dynamic' as per warning above).
You must assign them values within the class constructor if you must use Heredoc.
16-Jun-2003 06:34
class baseclass {
function static1() {return "bla";}
function static2() {return call_user_func(array(__CLASS__,'static1'));}
}
[ Editor's Note: Using the above, rather than below, will allow the static function to call its own generation's version of the method. ]
Unfortunately, inheritance of static methods is a bit problematic in PHP, because in order to use a static method you have to know the exact class it's defined in. This means trouble if you want to use one static function (or a static variable) from within another static function. For example:
class baseclass {
function static1() {return "bla";}
function static2() {return baseclass::static1();}
}
Now suppose that you write a class newclass that extends baseclass and redefines static1() to return "foo" instead of "bla" - this change will not be reflected in static2() of newclass. Not good at all.
You could use $this->static1() instead of baseclass::static1() in the definition of static2(), but then static2() will not be a static method. Another idea is to use get_class_name() to get the class name inside static2(), but again you need the $this variable to make this function call.
I found no way to overcome this problem, except to use real functions (not methods) for the purpose of wrapping my static functions. The name of the exact class to use is passed as a parameter to the wrapping function. It looks like this:
function wrapped_static1($clname) {
if (in_array('static1', get_class_methods($clname)))
return $clname::static1();
return baseclass::static1();
}
function wrapped_static2($clname) {
if (in_array('static2', get_class_methods($clname)))
return $clname::static2();
return baseclass::static2();
}
class baseclass {
function static1() {return "bla";}
function static2() {return wrapped_static1('baseclass');}
}
Now you can go on using baseclass and writing extension classes for it, using the following rules:
1. Use inheritance with your static functions in the natural way, as you would in C++. The wrapping code given here supports just 1 level of inheritance, but it may be improved to work its way up the inheritance tree using PHP's class functions.
2. When calling a static function, always call it through its wrapper.
For example:
class newclass extends baseclass // example for rule 1
{
function static1() {return 'foo';}
}
print static2_wrapper('newclass'); // example for rule 2
This is a little cumbersome, but now when you redefine a static function, you can be sure that any functions that rely on it will be able to use the correct definition.
18-Apr-2003 09:31
It is sometimes useful to register a class instance as a session variable. This can allow classes and their contained values to persist across multiple pages and/or frames. Frames which need to use the registered class must be loaded (or reloaded) after the class instance is registered and the class declaration must be included in each file that needs to access the registered class.
i.e.
<?
session_start();// must have a session, duh...
class foo{//normal class declaration
var $bar;
function foo(){//normal constructor
$this->bar = "a value to share and persist";
}
}
$vital = new foo;//instance "vital" of object type "foo"
session_register("vital");//register the instance "vital"
//other code as needed
?>
**NOTE: it would be helpful to include the class from an external source so the same declaration could be used everywhere its needed, duh
then simply include the class declaration in any other file and you will have access to the registered class instance. in a separate frame on the same page you could use ...
<?
session_start();
class foo{//same class declaration
var $bar;
function foo(){//normal constructor
$this->bar = "a value to share and persist";
}
}
echo $vital->bar;
?>
**NOTE: if you use a frameset you must allow processing time of the session registration or the value will not be available! You can use any number of methods to trigger the delay, but the session must NOT be started on the second page beforre the variable is registered on the first. On option is to use an onload statement in the first frames body tag, assuming normal html output...
<html><head></head><body onLoad="parent.frame[1].location.reload();"><!--what ever else you need to output--></body></html>
"frame[1]" assumes a two frame layout with frame[0] containing the values to share and frame[1] requiring those values. thus this, when included in frame[0] will force a reload of frame[1] AFTER the class instance was registered.
18-Jan-2003 04:47
In response to the comments above and using tomcats example directly... I love scripting languages and I love PHP the most out of them. While most programmers (and editors notes) try to state that PHP is not a true OO language it has what you need to develop good OO programs. Sure some of the really strong structured things aren't there but that is the fun you get with scripted languages. But after reading every comment on this page I think people (and I know I am going to get flamed for this one...) should start to fully understand the principles of OO programming: Encapsulation, Polymorphism and Abstraction.
For those new to those terms:
- Encapsulation is what you get when you can have data and the methods that act on those data in an "encapsulated" entity (object)
- Polymorphism is a property of objects that comes through inheritence that allows methods of the same name to perform different (but similar in purpose) actions
- Abstration provides a mechanism to design effective OO heirarchies by pulling common methods or actions into superclasses and using inheritence to provide functionality
If these principles are understood fully, PHP can be used as a great OO language. Another common complaint is that PHP doesn't offer private/protected members/methods, I too would like to see these features. One BIG thing to keep in mind while desiging an OO program is that the objects should provide funtionality at the class level. Don't think of objects as individual entities but think of a heirarchy that provides "blackboxes" of code. In otherwords the class names should tell you what the object does and the methods only tell you how to invoke the functionality. You should never be concerned with how the object achieves its functionality.
08-Jul-2001 05:22
If you need a destructor, perhaps it is an idear to simulate it this way with a global Destroy-Function:
<?
function DestroyObject ($name)
{
$theobject = &$GLOBALS[$name];
if (method_exists ($theobject,"Destroy"))
$theobject->Destroy ();
unset ($GLOBALS[$name]);
}
class xyz
{
var $somevar;
// ### This is the constructor
function xyz ()
{
}
// ### This is the destructor which will be called
function Destroy ()
{
echo ("Now we destroy it !");
}
function SomeDo ()
{
echo ("doing something: ".$this->somevar);
}
}
$example = new xyz;
// .... doing something here
$example->somevar = 3;
$example->SomeDo();
DestroyObject ("example");
// ### Test => should produce an error !
$example->SomeDo ();
?>
19-Feb-2001 02:15
[Editor's note: Remember tha PHP is not a hard core OOP language, and even the ones that are do not always support the unusual vector/array references applied to results from methods.]
It seems there is no way to access the return value of a method (or any function) inline, without assigning it to a variable.
For example:
<?php
class Test
{
function blah ()
{
return array(1,2,3);
}
function childTest ()
{
return new Test;
}
}
$test = new Test;
// This does not work:
$foo = $test->blah()[0];
// Instead have to do:
$temp = $test->blah();
$foo = $temp[0];
// Similarly for objects, cannot do:
$foo = $test->childTest()->blah();
// Instead have to do:
$temp = $test->childTest();
$foo = $temp->blah();
?>
14-Feb-2001 04:33
You can also store object variables as session variables, so that you don't have to create an object every time the page loads.
Let's see how:
here is my simple class file:
<?php
// simple.lib.php
class simple
{
function dummy
{
print "TEST SUCCESSFUL!\n";
}
}
?>
Then, I create a simple .php which starts a new session and registers the object-variable of the "simple"-class.
<?php
// test1.php
require ("simple.lib.php");
session_start();
session_register("CLASSOBJ");
$CLASSOBJ=new simple();
?>
That's all.
In the following .php-files you've only to add the following lines:
require("simple.lib.php");
session_start();
To test out if it works, simply call:
$CLASSOBJ->dummy();
and it will print the message.
I tried it out also with quite huge classes, and it always worked (I think the pointer to the instanciated class is stored and the class object itself won't be deleted if you eg. change to another .php-page)
22-Dec-2000 05:23
Defaulting a function parameter to a variable isn't directly supported, but here's how to get around that:
Suppose you have a class:
class query {
var $sql;
var $link;
function go ($SQLstring = $this->sql)
{
return mysql_query($this->sql,$link);
}
}
This doesn't work. Here's the workaround:
(function spec):
function go ($SQLstring)
{
if (isset($SQLstring)) { $this->sql = $SQLstring; }
return mysql_query($this->sql,$this->link);
}
This may not be the best example of this, but I thought I'd throw this out for you folks ... should allow support of presetting of an object value and then execution of the method on that, or something like query::go("SELECT ...");
Enjoy!
p.s. (in this case query::go wouldn't work because it is coded with $this->link, but if you wanted to just use the default connection, it'd work fine :)
09-Oct-2000 01:12
Here's a very important reminder to those of you used to Java/C++ object references/pointers. When you send a function arguments which include a class object, PHP will make copies of that object for use inside that function.
This differs from passing a Java reference to an object or passing a C++ pointer to an object. Within the scope of the above-mentioned function, calling class methods of the argument object will only affect the copy that PHP creates. Likewise, when the function itself is completed, the copy of the object you passed ceases to exist.
To emulate Java/C++ functionality of arguments that are objects, you just have to modify the given function's signature from this:
function foo(..., $object, ...)
to this:
function foo(..., &$object, ...)
The ampersand(&) thus signifies that the function should receive a reference to the object, instead of creating a copy of the object.
