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

search for in the

Überladung> <Interfaces
[edit] Last updated: Fri, 17 May 2013

view this page in

Traits

Seit PHP 5.4.0 gibt es in PHP eine Methode der Wiederverwendung von Code, die Traits genannt wird.

Traits ist ein Mechanismus zur Wiederverwendung von Code, der in Programmiersprachen mit einfacher Vererbung wie PHP verwendet wird. Ein Trait kann verwendet werden die Beschränkungen der einfachen Vererbung aufzuweichen indem er erlaubt, dass Mengen von Methoden frei in mehreren unabhängigen Klassen die in verschiedenen Klassenhierarchien stecken wiederzuverwenden. Die Semantik der Kombination von Traits und Klassen ist so definiert, dass die Komplexität reduziert wird und die üblichen Probleme vermeidet, die mit Mehrfachvererbung und Mixins in Verbindung gebracht werden.

Ein Trait hat Ähnlichkeit mit einer Klasse ist aber nur dafür vorgesehen Funktionalität in einer feingranularen und konsistenten Art und Weise zu bündeln. Es ist nicht möglich einen Trait alleinstehend zu instantiieren. Es handelt sich um einen Zusatz zur traditionellen Vererbung und erlaubt horizontale Komposition von Verhaltensweisen, d.h. die Verwendung von Klassenmethoden ohne Vererbung vorauszusetzen.

Beispiel #1 Trait Beispiel

<?php
trait ezcReflectionReturnInfo 
{
    function 
getReturnType() { /*1*/ }
    function 
getReturnDescription() { /*2*/ }
}

class 
ezcReflectionMethod extends ReflectionMethod {
    use 
ezcReflectionReturnInfo;
    
/* ... */
}

class 
ezcReflectionFunction extends ReflectionFunction {
    use 
ezcReflectionReturnInfo;
    
/* ... */
}
?>

Rangfolge

Methoden der aktuellen Klasse überschreiben Methoden, welche von Traits definiert wurden. Jene wiederum überschreiben von Elternklassen geerbte Methoden.

Beispiel #2 Rangfolge Beispiel

Die Methode sayHello der Basisklasse wird durch die gleichnamige Methode aus dem Trait überschrieben.

<?php
class Base {
    public function 
sayHello() {
        echo 
'Hallo ';
    }
}

trait SayWorld {
    public function 
sayHello() {
        
parent::sayHello();
        echo 
'Welt!';
    }
}

class 
MyHelloWorld extends Base {
    use 
SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Hallo Welt!

Beispiel #3 Weiteres Beispiel für Rangfolge

<?php
trait HelloWorld 
{
    public function 
sayHello() {
        echo 
'Hallo Welt!';
    }
}

class 
TheWorldIsNotEnough {
    use 
HelloWorld;
    public function 
sayHello() {
        echo 
'Hallo Universum!';
    }
}

$o = new TheWorldIsNotEnough();
$o->sayHello();
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Hallo Universum!

Mehrere Traits

Mehrere Traits können durch eine kommaseparierte Auflistung im Use- Statement zu einer Klasse hinzugefügt werden.

Beispiel #4 Verwendung mehrerer Traits

<?php
trait Hello 
{
    public function 
sayHello() {
        echo 
'Hallo ';
    }
}

trait World {
    public function 
sayWorld() {
        echo 
' Welt';
    }
}

class 
MyHelloWorld {
    use 
HelloWorld;
    public function 
sayExclamationMark() {
        echo 
'!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Hallo Welt!

Konfliktauflösung

Falls zwei Traits eine Methode mit gleichem namen einfügen, so wird ein Fatal Error erzeugt, wenn der Konflikt nicht explizit aufgelöst wird.

Um einen Namenskonflikt zwischen Traits in der gleichen Klasse aufzulösen muss der insteadof-Operator verwendet werden, um genau eine der Methoden des Konflikts auszuwählen.

Da dies es nur erlaubt Methoden auszuschließen kann der as-Operator verwendet werden, um eine der Methoden des Konflikts wieder unter einem anderen Namen hinzuzufügen.

Beispiel #5 Konfliktauflösung

In diesem Beispiel verwendet die Klasse Talker die Traits A und B. Nachdem A und B sich widersprechende Methoden besitzen definiert die Klasse, dass sie die Variante von smallTalk aus dem Trait B und die Variante von bigTalk des Traits A verwenden möchte.

Die Klasse Aliased_Talker verwendet den as-Operator, damit sie außerdem die Implementierung der bigTalk-Methode von B unter dem Alias talk verwenden kann.

<?php
trait A 
{
    public function 
smallTalk() {
        echo 
'a';
    }
    public function 
bigTalk() {
        echo 
'A';
    }
}

trait B {
    public function 
smallTalk() {
        echo 
'b';
    }
    public function 
bigTalk() {
        echo 
'B';
    }
}

class 
Talker {
    use 
A{
        
B::smallTalk insteadof A;
        
A::bigTalk insteadof B;
    }
}

class 
Aliased_Talker {
    use 
A{
        
B::smallTalk insteadof A;
        
A::bigTalk insteadof B;
        
B::bigTalk as talk;
    }
}
?>

Veränderung der Sichtbarkeit von Methoden

Mit der as-Syntax ist es ebenso möglich, die Sichtbarkeit einer Methode in der darstellenden Klasse zu verändern.

Beispiel #6 Veränderung der Sichtbarkeit von Methoden

<?php
trait HelloWorld 
{
    public function 
sayHello() {
        echo 
'Hallo Welt!';
    }
}

// Ändern der Sichtbarkeit von sayHello
class MyClass1 {
    use 
HelloWorld sayHello as protected }
}

// Alias der Methode mit geänderter Sichtbarkeit
// Die Sichtbarkeit von sayHello bleibt unverändert
class MyClass2 {
    use 
HelloWorld doHelloWorld as private sayHello }
}
?>

Trait-Zusammensetzung aus Traits

Ebenso wie Klassen können auch traits andere Traits verwenden. Indem man einen oder mehrere Traits in einer Traitdefinition verwendet kann man Traits entweder teilweise oder vollständig aus Methoden, welche in anderen Traits definiert sind, zusammensetzen.

Beispiel #7 Trait-Zusammensetzung aus Traits

<?php
trait Hello 
{
    public function 
sayHello() {
        echo 
'Hallo ';
    }
}

trait World {
    public function 
sayWorld() {
        echo 
'Welt!';
    }
}

trait HelloWorld {
    use 
HelloWorld;
}

class 
MyHelloWorld {
    use 
HelloWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Hallo Welt!

Abstrakte Traitmember

Traits unterstützen auch die Verwendung von abstrakten Methoden, um darstellenden Klassen Anforderungen aufzudrängen.

Beispiel #8 Ausdrücken von Anforderungen durch abstrakte Methoden

<?php
trait Hello 
{
    public function 
sayHelloWorld() {
       echo 
'Hallo'.$this->getWorld();
    }
    abstract public function 
getWorld();
}

class 
MyHelloWorld {
    private 
$world;
    use 
Hello;
    public function 
getWorld() {
        return 
$this->world;
    }
    public function 
setWorld($val) {
        
$this->world $val;
    }
}
?>

Statische Traitmember

Innerhalb von Traits kann auf statische Variablen zugegriffen werden, aber diese können nicht in Traits definiert werden. Statische Methoden können hingegen auch durch Traits für die darstellende Klasse definiert werden.

Beispiel #9 Statische Variablen

<?php
trait Counter 
{
    public function 
inc() {
        static 
$c 0;
        
$c $c 1;
        echo 
"$c\n";
    }
}

class 
C1 {
    use 
Counter;
}

class 
C2 {
    use 
Counter;
}

$o = new C1(); $o->inc(); // echo 1
$p = new C2(); $p->inc(); // echo 1
?>

Beispiel #10 Statische Methoden

<?php
trait StaticExample 
{
    public static function 
doSomething() {
        return 
'Tue etwas';
    }
}

class 
Example {
    use 
StaticExample;
}

Example::doSomething();
?>

Attribute

Traits können ebenfalls Attribute definieren.

Beispiel #11 Attribute definieren

<?php
trait PropertiesTrait 
{
    public 
$x 1;
}

class 
PropertiesExample {
    use 
PropertiesTrait;
}

$example = new PropertiesExample;
$example->x;
?>

Ein Attribut, welches durch einen Trait definiert wurde, kann nicht von der Klasse erneut definiert werden. Wenn die Attribute kompatibel sind, d.h. die selbe Sichtbarkeit und den selben Standardwert besitzen, wird ein E_STRICT Fehler geworfen. Anderfalls wird ein Fatal Error geworfen.

Beispiel #12 Konfliktauflösung

<?php
trait PropertiesTrait 
{
    public 
$same true;
    public 
$different false;
}

class 
PropertiesExample {
    use 
PropertiesTrait;
    public 
$same true// Strict Standards
    
public $different true// Fatal error
}
?>


Überladung> <Interfaces
[edit] Last updated: Fri, 17 May 2013
 
add a note add a note User Contributed Notes Traits - [19 notes]
up
25
Safak Ozpinar / safakozpinar at gmail
1 year ago
Unlike inheritance; if a trait has static properties, each class using that trait has independent instances of those properties.

Example using parent class:
<?php
class TestClass {
    public static
$_bar;
}
class
Foo1 extends TestClass { }
class
Foo2 extends TestClass { }
Foo1::$_bar = 'Hello';
Foo2::$_bar = 'World';
echo
Foo1::$_bar . ' ' . Foo2::$_bar; // Prints: World World
?>

Example using trait:
<?php
trait TestTrait {
    public static
$_bar;
}
class
Foo1 {
    use
TestTrait;
}
class
Foo2 {
    use
TestTrait;
}
Foo1::$_bar = 'Hello';
Foo2::$_bar = 'World';
echo
Foo1::$_bar . ' ' . Foo2::$_bar; // Prints: Hello World
?>
up
5
t8 at AT pobox dot com
10 months ago
Another difference with traits vs inheritance is that methods defined in traits can access methods and properties of the class they're used in, including private ones.

For example:
<?php
trait MyTrait
{
  protected function
accessVar()
  {
    return
$this->var;
  }

}

class
TraitUser
{
  use
MyTrait;

  private
$var = 'var';

  public function
getVar()
  {
    return
$this->accessVar();
  }
}

$t = new TraitUser();
echo
$t->getVar(); // -> 'var'                                                                                                                                                                                                                         

?>
up
1
ryanhanekamp at yahoo dot com
1 year ago
Using AS on a __construct method (and maybe other magic methods) is really, really bad. The problem is that is doesn't throw any errors, at least in 5.4.0. It just sporadically resets the connection. And when I say "sporadically," I mean that arbitrary changes in the preceding code can cause the browser connection to reset or not reset *consistently*, so that subsequent page refreshes will continue to hang, crash, or display perfectly in the same fashion as the first load of the page after a change in the preceding code, but the slightest change in the code can change this state. (I believe it is related to precise memory usage.)

I've spent a good part of the day chasing down this one, and weeping every time commenting or even moving a completely arbitrary section of code would cause the connection to reset. It was just by luck that I decided to comment the

"__construct as primitiveObjectConstruct"

line and then the crashes went away entirely.

My parent trait constructor was very simple, so my fix this time was to copy the functionality into the child __construct. I'm not sure how I'll approach a more complicated parent trait constructor.
up
11
chris dot rutledge at gmail dot com
1 year ago
It may be worth noting here that the magic constant __CLASS__ becomes even more magical - __CLASS__ will return the name of the class in which the trait is being used.

for example

<?php
trait sayWhere {
    public function
whereAmI() {
        echo
__CLASS__;
    }
}

class
Hello {
    use
sayWHere;
}

class
World {
    use
sayWHere;
}

$a = new Hello;
$a->whereAmI(); //Hello

$b = new World;
$b->whereAmI(); //World
?>

The magic constant __TRAIT__ will giev you the name of the trait
up
9
greywire at gmail dot com
1 year ago
The best way to understand what traits are and how to use them is to look at them for what they essentially are:  language assisted copy and paste.

If you can copy and paste the code from one class to another (and we've all done this, even though we try not to because its code duplication) then you have a candidate for a trait.
up
15
ryan at derokorian dot com
1 year ago
Simple singleton trait.

<?php

trait singleton {   
   
/**
     * private construct, generally defined by using class
     */
    //private function __construct() {}
   
   
public static function getInstance() {
        static
$_instance = NULL;
       
$class = __CLASS__;
        return
$_instance ?: $_instance = new $class;
    }
   
    public function
__clone() {
       
trigger_error('Cloning '.__CLASS__.' is not allowed.',E_USER_ERROR);
    }
   
    public function
__wakeup() {
       
trigger_error('Unserializing '.__CLASS__.' is not allowed.',E_USER_ERROR);
    }
}

/**
 * Example Usage
 */

class foo {
    use
singleton;
   
    private function
__construct() {
       
$this->name = 'foo';
    }
}

class
bar {
    use
singleton;
   
    private function
__construct() {
       
$this->name = 'bar';
    }
}

$foo = foo::getInstance();
echo
$foo->name;

$bar = bar::getInstance();
echo
$bar->name;
up
4
Jason dot Hofer dot deletify dot this dot part at gmail dot com
1 year ago
A (somewhat) practical example of trait usage.

Without traits:

<?php

class Controller {
 
/* Controller-specific methods defined here. */
}

class
AdminController extends Controller {
 
/* Controller-specific methods inherited from Controller. */
  /* Admin-specific methods defined here. */
}

class
CrudController extends Controller {
 
/* Controller-specific methods inherited from Controller. */
  /* CRUD-specific methods defined here. */
}

class
AdminCrudController extends CrudController {
 
/* Controller-specific methods inherited from Controller. */
  /* CRUD-specific methods inherited from CrudController. */
  /* (!!!) Admin-specific methods copied and pasted from AdminController. */
}

?>

With traits:

<?php

class Controller {
 
/* Controller-specific methods defined here. */
}

class
AdminController extends Controller {
 
/* Controller-specific methods inherited from Controller. */
  /* Admin-specific methods defined here. */
}

trait
CrudControllerTrait {
 
/* CRUD-specific methods defined here. */
}

class
AdminCrudController extends AdminController {
  use
CrudControllerTrait;
 
/* Controller-specific methods inherited from Controller. */
  /* Admin-specific methods inherited from AdminController. */
  /* CRUD-specific methods defined by CrudControllerTrait. */
}

?>
up
2
karolis at iwsolutions dot ie
11 months ago
Not very obvious but trait methods can be called as if they were defined as static methods in a regular class

<?php
trait Foo {
    function
bar() {
        return
'baz';
    }
}

echo
Foo::bar(),"\\n";
?>
up
2
anthony bishopric
1 year ago
The magic method __call works as expected using traits.

<?php
trait Call_Helper{
   
    public function
__call($name, $args){
        return
count($args);
    }
}

class
Foo{
    use
Call_Helper;
}

$foo = new Foo();
echo
$foo->go(1,2,3,4); // echoes 4
up
2
D. Marti
7 months ago
Traits are useful for strategies, when you want the same data to be handled (filtered, sorted, etc) differently.

For example, you have a list of products that you want to filter out based on some criteria (brands, specs, whatever), or sorted by different means (price, label, whatever). You can create a sorting trait that contains different functions for different sorting types (numeric, string, date, etc). You can then use this trait not only in your product class (as given in the example), but also in other classes that need similar strategies (to apply a numeric sort to some data, etc).

<?php
trait SortStrategy {
    private
$sort_field = null;
    private function
string_asc($item1, $item2) {
        return
strnatcmp($item1[$this->sort_field], $item2[$this->sort_field]);
    }
    private function
string_desc($item1, $item2) {
        return
strnatcmp($item2[$this->sort_field], $item1[$this->sort_field]);
    }
    private function
num_asc($item1, $item2) {
        if (
$item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
        return (
$item1[$this->sort_field] < $item2[$this->sort_field] ? -1 : 1 );
    }
    private function
num_desc($item1, $item2) {
        if (
$item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
        return (
$item1[$this->sort_field] > $item2[$this->sort_field] ? -1 : 1 );
    }
    private function
date_asc($item1, $item2) {
       
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
       
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
        if (
$date1 == $date2) return 0;
        return (
$date1 < $date2 ? -1 : 1 );
    }
    private function
date_desc($item1, $item2) {
       
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
       
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
        if (
$date1 == $date2) return 0;
        return (
$date1 > $date2 ? -1 : 1 );
    }
}

class
Product {
    public
$data = array();
   
    use
SortStrategy;
   
    public function
get() {
       
// do something to get the data, for this ex. I just included an array
       
$this->data = array(
           
101222 => array('label' => 'Awesome product', 'price' => 10.50, 'date_added' => '2012-02-01'),
           
101232 => array('label' => 'Not so awesome product', 'price' => 5.20, 'date_added' => '2012-03-20'),
           
101241 => array('label' => 'Pretty neat product', 'price' => 9.65, 'date_added' => '2012-04-15'),
           
101256 => array('label' => 'Freakishly cool product', 'price' => 12.55, 'date_added' => '2012-01-11'),
           
101219 => array('label' => 'Meh product', 'price' => 3.69, 'date_added' => '2012-06-11'),
        );
    }
   
    public function
sort_by($by = 'price', $type = 'asc') {
        if (!
preg_match('/^(asc|desc)$/', $type)) $type = 'asc';
        switch (
$by) {
            case
'name':
               
$this->sort_field = 'label';
               
uasort($this->data, array('Product', 'string_'.$type));
            break;
            case
'date':
               
$this->sort_field = 'date_added';
               
uasort($this->data, array('Product', 'date_'.$type));
            break;
            default:
               
$this->sort_field = 'price';
               
uasort($this->data, array('Product', 'num_'.$type));
        }
    }
}

$product = new Product();
$product->get();
$product->sort_by('name');
echo
'<pre>'.print_r($product->data, true).'</pre>';
?>
up
1
Serafim
4 months ago
Another useful property of traits:
<?php
namespace Traits;
trait
Properties{
    public function
__get($var){
       
$var = '_' . $var;
       
$getter = '_get' . $var;
       
        if(
method_exists($this, $getter)){
            try{
               
$val = $this->$getter();
            }catch(\
Exception $e){
                throw new \
Exception($e);
            }
            return
$val;
        }
        throw new \
Exception('Can not get property: ' . $var . ', method ' . $getter . ' not exists');
    }
   
    public function
__set($var, $val){
       
$var = '_' . $var;
       
$setter = '_set' . $var;
       
        if(
method_exists($this->$setter) && isset($this->$var)){
            try{
               
$setval = $this->$setter($val);
            }catch(\
Exception $e){
                throw new \
Exception($e);
            }
           
$this->$var = ($setval === NULL) ? $this->$var : $setval;
        }else{
            throw new \
Exception('Can not set property: ' . $var . ', method ' . $setter . ' not exists');
        }
    }
}

class
Some{
  use \
Chidori\Traits\Properties;
 
 
// Magic begin
 
protected $_var = 42;
  protected function
_get_var(){ return $this->_var; }
  protected function
_set_var($val){ return NULL; }
}
 
$s = new Some();
$s->var = 23; \\ set value
echo $s->var; \\ return 42? where is my 23? =)
?>
up
1
Edward
1 year ago
The difference between Traits and multiple inheritance is in the inheritance part.   A trait is not inherited from, but rather included or mixed-in, thus becoming part of "this class".   Traits also provide a more controlled means of resolving conflicts that inevitably arise when using multiple inheritance in the few languages that support them (C++).  Most modern languages are going the approach of a "traits" or "mixin" style system as opposed to multiple-inheritance, largely due to the ability to control ambiguities if a method is declared in multiple "mixed-in" classes.

Also, one can not "inherit" static member functions in multiple-inheritance.
up
1
Anonymous
1 year ago
Traits can not implement interfaces.
(should be obvious, but tested is tested)
up
-2
artur at webprojektant dot pl
8 months ago
Trait can not have the same name as class because it will  show: Fatal error: Cannot redeclare class
up
-3
dario dot masamune at gmail dot com
10 months ago
Just in case someone was wondering, traits can be inside namespaces too! Cool!!
up
-1
Oddant
20 days ago
I think it's obvious to notice that using 'use' followed by the traits name must be seen as just copying/pasting lines of code into the place where they are used.
up
-1
syzer3 at gmail dot com
1 month ago
Traits can be useful to create Fluent API
ex:
trait StaticMake
{
    public static function make()
    {
        return new static();
    }
}
class HelloWorld
{
 use StaticMake;

   public function getHello()
   {
      return "Hello World";
   }
}
//now instead:
$theHello = new HelloWorld;
echo $theHello -> getHello();

//one may just use
echo HelloWorld:make() -> getHello();
up
-1
jan
3 months ago
Hi! Just a quick solution to use class-identical static property. I use it to store SQL descriptions, which is always same for the same class, but may change for an extended class.

<?php
interface hasO{            // just for forcing basic functionalities
   
static function O($use_as);
    function
myObj($append = "nothing");
    function
inc();
    static function
getName();
}
class
O{            // the target class to access
   
var $val, $num = 0;
    function
setVAl($val){$this->val = $val;}
    function
inc(){$this->num++;}
    function
prt($append){echo "hello, i'm {$this->val} with number: {$this->num} and append a string: {$append}<br>"; }
}
trait
T{            // the trait to access O
   
private static $objs = [];
    private static
$preference = [];
    static function
setPreference($class){
   
self::$preference[get_called_class()] = $class;        // we can hack even polymorphism
   
}
    static function
O($use_as = null){
   
/* we use $use_as, preference or the current calling class in this order. */
   
$cc = ($use_as ? $use_as : (($cc2 = @self::$preference[get_called_class()])!= null ? $cc2 get_called_class()));
    if (!@
self::$objs[$cc]){        // you have to use 'self::' to access a private method.
       
self::$objs[$cc] = new O();
       
self::$objs[$cc]->setVal(static::getName());    // but you can use 'static::' to access class method.
   
}
    return
self::$objs[$cc];
    }
}

class
A implements hasO{    // A is independent from the other classes
   
use T;
    static function
getName() {return 'A';}
    function
myObj($append = "i'm A",$use_as = null){
    if (!
$append && $append !== false) $append = "i'm ".get_called_class();
   
self::O($use_as)->prt($append);
    }
    function
inc(){self::O()->inc();}
}
class
B implements hasO{
    use
T;
    function
myObj($append = null){
    if (!
$append && $append !== false) $append = "i'm ".get_called_class();
    static::
O()->prt($append);
    }
    function
inc(){static::O()->inc();}
    static function
getName() {return get_called_class();}
}
class
C extends B{}   // not relevant inheritence.
class D extends B{
    use
T;            // you won't get errors if you accidently reuse the same trait
   
static function getName() {return 'a child of B ';}        // we can use current object static methods, so inheritence is intact
   
function inc(){
    static::
O()->inc();                    // both self::O and static::O is usable to preserve further inherits
   
self::O()->inc();
    }
}
class
E extends B{
    const
CLSS = 'E';
    function
myObj($append="EEEE!", $use_as = null){
    if (!
$append && $append !== false) $append = "i'm ".get_called_class();
   
self::O($use_as)->prt($append);
    }
}
$a = new A;$b = new B;$c = new C;$d = new D;$e = new E;    // create all objects...
$b->myObj();    $b->inc();    $b->myObj();
$c->myObj();    $c->inc();    $c->myObj();        // C comes before A, so C's object is already instantized before A tries to access it
$a->myObj();    $a->inc();    $a->myObj();
$a->myObj(null,'C');        // this isn't works, because it's protected private
$d->myObj();    $d->inc();    $d->myObj();
$e->myObj();    $e->inc();    $e->myObj("i'm E again");
$e->myObj(0,'C');        // but this IS working, even if it's private NOT protected.
$e::setPreference('B');        // we want to morph to B
$e->myObj();
$e->inc();            // we incement B's object now as seen bellow
$e->myObj();    $b->myObj();

?>
up
-3
farhad dot peb at gmail dot com
1 year ago
<?php
trait first_trait
 
{
    function
first_function()
    {
      echo
"From First Trait";
    }
  }
 
  trait
second_trait
 
{
    function
first_function()
    {
      echo
"From Second Trait";
    }
  }
 
  class
first_class
 
{
    use
first_trait, second_trait
   
{
     
// This class will now call the method
      // first function from first_trait only
     
first_trait::first_function insteadof second_trait;
 
     
// first_function of second_traits can be
      // accessed with second_function
     
second_trait::first_function as second_function;
 
    }
  }
 
 
$obj = new first_class();
 
// Output: From First Trait
 
$obj->first_function();
 
 
// Output: From Second Trait
 
$obj->second_function();
?>

the iranian php programmer

writer: farhad zand

farhad.peb@gmail.com
php_engineer_bk@yahoo.com

 
show source | credits | stats | sitemap | contact | advertising | mirror sites