PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Les ressources> <Les tableaux
Last updated: Fri, 10 Oct 2008

view this page in

Les objets

Initialisation des objets

Pour créer un nouvel objet, utilisez le mot clé new afin d'instancier une classe :

<?php
class foo
{
    function 
do_foo()
    {
        echo 
"Doing foo.";
    }
}

$bar = new foo;
$bar->do_foo();
?>

Pour une discussion complète, voir le chapitre sur les classes et les objets.

Conversion en un objet

Si un objet est converti en un objet, il ne sera pas modifié. Si une valeur de n'importe quel type est convertie en un objet, une nouvelle instance de la classe interne stdClass sera créée. Si la valeur est NULL, la nouvelle instance sera vide. La conversion d'un objet en tableau fera que les propriétés seront les clés, et les valeurs correspondantes aux propriétés, les valeurs de ces clés. Pour n'importe quel autre type, un membre appelé scalar contiendra la valeur.

<?php
$obj 
= (object) 'ciao';
echo 
$obj->scalar;  // Affiche : 'ciao'
?>


Les ressources> <Les tableaux
Last updated: Fri, 10 Oct 2008
 
add a note add a note User Contributed Notes
Les objets
wbcarts at juno dot com
30-Sep-2008 01:40
ON-THE-FLY!!!

In response to Bobs note below (and Rick's somewhat): It is much better to predefine the object you want to create. This is because in all the programs you write, you will still create objects On-the-Fly anyway:

$foo = 'My String Object';      // on-the-fly!
$bar = 45;                      // on-the-fly!
$obj = new stdClass();          // on-the-fly!
$obj->blah = 3;                 // on-the-fly!

So what's missing above? Real control over WHAT your program does, HOW it does it, and HOW your data is organized. Let's say your code $obj->blah = 3 was 'blah' because 3 was your last Test Score (take no offense, I've done worse!). In that case, you could use code like so:

<?php

class Test{
  const
MIN = 0, MAX = 100;     // acceptable range for a test

 
protected $person;            // person taking the test
 
protected $score;             // use the word 'score' because 'blah' is meaningless

 
public function __construct($p, $s){
   
$this->person = $p;
   
$this->score = self::clamp($s);
  }

  protected static function
clamp($val){
    if(
$val < self::MIN) $val = self::MIN;
    if(
$val > self::MAX) $val = self::MAX;
    return
$val;
  }

  public function
__toString(){
    return
"Test [person=$this->person, score=$this->score%]";
  }
}

$obj = new Test("John Doe", 83);    // on-the-fly!
echo (object)$obj;                  // outputs 'Test [person=John Doe, score=83%]'
?>

Writing your own class definitions help maintain the "integerity" of your objects - see how the clamp() function keeps test scores between 0 and 100 percent? PHP  uses similar techniques to set min and max vals on Numbers. And, classes like Test are way more useful than objects created with an empty shell, uh em, stdClass. In addition, you can see WHAT, WHERE, WHY, and HOW your program actually works... On-the-Fly!

-->
Isaac Z. Schlueter i at foohack dot com
31-Aug-2008 03:31
In response to Harmor and Mithras,  you can use the json functions to convert multi-dimensional arrays to objects very reliably.

Also, note that just using (object)$x doesn't allow you to access properties inline.  For example, this is invalid:

<?php
$x
= array("foo"=>"bar");
echo ((object)
$x)->foo; // PHP Parse error, unexpected T_OBJECT_OPERATOR
?>

However, this function will let you do that, and will also handle multi-dimensional arrays without any hassle.

<?php
function to_object ($x) {
    return (
is_object($x) || is_array($x)) ? json_decode(json_encode($x)) : (object) $x;
}

echo
to_object( array("foo"=>"bar") )->foo; // "bar"
?>

Note that *numeric* arrays will not be converted to objects using this method.
Mithras
21-Aug-2008 04:54
In response to harmor: if an array contains another array as a value, you can recursively convert all arrays with:

<?php
function arrayToObject( $array ){
  foreach(
$array as $key => $value ){
    if(
is_array( $value ) ) $array[ $key ] = arrayToObject( $value );
  }
  return (object)
$array;
}
?>
Rick
18-Apr-2008 08:35
Bob, I think you solution is to use stdClass and add properties on the fly...

$obj = new stdClass();
$obj->data ="This is the solution";
bob
10-Apr-2008 06:03
Why is there nothing in the docs about instantiating a generic object?  ie new object() - it does not work.

If one wants to create a dynamic object on the fly, the only option I see is to create it implicitly, by creating a child of it - ghetto:

unset($obj);
$obj->blah = 3;
harmor
10-Mar-2008 10:17
Environment: PHP/5.2.5

Note that multi-dimentional arrays are not converted to objects, only the first level is like this:

Input:
<?php
$arr
= array('nameOfAKey'=>array('subKeyName'=>'itsValue'));
$obj = (object)$arr;
echo
'01: '.print_r($obj->nameOfAKey, true).'<br />'//As expected
echo '02: Test: ('.var_export($obj->nameOfAKey->subKeyName,true).')'  //Not supported
?>

Output:
01: Array ( [subKeyName] => itsValue )
02: Test: (NULL)
gabe at fijiwebdesign dot com
22-May-2007 07:25
In response to sirbinam.
You cannot call a function or method before it exists. In your example, the global instance of stdout is just being passed around to differnet references (pointers). It however exists in the "dump" function scope via the global keyword.

The code below works fine and illustrates that "stdout" has been defined before its instantiation.

<?php

class profiler{
  function
profiler(){
   
$this->starttime = microtime();
  }

  function
dump(){
    global
$stdout;
   
$this->endtime = microtime();
   
$duration = $this->endtime - $this->starttime;
   
$stdout->write($duration);
  }
}

class
stdout{
  function
write($msg){
    echo
$msg;
  }
}

$stdout =& new stdout();
$profiler =& new profiler();
$profiler->dump();

?>

All classes and functions declarations within a scope exist even before the php execution reaches them. It does not matter if you have your classes defined on the first or last line, as long as they are in the same scope as where they are called and are not in a conditional statement that has not been evaluated yet.
ludvig dot ericson at gmail dot com
19-Aug-2006 01:35
In reply to the usort thing, you can access a property of an object dynamically by:
<?php
$obj
= (object)array("Test" => "bar")
$var = "Test";
echo
$obj->$var;
?>
This will output "bar", and do notice I call on ->$var and not just ->var.
Trevor Blackbird > yurab.com
27-Nov-2005 07:33
You can create a new object using the built-in stdClass or by using type-casting:

<?php

// This is the proper way
$object1 = new stdClass();

// This works too
$object2 = (object) NULL;

// This will create an object from an array
$monkey_array = array('title'=>'Spider Monkey', 'src'=>'monkey.jpg');
$monkey_object = (object) $monkey_array;
print
$monkey_object->title . ' ' . $monkey_object->src;

// You can type-cast in the middle of an expression
function customHTML($some_object) {
// this function expects an object as the argument and returns some output
}
print
'<p>Writing some output ' . customHTML( (object) array('rows'=>3, 'cols'=>4) );

?>
james dot jones at firstinvestors dot com
10-Mar-2005 07:32
iblun:

Highly recommended that you NOT try to write your own sort function. Try something like this instead:

<?php

function sort_by_field($obj_array, $field)
{
   return
usort($obj_array,
        
create_function('$o1,$o2',
             
"return (\$o1->$field < \$o2->$field) ? -1 : 1"));
}

?>

(Warning: untested code...)
iblun at gmx dot net
09-Mar-2005 03:08
To sort an array, that contains an object, after one fieldname inside the object, im using this function:

function objectSort($objectarray, $field)
{
    for ($a=0;$a < (count($objectarray)); $a++)
    {
        for ($b=0;$b < (count($objectarray)); $b++)
        {   
            if ($objectarray[$a]->$field < $objectarray[$b]->$field)
            {
                $temp = $objectarray[$a];
                $objectarray[$a] = $objectarray[$b];
                $objectarray[$b] = $temp;
            }
        }
    }
   
    return $objectarray;
}
mortoray at ecircle-ag dot com
16-Feb-2005 12:07
If you use new to create items in an array, you may not get the results you want since the parameters to array will be copies of the original and not references.

By Example:
class Store {
    var $item = 3;
}

    $a = array( new Store() );
    $b = $a;
    $a[0]->item = 2;
    print( "|" . $b[0]->item . "| <br>" );   //shows 3

    $a = array();
    $a[] =& new Store();
    $b = $a;
    $a[0]->item = 2;
    print( "|" . $b[0]->item . "| <br>" );   //shows 2

This is extremely important if you intend on passing arrays of classes to functions and expect them to always use the same object instance!

Note: The following syntax is desired (or maybe even the default notation should translate as this):
   $a = array( &new Store() );
sirbinam at nospam dot please dot hotmail dot com
16-Nov-2004 04:46
<?php

class hack{}
$hack =& new hack;

class
profiler{
  function
profiler(){
   
$this->startime = microtime();
  }

  function
dump(){
    global
$hack;
   
$this->endtime = microtime();
   
$duration = $this->endtime - $this->starttime; /* this won't actually work, it just the concept */
   
$stdout->write($duration);
  }
}

class
stdout{
  function
write($msg){
    echo
$msg;
  }
}

$stdout =& new stdout();
$hack =& $stdout;
$profiler->dump();

?>

/*
     *
     * In short this little hack allows us to call $stdout->write() from
     * $profiler->dump
     *
     * The problem is that $stdout doesn't exist yet and when the compiler
     * parses this class, it sends a fatal error and dies because you can't
     * refer to a method of an object that doesn't exist yet, even though
     * this method doesn't get called until the end of execution, when the
     * method does exist.
     * This is the same as not being able to use a function before it is
     * at least declared in say a header file. This is seen in C, Perl,
     * and pretty much every language known to man. (TTBOMK?)
     *
     * So what does this hack do?
     * The first thing that happens in the global scope is an empty class
     * definition, it then creates a object called $hack from this class.
     * All this does is allocate memory for an object, and places a pointer
     * at the begining of that memory segment.
     * When the compiler parses this class, it doesn't care that the $hack
     * object is empty, as long as it has somewhere to assign a function
     * pointer. Later in global scope the $stdout object is created.
     * After $stdout is created, we do $hack =& $stdout. The =&
     * (assign by reference) moves the pointer for $hack to the begining of
     * the memory segment for $stdout. So when we call $hack->write(), it
     * points to the exact same object->method() as $stdout->write(). So
     * this is actually very reliable, just don't tell a purist!
     */
jbinam at nospam dot please dot hotmail dot com
16-Nov-2004 04:46
<?php

class hack{}
$hack =& new hack;

class
profiler{
  function
profiler(){
   
$this->startime = microtime();
  }

  function
dump(){
    global
$hack;
   
$this->endtime = microtime();
   
$duration = $this->endtime - $this->starttime; /* this won't actually work, it just the concept */
   
$stdout->write($duration);
  }
}

class
stdout{
  function
write($msg){
    echo
$msg;
  }
}

$stdout =& new stdout();
$hack =& $stdout;
$profiler->dump();

?>

/*
     *
     * In short this little hack allows us to call $stdout->write() from
     * $profiler->dump
     *
     * The problem is that $stdout doesn't exist yet and when the compiler
     * parses this class, it sends a fatal error and dies because you can't
     * refer to a method of an object that doesn't exist yet, even though
     * this method doesn't get called until the end of execution, when the
     * method does exist.
     * This is the same as not being able to use a function before it is
     * at least declared in say a header file. This is seen in C, Perl,
     * and pretty much every language known to man. (TTBOMK?)
     *
     * So what does this hack do?
     * The first thing that happens in the global scope is an empty class
     * definition, it then creates a object called $hack from this class.
     * All this does is allocate memory for an object, and places a pointer
     * at the begining of that memory segment.
     * When the compiler parses this class, it doesn't care that the $hack
     * object is empty, as long as it has somewhere to assign a function
     * pointer. Later in global scope the $stdout object is created.
     * After $stdout is created, we do $hack =& $stdout. The =&
     * (assign by reference) moves the pointer for $hack to the begining of
     * the memory segment for $stdout. So when we call $hack->write(), it
     * points to the exact same object->method() as $stdout->write(). So
     * this is actually very reliable, just don't tell a purist!
     */
nconantj
18-Jul-2004 10:43
php at electricsurfer.com,

More than a year later and here's some clarification of what's happening in your code, via comments in an otherwise verbatim copy.

<?
class c
{
   var
$a = array('a'=>'aa','b'=>'ab');
   var
$b = 'c';
 
   function
show()
   {
       echo
$this->a['a']; // -> 1st
      
echo $this->a['b']; // outputs 'ab'
     
      
$a = 'a';
      
$b = 'b';
     
       echo
$this->$a[$a]; // [] 1st, not what I expected
       //Above first becomes $this->$a['a'] by looking at the function's local $a
       //Next it becomes $this->a by again looking at the function's local $a, which references the class variable $a with no subscripts.
       // In order to reference elements of the class variable $a,
       // you want to use $this->a[$a]

      
echo $this->$a[$b]; // does NOT output 'ab'
       // Same as above, but the first step $b becomes 'b'

      
$this_a =& $this->$a; // work-around
     
      
echo $this_a[$a]; // no question
      
echo $this_a[$b];
     
      
$a_arr = array('a'=>'b');
     
       echo
$this->$a_arr[$a]; // [] 1st => outputs 'c'
       // This becomes $this->$a_arr['a'] which becomes $this->c,
       // by referencing the local variables first.
  
}
}
$c = new c();
$c->show();
?>
info at keltoi-web dot com
26-Aug-2003 12:26
PHP supports recursive type definitions as far as I've tried. The class below (a _very_ simple tree) is an example:

class Tree {

var $_value = null;
var $_children = array();

function Tree ($value) {
  $this->_value = $value;
}

function addChild ($value) {
  $aux_node = new Tree ($value);
  $this->_children [] = $aux_node;
  return $aux_node;
}
}

As you can see, in addChild we reference Tree again...

However, you must be careful about references. See the chapter "References explained" for more details.

Hope this helps.
php at electricsurfer dot com
22-May-2003 07:25
Here's an example on operator precedence between ->  and []
& what happens with $object->$member[$array_element]

<?
class c
{
    var
$a = array('a'=>'aa','b'=>'ab');
    var
$b = 'c';
   
    function
show()
    {
        echo
$this->a['a']; // -> 1st
       
echo $this->a['b']; // outputs 'ab'
       
       
$a = 'a';
       
$b = 'b';
       
        echo
$this->$a[$a]; // [] 1st, not what I expected
       
echo $this->$a[$b]; // does NOT output 'ab'
       
       
$this_a =& $this->$a; // work-around
       
       
echo $this_a[$a]; // no question
       
echo $this_a[$b];
       
       
$a_arr = array('a'=>'b');
       
        echo
$this->$a_arr[$a]; // [] 1st => outputs 'c'
   
}
}
$c = new c();
$c->show();
?>

Les ressources> <Les tableaux
Last updated: Fri, 10 Oct 2008
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites