kit dot lester:
Your terrible confusion was caused by a couple of errors in your test code.
Firstly, you had $c.makeme instead of $c->makeme, which screwed that up.
Secondly, inside the class methods, you used $killme instead of $this->killme. $this context is required, otherwise the variables will just be local to the function, and not work as expected.
To wit:
<?
class C {
public $survivor = "s";
public $killme = "k";
}
$c = new C();
//echo $c."<p>";
// No longer echoes "Object #1" in PHP 5.2, throws an error instead
echo "/".$c->survivor."/".$c->killme."/<p>";
// That renders /s/k/ - as I expected.
unset($c->killme);
echo "/".$c->survivor."/".$c->killme."/<p>";
// That renders /s// - as the PHP
// programmer in would expect, but rather
// shocking to the C++-and-Java programmer
// in you.
// HAVING DISCOVERED THAT WORKS, I WONDERED IF THE
// CONVERSE WORKS... SO HERE WE GO...
$c->makeme = "m";
// No hint of a runtime error.
echo "/".$c->survivor."/".$c->killme."/".$c->makeme."/<p>";
// Which renders
// /s//m/
// There was a typo in the orginal code, $c.makeme, which screwed everything up.
// Without the typo, everything works like it should in reverse.
//Therefore there is no inconsistency. However...
class D {
public $survivor = "s";
public $killme = "k";
function echo_killme()
{ echo "killme is ";
if (isset($this->killme)) echo "set to {$this->killme}";
else echo "unset";
echo ".<p>";
}
function echo_makeme()
{ echo "makeme is ";
if (isset($this->makeme)) echo "set to {$this->makeme}";
else echo "unset";
echo ".<p>";
}
function echo_survivor()
{ echo "survivor is ";
if (isset($this->survivor)) echo "set to {$this->survivor}";
else echo "unset";
echo ".<p>";
}
}
$d = new D();
$d->echo_killme();
// Renders
// killme is set to k.
unset($d->killme);
$d->echo_killme();
// Renders
// killme is unset.
$d->makeme = "m";
// No hint of a runtime error, creates on the fly
$d->echo_makeme();
// Renders
// makeme is set to m
//The above problems were caused by not using the $this->var syntax in the methods, as fixed above.
?>
Clases y Objetos (PHP 5)
Table of Contents
- Las Bases
- Auto carga de Objetos
- Constructores y Destructores
- Visibilidad
- Alcance del operador de resolución (::)
- La palabra reservada 'Static'
- Constantes De la Clase
- Abstracción de Clases
- Interfaces de Objetos
- Sobrecarga
- Interacción de Objetos
- Patrones
- Métodos mágicos
- La palabra reservada 'Final'
- Clonado de Objetos
- Comparación de Objetos
- Reflección
- Type Hinting
Introducción
En PHP 5 hay un nuevo modelo de Objetos. El manejo de PHP de objetos ha sido reescrito por completo, permitiendo un mejor desempeño y mas caracterÃsticas.
Tip
See also the Userland Naming Guide.
Clases y Objetos (PHP 5)
cincodenada_NO at SPAM_gmail dot com
21-Aug-2008 02:37
21-Aug-2008 02:37
kit dot lester at port dot ac dot uk
18-Aug-2008 09:21
18-Aug-2008 09:21
<?
class C {
public $survivor = "s";
public $killme = "k";
}
$c = new C();
echo $c."<p>";
// That renders
// Object id #1
// - not documented, and rather handy to
// know for when one is debugging.
echo "/".$c->survivor."/".$c->killme."/<p>";
// That renders /s/k/ - as I expected.
unset($c->killme);
echo "/".$c->survivor."/".$c->killme."/<p>";
// That renders /s// - as the PHP
// programmer in would expect, but rather
// shocking to the C++-and-Java programmer
// in me.
// HAVING DISCOVERED THAT WORKS, I WONDERED IF THE
// CONVERSE WORKS... SO HERE WE GO...
$c->makeme = "m";
// No hint of a runtime error.
echo "/".$c->survivor."/".$c->killme."/".$c.makeme."/<p>";
// Which renders
// /s//Object id #1makeme/
// - which rather appalls all the programmers
// in me - the PHP programmer because he
// thinks it should it should work, and the
// C++/Java programmers because of the
// inconsistency with the unset working...
// Worse: looking at the view/source of what
// was rendered, the -> before makeme is
// missing. No doubt there is some contorted
// explanation of WHY it is missing, but
// that would be a justification for something
// that is undesirable because it will make
// it harder to debug assignments to mis-spelt
// member names.
// THE APPARENT FAILURE TO ASSIGN TO MAKEME, BUT WITH
// NO RUNTIME ERROR ON THE ASSIGNMENT, LEAVES ME
// WONDERING WHETHER IT SUCCEEDED, BUT NOT VISIBLY
// FROM OUTSIDE THE CLASS...
// ...so let's do a more elaborate class definition...
class D {
public $survivor = "s";
public $killme = "k";
function echo_killme()
{ echo "killme is ";
if (isset($killme)) echo "set to $killme";
else echo "unset";
echo ".<p>";
}
function echo_makeme()
{ echo "makeme is ";
if (isset($makeme)) echo "set to $makeme";
else echo "unset";
echo ".<p>";
}
}
$d = new D();
$d->echo_killme();
// Renders
// killme is unset.
// - OK.
$d->makeme = "m";
// No hint of a runtime error.
$d->echo_makeme();
// Renders
// makeme is unset.
// - so (apart from the asymmetry in the
// language) THE ABSENCE OF A RUNTIME
// ERROR IS ANOTHER DEBUGGING HAZARD WHEN
// ASSIGNING TO A MISSPELT MEMBER.
?>
wbcarts at juno dot com
18-Aug-2008 02:49
18-Aug-2008 02:49
Sorry to change the subject, but OOP is way cooler if you "define" and "use" several objects in combination with each other.
<?php
class Point{ // an object that represents a location in 2-dimensional space.
public $x; // x position of this point
public $y; // y position of this point
public function __construct($xPos = 0, $yPos = 0){
$this->x = $xPos;
$this->y = $yPos;
}
public function __toString(){ // get a string representation of this point
return 'Point(' . $this->x . ', ' . $this->y .')';
}
}
class Line{ // an object that represents a line in 2-dimensional space
public $start; // start point of this line
public $end; // end point of this line
public function __construct($xPos1 = 0, $yPos1 = 0, $xPos2 = 0, $yPos2 = 0){
$this->start = new Point($xPos1, $yPos1); // create a Point object
$this->end = new Point($xPos2, $yPos2); // create a Point object
}
public function getLength(){ // get the length of this line
return sqrt(
pow(($this->start->x - $this->end->x), 2) +
pow(($this->start->y - $this->end->y), 2)
);
}
public function __toString(){ // get a string representation of this line
return 'Line[start=' . $this->start . ', end=' . $this->end .
', length=' . $this->getLength() . ']';
}
}
// create a few objects of TYPE Line.
$line1 = new Line(25, 25, 40, 40);
$line2 = new Line(10, 10, 30, -10);
$line3 = new Line(-50, 65, 50, 65);
// output to the display
echo '<p>$line1 = ' . $line1 . '</p>
<p>$line2 = ' . $line2 . '</p>
<p>$line3 = ' . $line3 . '</p>';
?>
-- Begin output --
$line1 = Line[start=Point(25, 25), end=Point(40, 40), length=21.2132034356]
$line2 = Line[start=Point(10, 10), end=Point(30, 0), length=22.360679775]
$line3 = Line[start=Point(-50, 65), end=Point(50, 65), length=100]
-- End output --
Each of the objects created above ($line1, $line2, $line3) are of TYPE Line, and each one can perform their own special tasks which includes; creating the start and end points, and calculating its length. The start and end points are created in the constructor when the Line is created, and the length is calculated in the __toString method when the Line is called to be displayed, although, you can call the getLength() method at any time. Having individual objects work on themselves this way is one of the really cool things about OOP, and allows you to create more complicated software.
Jason
08-Jul-2008 08:34
08-Jul-2008 08:34
For real quick and dirty one-liner anonymous objects, just cast an associative array:
<?php
$obj = (object) array('foo' => 'bar', 'property' => 'value');
echo $obj->foo; // prints 'bar'
echo $obj->property; // prints 'value'
?>
... no need to create a new class or function to accomplish it.
ranema at ubuntu dot polarhome dot com
30-Mar-2008 06:55
30-Mar-2008 06:55
Just response to osculabond at gmail dot com:
Yeah, it's better way to emulate enum by using final classes, but I think it would be the best way if we used interfaces.
ranema at ubuntu dot polarhome dot com
30-Mar-2008 06:49
30-Mar-2008 06:49
Sometimes you just forget to close handles, links, etc and sometimes you are just lazy to do that. PHP 5 OOP can do it automatically by using destructors:
<?php
class MySqlDriver {
private $_Link;
public function __construct( <...> ) {
$this->_Link = mysql_connect( <...> );
}
// this will be called automatically at the end of scope
public function __destruct() {
mysql_close( $this->_Link );
}
}
$_gLink = new MySqlDriver( <...> );
// and you don't need to close the link manually
?>
unclesam at yourshowcase dot com
25-Oct-2007 08:57
25-Oct-2007 08:57
I discovered by experimentation (when I found it to be undocumented or mentioned in a forum), that it is possible to use anonymous class names when instantiating an object.
To wit:
class Something {
public $someproperty = "somevalue";
}
...
$class = "Something";
$object = new $class;
echo "{$object->someproperty}\n";
will show:
somevalue
bearachute at gmail dot com
27-Aug-2007 06:53
27-Aug-2007 06:53
in addition to mail at touchmypixel dot com:
if methods aren't a concern, a great way to work with anonymous objects is to instantiate stdClass, which is php's base class. word up on the ECMAScript -- this works great with json!
<?php
$foo = new stdClass();
$foo->bar = 'string';
$foo->num = 10;
header('Content-type: application/json');
echo json_encode($foo);
?>
openspecies
16-Mar-2007 03:14
16-Mar-2007 03:14
class enum {
private $__this = array();
function __construct()
{
$args = func_get_args();
$i = 0;
do{
$this->__this[$args[$i]] = $i;
} while(count($args) > ++$i);
}
public function __get($n){
return $this->__this[$n];
}
};
$days = new enum(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
);
$today = $days->Thursday;
echo $today;
mail at touchmypixel dot com
15-Feb-2007 07:05
15-Feb-2007 07:05
An addition to the earlier post on creating anonymous objects.
You can make a quick anonmymous object just by using an unset variable as an object.
$foo->bar = "Hello World";
var_dump($foo->bar);
If you want to set it you can just use NULL or an empty string.
$foo = NULL;
$foo->bar = "Hello World";
var_dump($foo->bar);
This is extremely useful if you need to set a variable before using it, for example as a STATIC in a CLASS.
class MyClass {
static $foo = NULL;
}
//
MyClass::$foo->bar = "Hello World";
You can also just create a NULL object and cast it as OBJECT.
$foo = (object) NULL;
This cannot be used when creating CLASS STATICs though.
You can get some nice functionality out of this by combining some of the earlier examples into a simple function (thanks guys).
function object(){
$o = (object) NULL;
$n = func_num_args( ) ;
for ( $i = 0 ; $i < $n ; $i += 2 ) {
$o->{func_get_arg($i)} = func_get_arg($i + 1) ;
}
return($o);
}
This lets you create an anonymous object, with variables already set, which is useful for single line creation, for example sending an object through to a function.
function say($obj){
var_dump($obj->message);
}
say(object("message", "Hello World"));
Hope this helps for anyone looking how to create anonymous objects in PHP (anyone from the ECMAScript world - JavaScript or ActionScript!)
osculabond at gmail dot com
07-Oct-2006 09:20
07-Oct-2006 09:20
A better way to simulate an enum in php5:
<?php
final class Days {
const Sunday = 0x00000001;
const Monday = 0x00000010;
const Tuesday = 0x00000100;
const Wednesday = 0x00001000;
const Thursday = 0x00010000;
const Friday = 0x00100000;
const Saturday = 0x01000000;
const Unknown = 0x00000000;
// ensures that this class acts like an enum
// and that it cannot be instantiated
private function __construct(){}
}
?>
This will allow you to do things like:
<?php
$day_to_email = Days::Thursday;
if($day_to_email == Days::Wednesday) echo "Wednesday<br />";
if($day_to_email == Days::Thursday) echo "Thursday<br />";
if($day_to_email == Days::Friday) echo "Friday<br />";
?>
Which would output:
Thursday
Or if you wanted to get a little fancier you could also do the following:
<?php
$days_to_email = Days::Monday | Days::Wednesday | Days::Friday;
if($days_to_email & Days::Monday) echo "Monday<br />";
if($days_to_email & Days::Tuesday) echo "Tuesday<br />";
if($days_to_email & Days::Wednesday) echo "Wednesday<br />";
if($days_to_email & Days::Thursday) echo "Thursday<br />";
if($days_to_email & Days::Friday) echo "Friday<br />";
?>
Which would output:
Monday
Wednesday
Friday
01-May-2006 04:06
Members can be added to instances on the fly.
Simply use
$apple= new fruit();
$pear=new fruit();
$apple->color='red';
$pear->smell='sweet';
and $apple only will contain a member (field) color, but $pear only will contain a field smell.
It is not clear however whether members an be added to the class at large on the fly.
Séb.
27-May-2005 07:50
27-May-2005 07:50
We can't create easily anonymous objects like in JavaScript.
JS example :
var o = {
aProperty : "value",
anotherProperty : [ "element 1", "element 2" ] } ;
alert(o.anotherProperty[1]) ; // "element 2"
So I have created a class Object :
class Object {
function __construct( ) {
$n = func_num_args( ) ;
for ( $i = 0 ; $i < $n ; $i += 2 ) {
$this->{func_get_arg($i)} = func_get_arg($i + 1) ;
}
}
}
$o = new Object(
'aProperty', 'value',
'anotherProperty', array('element 1', 'element 2')) ;
echo $o->anotherProperty[1] ; // "element 2"
You must feel free to make it better :)
29-Mar-2005 02:21
There are 3 simple, and utterly annoying problems with your classes (not because of how you want them to work, but because how the Zend II engine handles them):
1) You cannot type hint string or int/integer in a method signature. This is incredibly annoying that the Zend II engine doesn't support it, but there are workarounds.
2) Supplying null in a method signature for a default value means that you will not accept any null value for that parameter. (therefore the method doesn't need to check if the parameters are null anyway).
3) Sadly, overriding methods is only possible with the Zend II engine via Inheritance or Polymorphism, ( and __construct() can only be defined within a class). If you want to override a method in the same class, my suggestion is to provide the method signature with a $flag = null variable, which you call a SWITCH on to pick what the data should do.
==============================================
Other than the afformentioned, the Zend II engine works very similarly to Java, which has made PHP much more versatile and robust in version 5. Thank you again Zend!
spam at afoyi dot com
21-Mar-2005 03:18
21-Mar-2005 03:18
You can call a function defined in an inherited class from the parent class. This works in both PHP 4.3.6 and 5.0.0:
<?php
class p {
function p() {
print "Parent's constructor\n";
}
function p_test() {
print "p_test()\n";
$this->c_test();
}
}
class c extends p {
function c() {
print "Child's constructor\n";
parent::p();
}
function c_test() {
print "c_test()\n";
}
}
$obj = new c;
$obj->p_test();
?>
Outputs:
Child's constructor
Parent's constructor
p_test()
c_test()
farzan at ifarzan dot com
06-Oct-2004 02:04
06-Oct-2004 02:04
PHP 5 is very very flexible in accessing member variables and member functions. These access methods maybe look unusual and unnecessary at first glance; but they are very useful sometimes; specially when you work with SimpleXML classes and objects. I have posted a similar comment in SimpleXML function reference section, but this one is more comprehensive.
I use the following class as reference for all examples:
<?
class Foo {
public $aMemberVar = 'aMemberVar Member Variable';
public $aFuncName = 'aMemberFunc';
function aMemberFunc() {
print 'Inside `aMemberFunc()`';
}
}
$foo = new Foo;
?>
You can access member variables in an object using another variable as name:
<?
$element = 'aMemberVar';
print $foo->$element; // prints "aMemberVar Member Variable"
?>
or use functions:
<?
function getVarName()
{ return 'aMemberVar'; }
print $foo->{getVarName()}; // prints "aMemberVar Member Variable"
?>
Important Note: You must surround function name with { and } or PHP would think you are calling a member function of object "foo".
you can use a constant or literal as well:
<?
define(MY_CONSTANT, 'aMemberVar');
print $foo->{MY_CONSTANT}; // Prints "aMemberVar Member Variable"
print $foo->{'aMemberVar'}; // Prints "aMemberVar Member Variable"
?>
You can use members of other objects as well:
<?
print $foo->{$otherObj->var};
print $foo->{$otherObj->func()};
?>
You can use mathods above to access member functions as well:
<?
print $foo->{'aMemberFunc'}(); // Prints "Inside `aMemberFunc()`"
print $foo->{$foo->aFuncName}(); // Prints "Inside `aMemberFunc()`"
?>
