PHP Class TERMINOLOGY
If you find that your code lacks structure, organization, and/or is hard to maintain... PHP Classes may be what you need. But first, some terminology -- terms are in UPPERCASE:
<?php
class MyClass
{
// This is the CLASS DEFINITION (everything in the curly brackets).
// $myVar is DECLARED, but it is not INITIALIZED (assigned a value).
protected $myVar;
public function __construct($value = 'What?')
{
$this->setMyVar($value); // $myVar will now be INITIALIZED
}
public function setMyVar($value)
{
if(!is_string($value))
{
$value = (string)'Non-String type passed in argument';
}
$this->myVar = $value;
}
}
?>
The class definition is like a blueprint. Imagine an architect who goes to the job site carrying a big roll of papers with drawings on them. Those drawings represent a design which is meant 'to be built', and they are used throughout the entire construction process. Once the project is done, then people occupy the buliding and commense their work. One crucial difference between a CLASS DEFINITION and a blueprint though is, that a class definition does say what does and what doesn't go on with the project after it is designed and built.
We have a CLASS DEFINITON at this stage -- PHP is happy -- but it does nothing for us yet. We need to INSTANTIATE (make real MyClass object(s)) and have those INSTANCE(S) follow the design and rules outlined in the CLASS DEFINITION.
<?php
// INSTANTIATE (to build or create) objects with the 'new' operator.
$mc1 = new MyClass(); // $mc1 is now an INSTANCE (built or created, materialized).
$mc2 = new MyClass('Hello World'); // $mc2 is now an INSTANCE (built or created, materialized).
$mc3 = new MyClass('Take that!'); // $mc3 is now an INSTANCE (built or created, materialized).
$mc4 = new MyClass(true); // $mc4 is now an INSTANCE (built or created, materialized).
?>
Now it is time to put the INSTANCES to work. According to our CLASS DEFINITION, all we can do is set the value of $myVar with the setMyVar() function.
<?php
$mc1->setMyVar(''); // Ok
$mc2->setMyVar(''); // Ok
$mc3->setMyVar(''); // Ok
$mc4->setMyVar(''); // Ok
?>
Try putting a non INSTANCE to work:
<?php
$youTrickyLittleBitch->setMyVar('You like that?');
?>
That throws: 'Fatal error: Call to a member function setMyVar() on a non-object'. This means that the variable was not INSTANTIATED with the proper CLASS DEFINITON, therefore it is not an INSTANCE of that class, therefore illegal to even try.
Les classes et les objets
Sommaire
- Introduction
- Syntaxe de base
- Propriétés
- Constantes de classe
- Auto-chargement de classes
- Constructeurs et destructeurs
- Visibilité
- Héritage
- L'opérateur de résolution de portée (::)
- Statique
- Abstraction de classes
- Interfaces
- Traits
- Surcharge magique
- Parcours d'objets
- Méthodes magiques
- Mot-clé "final"
- Clônage d'objets
- Comparaison d'objets
- Typage objet
- Late Static Bindings (Résolution statique à la volée)
- Objets et références
- Sérialisation d'objets
- Modifications en POO (Programmation orientée objet)
wbcarts at juno dot com
22-May-2012 05:00
dances_with_peons at live dot com
18-Jan-2011 02:36
As of PHP 5.3, $className::funcName() works fine.
<?php
class test
{
public static function run() { print "Works\n"; }
}
$className = 'test';
$className::run();
?>
on my system, prints "Works". May work with earlier versions of PHP as well. Even if it doesn't, there's always
<?php
$className = 'test';
call_user_func(array($className, 'run'));
?>
The point is, there's no need for eval.
dances_with_peons at live dot com
18-Jan-2011 02:30
As of PHP 5.3, $className::funcName() works fine.
<?php
class test
{
public static function run() { print "Works\n"; }
}
$className = 'test';
$className::run();
?>
on my system, prints "Works". It may work with earlier versions of PHP as well.
corpus-deus at softhome dot net
26-Nov-2010 08:27
With regards to Singleton patterns (and variable class names) - try:
<?php
class MyClass {
// singleton instance
private static $instance;
// private constructor function
// to prevent external instantiation
private __construct() { }
// getInstance method
public static function getInstance() {
if(!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
//...
}
?>
suleman dot saleh at gmail dot com
25-Oct-2010 11:41
Using php abstract classes we must have to implement all their functions in child classes other wise it will make automatically child class as a concrete
DavMe
01-Oct-2010 12:03
When you have a class name in a variable and want to create a new instance of that class, you can simply use:
<?php
$className = "ClassName";
$instance = new $className();
?>
If, however, you have a class that is part of a singleton pattern where you cannot create it with new and need to use:
<?php
$instance = ClassName::GetInstance();
?>
...you quickly discover that it fails miserably with a variable.
Fail Example:
<?php
$className = "ClassName";
$instance = $className::GetInstance();
?>
After a few days of head pounding, I finally put together this workaround:
<?php
$className = "ClassName";
eval('$instance = '.$className.'::GetInstance();');
?>
I hope this saves you some effort and if anyone knows of a non-eval method to accomplish this, please share!
Thanks!
midir
02-Mar-2009 07:40
There are a couple of tricks you can do with PHP's classes that programmers from C++, etc., will find very peculiar, but which can be useful.
You can create instances of classes without knowing the class name in advance, when it's in a variable:
<?php
$type = 'cc';
$obj = new $type; // outputs "hi!"
class cc {
function __construct() {
echo 'hi!';
}
}
?>
You can also conditionally define them by wrapping them in if/else blocks etc, like so:
<?php
if (expr) {
class cc {
// version 1
}
} else {
class cc {
// version 2
}
}
?>
It makes up for PHP's lack of preprocessor directives. The caveat is that the if/else code body must have been executed before you can use the class, so you need to pay attention to the order of the code, and not use things before they're defined.
redrik at gmail dot com
31-Dec-2008 01:08
Maybe someone will find these classes, which simulate enumeration, useful.
<?php
class Enum {
protected $self = array();
public function __construct( /*...*/ ) {
$args = func_get_args();
for( $i=0, $n=count($args); $i<$n; $i++ )
$this->add($args[$i]);
}
public function __get( /*string*/ $name = null ) {
return $this->self[$name];
}
public function add( /*string*/ $name = null, /*int*/ $enum = null ) {
if( isset($enum) )
$this->self[$name] = $enum;
else
$this->self[$name] = end($this->self) + 1;
}
}
class DefinedEnum extends Enum {
public function __construct( /*array*/ $itms ) {
foreach( $itms as $name => $enum )
$this->add($name, $enum);
}
}
class FlagsEnum extends Enum {
public function __construct( /*...*/ ) {
$args = func_get_args();
for( $i=0, $n=count($args), $f=0x1; $i<$n; $i++, $f *= 0x2 )
$this->add($args[$i], $f);
}
}
?>
Example usage:
<?php
$eFruits = new Enum("APPLE", "ORANGE", "PEACH");
echo $eFruits->APPLE . ",";
echo $eFruits->ORANGE . ",";
echo $eFruits->PEACH . "\n";
$eBeers = new DefinedEnum("GUINESS" => 25, "MIRROR_POND" => 49);
echo $eBeers->GUINESS . ",";
echo $eBeers->MIRROR_POND . "\n";
$eFlags = new FlagsEnum("HAS_ADMIN", "HAS_SUPER", "HAS_POWER", "HAS_GUEST");
echo $eFlags->HAS_ADMIN . ",";
echo $eFlags->HAS_SUPER . ",";
echo $eFlags->HAS_POWER . ",";
echo $eFlags->HAS_GUEST . "\n";
?>
Will output:
1, 2, 3
25, 49
1,2,4,8 (or 1, 10, 100, 1000 in binary)
Jeffrey
08-Oct-2008 11:51
Why should anyone learn what classes and objects are? The short answer is to clarify and simplify code. Take this regular script:
<?php
$item_name = 'Widget 22';
$item_price = 4.90;
$item_qty = 2;
$item_total = ($item_price * $item_qty);
echo "You ordered $item_qty $item_name @ \$$item_price for a total of: \$$item_total.";
?>
You ordered 2 Widget 22 @ $4.9 for a total of: $9.8.
You can see clearly that you have to "define and set" the data, "perform a calculation", and explicitly "write" the results - for a total of 5 written statements. But the more you look at it, the more it needs fixin'. If you attempt to do that, your code can get really ugly, really fast - and remember, this is just a simple script! Here's the same program in OOP with all the fixin's:
<?php
class Item {
protected $name, $price, $qty, $total;
public function __construct($iName, $iPrice, $iQty) {
$this->name = $iName;
$this->price = $iPrice;
$this->qty = $iQty;
$this->calculate();
}
protected function calculate() {
$this->price = number_format($this->price, 2);
$this->total = number_format(($this->price * $this->qty), 2);
}
public function __toString() {
return "You ordered ($this->qty) '$this->name'" . ($this->qty == 1 ? "" : "s") .
" at \$$this->price, for a total of: \$$this->total.";
}
}
echo (new Item("Widget 22", 4.90, 2));
?>
You ordered (2) 'Widget 22's at $4.90, for a total of: $9.80.
By loading class Item (which houses all the improvements we made over the first script) into PHP first, we went from having to write 5 statements in the first script, to writing only 1 statement "echo new Item" in the second.
Jason
07-Jul-2008 10: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 07: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
?>
osculabond at gmail dot com
06-Oct-2006 11: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
S�b.
27-May-2005 09: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 :
<?php
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 :)
spam at afoyi dot com
20-Mar-2005 05: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
05-Oct-2004 04: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:
<?php
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:
<?php
$element = 'aMemberVar';
print $foo->$element; // prints "aMemberVar Member Variable"
?>
or use functions:
<?php
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:
<?php
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:
<?php
print $foo->{$otherObj->var};
print $foo->{$otherObj->func()};
?>
You can use mathods above to access member functions as well:
<?php
print $foo->{'aMemberFunc'}(); // Prints "Inside `aMemberFunc()`"
print $foo->{$foo->aFuncName}(); // Prints "Inside `aMemberFunc()`"
?>
