PHP 5.6.18 is available

Nitelikler

PHP 5.4.0 itibariyle, PHP tekrar tekrar kullanılabilen bir yöntem kodu olarak trait isminı kullanarak nitelikleri tanımlamıştır.

Nitelikler, PHP gibi tek kalıtımlı dillerde kodun yeniden kullanımını sağlayan bir mekanizmadır. Yöntem kümelerini farklı sınıf hiyerarşilerinde yaşayan birçok bağımsız sınıfın içinde özgürce yeniden kullanımını mümkün kılarak tek kalıtımlı dillerdeki bazı sınırlamaları azaltmak için tasarlanmıştır. Sınıfların ve niteliklerin birleşiminden doğan anlamlılık, karmaşıklığı azaltan ve çoklu kalıtım ve iç içeliklerle ilgili bilinen sorunlardan kaçınan bir yol izlenerek tanımlanmıştır.

Nitelikler sınıflara benzemekle birlikte işlevselliği gruplamak için daha bir ince elenip sık dokunarak tasarlanmıştır. Bir niteliği kendi içinde örneklemek mümkün değildir. Geleneksel kalıtıma bir ekleme olup yatay davranış düzenini, yani kalıtım gerekmeksizin sınıf üyesi olmayı mümkün kılar.

Örnek 1 Nitelik örneği

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

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

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

Öncelik sırası

Bir nitelikle gelen bir üye, bir temel sınıftan miras alınan bir üyenin yerine geçerse onu geçersiz kılar; sınıfın kendi üyeleri de niteliğin yerine geçerse onu geçersiz kılar.

Örnek 2 Öncelik sırası örneği

Temel sınıftan miras alınan yöntem, DünyaDe niteliğinden MerhabaDünyam içine yerleştirilen üye tarafından geçersizleştirilmektedir. MerhabaDünyam sınıfı içinde tanımlı yöntemler için de davranış aynıdır. Öncelik sırası şöyledir: Temel sınıftan alınan yöntemleri geçersizleştiren nitelikleri geçerli sınıfın yöntemleri geçersizleştirir.

<?php
class Temel {
    public function 
merhabaDe() {
        echo 
'Merhaba ';
    }
}

trait 
DünyaDe {
    public function 
merhabaDe() {
        
parent::merhabaDe();
        echo 
'Dünya!';
    }
}

class 
MerhabaDünyam extends Temel {
    use 
DünyaDe;
}

$o = new MerhabaDünyam();
$o->merhabaDe();
?>

Yukarıdaki örneğin çıktısı:

Merhaba Dünya!

Örnek 3 Bir diğer öncelik sırası örneği

<?php
trait MerhabaDünya {
    public function 
merhabaDe() {
        echo 
'Merhaba Dünya!';
    }
}

class 
DünyaYetmez {
    use 
MerhabaDünya;
    public function 
merhabaDe() {
        echo 
'Merhaba Evren!';
    }
}

$o = new DünyaYetmez();
$o->merhabaDe();
?>

Yukarıdaki örneğin çıktısı:

Merhaba Evren!

Çoklu Nitelikler

Çok sayıda nitelik bir sınıfın içine use deyiminde virgüllerle ayrılarak yerleştirilebilir.

Örnek 4 Çok sayıda niteliğin kullanımı

<?php
trait Merhaba {
    public function 
merhabaDe() {
        echo 
'Merhaba ';
    }
}

trait 
Dünya {
    public function 
dünyaDe() {
        echo 
'Dünya';
    }
}

class 
MerhabaDünyam {
    use 
MerhabaDünya;
    public function 
Bağır() {
        echo 
'!';
    }
}

$o = new MerhabaDünyam();
$o->merhabaDe();
$o->dünyaDe();
$o->Bağır();
?>

Yukarıdaki örneğin çıktısı:

Merhaba Dünya!

Çelişki Çözümleme

Bir yönteme aynı isme sahip iki nitelik yerleştirilirse çelişki açıkça çözümlenmediği takdirde ölümcül bir hataya sebep olur.

Aynı sınıfta kullanılan nitelikler arasındaki adlandırma çakışmasını çözümlemek için insteadof işleci birini seçmek amacıyla kullanılabilir.

Bu işlem niteliklerin birini dışlamayı sağladığından diğerini de farklı bir isimle içermek için as işleci kullanılabilir.

Örnek 5 Çelişki çözümleme örneği

Bu örnekte, Talker A ve B niteliklerini kullanıyor. A ve B çakışan yöntemlere sahip olduğundan B niteliğinden smallTalk ve A niteliğinden bigTalk kullanılmaktadır.

Aliased_Talker ise B'nin bigTalk gerçeklenimini talk diye bir takma ad altında kullanmak için as işlecinden yararlanmaktadır.

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

trait 
{
    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;
    }
}
?>

Yöntem Görünürlüğünü Değiştirme

Sergileyen sınıf içinde yöntemin görünürlüğünü ayarlamak için as sözdizimi kullanılabilir.

Örnek 6 Yöntem görünürlüğünü değiştirme örneği

<?php
trait MerhabaDünya {
    public function 
merhabaDe() {
        echo 
'Merhaba Dünya!';
    }
}

// merhabaDe görünürlüğünü değiştir
class Sınıfım1 {
    use 
MerhabaDünya merhabaDe as protected; }
}

// Görünürlüğü ve ismi değişmiş yöntem
// merhabaDe görünürlüğü değişmedi
class Sınıfım2 {
    use 
MerhabaDünya merhabaDe as private özelMerhabam; }
}
?>

Niteliklerden oluşturulmuş Nitelikler

Sınıflarda olduğu gibi nitelikler de bir diğerinin içinde kullanılabilir. Birden fazla nitelik kısmen veya tamamen bir diğer niteliğin içinde kullanılabilir.

Örnek 7 Niteliklerden nitelik oluşturma örneği

<?php
trait Merhaba {
    public function 
merhabaDe() {
        echo 
'Merhaba ';
    }
}

trait 
Dünya {
    public function 
dünyaDe() {
        echo 
'Dünya!';
    }
}

trait 
MerhabaDünya {
    use 
MerhabaDünya;
}

class 
MerhabaDünyam {
    use 
MerhabaDünya;
}

$o = new MerhabaDünyam();
$o->merhabaDe();
$o->dünyaDe();
?>

Yukarıdaki örneğin çıktısı:

Merhaba Dünya!

Soyut Nitelik Yöntemleri

Nitelikler, sergileyen sınıfa gereksinimleri aşılamak amacıyla yöntem soyutlamayı destekler.

Örnek 8 Gereksinimlerin soyut yöntemlerle ifadesi

<?php
trait Merhaba {
    public function 
merhabaDünyaDe() {
        echo 
'Merhaba'.$this->dünyaGetir();
    }
    abstract public function 
dünyaGetir();
}

class 
MerhabaDünyam {
    private 
$dünya;
    use 
Merhaba;
    public function 
dünyaGetir() {
        return 
$this->dünya;
    }
    public function 
dünyaAta($val) {
        
$this->dünya $val;
    }
}
?>

Duruk Nitelik Yöntemleri

Nitelikler hem duruk üyeleri hem de duruk yöntemleri tanımlayabilir.

Örnek 9 Duruk Değişkenler

<?php
trait Sayaç {
    public function 
arttır() {
        static 
$c 0;
        
$c $c 1;
        echo 
"$c\n";
    }
}

class 
C1 {
    use 
Sayaç;
}

class 
C2 {
    use 
Sayaç;
}

$o = new C1(); $o->arttır(); // 1 basar
$p = new C2(); $p->arttır(); // 1 basar
?>

Örnek 10 Duruk Yöntemler

<?php
trait DurukÖrnek {
    public static function 
bişeyYap() {
        return 
'Bir şey yapıyorum';
    }
}

class 
Örnek {
    use 
DurukÖrnek;
}

Örnek::bişeyYap();
?>

Özellikler

Nitelikler özellik tanımlayabilir.

Örnek 11 Özellik tanımlama örneği

<?php
trait NitelikliÖzellik {
    public 
$x 1;
}

class 
ÖzellikÖrneği {
    use 
NitelikliÖzellik;
}

$örnek = new ÖzellikÖrneği;
örnek->x;
?>

Bir nitelik bir özellik tanımlarsa sınıf aynı isimde bir özellik tanımlayamaz, aksi takdirde bir hata oluşur. Eğer sınıf tanımı (aynı görünürlük ve ilk değer olarak) uyumluysa E_STRICT çıktılanır değilse ölümcül bir hata oluşur.

Örnek 12 Çelişki yaratma örneği

<?php
trait NitelikliÖzellik {
    public 
$aynı true;
    public 
$farklı false;
}

class 
ÖzellikÖrneği {
    use 
NitelikliÖzellik;
    public 
$aynı true// Strict
    
public $farklı true// ölümcül hata
}
?>
add a note add a note

User Contributed Notes 31 notes

up
226
Safak Ozpinar / safakozpinar at gmail
3 years 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
107
greywire at gmail dot com
3 years 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
91
Stefan W
2 years ago
Note that the "use" operator for traits (inside a class) and the "use" operator for namespaces (outside the class) resolve names differently. "use" for namespaces always sees its arguments as absolute (starting at the global namespace):

<?php
namespace Foo\Bar;
use
Foo\Test// means \Foo\Test - the initial \ is optional
?>

On the other hand, "use" for traits respects the current namespace:

<?php
namespace Foo\Bar;
class
SomeClass {
    use
Foo\Test;   // means \Foo\Bar\Foo\Test
}
?>

Together with "use" for closures, there are now three different "use" operators. They all mean different things and behave differently.
up
13
qeremy (!) gmail
10 months ago
Keep in mind; "final" keyword is useless in traits when directly using them, unlike extending classes / abstract classes.

<?php
trait Foo {
    final public function
hello($s) { print "$s, hello!"; }
}
class
Bar {
    use
Foo;
   
// Overwrite, no error
   
final public function hello($s) { print "hello, $s!"; }
}

abstract class
Foo {
    final public function
hello($s) { print "$s, hello!"; }
}
class
Bar extends Foo {
   
// Fatal error: Cannot override final method Foo::hello() in ..
   
final public function hello($s) { print "hello, $s!"; }
}
?>

But this way will finalize trait methods as expected;

<?php
trait FooTrait {
    final public function
hello($s) { print "$s, hello!"; }
}
abstract class
Foo {
    use
FooTrait;
}
class
Bar extends Foo {
   
// Fatal error: Cannot override final method Foo::hello() in ..
   
final public function hello($s) { print "hello, $s!"; }
}
?>
up
33
atorich at gmail dot com
2 years ago
add to "chris dot rutledge at gmail dot com":
__CLASS__ will return the name of the class in which the trait is being used (!) not the class in which trait method is being called:

<?php
trait TestTrait {
    public function
testMethod() {
        echo
"Class: " . __CLASS__ . PHP_EOL;
        echo
"Trait: " . __TRAIT__ . PHP_EOL;
    }
}

class
BaseClass {
    use
TestTrait;
}

class
TestClass extends BaseClass {

}

$t = new TestClass();
$t->testMethod();

//Class: BaseClass
//Trait: TestTrait
up
54
chris dot rutledge at gmail dot com
4 years 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
33
t8 at AT pobox dot com
3 years 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
43
ryan at derokorian dot com
3 years 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
24
Anonymous
3 years ago
Traits can not implement interfaces.
(should be obvious, but tested is tested)
up
21
karolis at iwsolutions dot ie
3 years 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
9
Kristof
1 year ago
don't forget you can create complex (embedded) traits as well

<?php
trait Name {
 
// ...
}
trait
Address {
 
// ...
}
trait
Telephone {
 
// ...
}
trait
Contact {
  use
Name, Address, Telephone;
}
class
Customer {
  use
Contact;
}
class
Invoce {
  use
Contact;
}
?>
up
10
anthony bishopric
3 years 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
3
qschuler at neosyne dot com
1 year ago
Note that you can omit a method's inclusion by excluding it from one trait in favor of the other and doing the exact same thing in the reverse way.

<?php

trait A {
    public function
sayHello()
    {
        echo
'Hello from A';
    }

    public function
sayWorld()
    {
        echo
'World from A';
    }
}

trait
B {
    public function
sayHello()
    {
        echo
'Hello from B';
    }

    public function
sayWorld()
    {
        echo
'World from B';
    }
}

class
Talker {
    use
A, B {
       
A::sayHello insteadof B;
       
A::sayWorld insteadof B;
       
B::sayWorld insteadof A;
    }
}

$talker = new Talker();
$talker->sayHello();
$talker->sayWorld();

?>

The method sayHello is imported, but the method sayWorld is simply excluded.
up
11
Edward
3 years 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
11
D. Marti
3 years 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
5
ryan dot yoosefi at gmail dot com
1 year ago
Visibility in traits is not shared between trait users.

<?php

trait T {
    protected
$secret = 1;
}

class
X {
    use
T;
    public function
peek ( Y $y ) {
        echo
$y->secret;
    }
}

class
Y {
    use
T;
}

(new
X)->peek(new Y); // Fatal:  Cannot access protected property Y::$secret
?>

This is as expected when thinking of traits as language assisted copy-paste.
up
10
Jason dot Hofer dot deletify dot this dot part at gmail dot com
3 years 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
3
ryanhanekamp at yahoo dot com
3 years 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
1
Oddant
2 years 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
2
Vasyl Sovyak
2 months ago
<?php
trait A
{
    public function
bar()
    {
        echo
'A::bar';
    }
}

trait
B
{
    public function
bar()
    {
        echo
'B::bar';
    }
}

trait
C
{
    public function
bar()
    {
        echo
'C::bar';
    }
}

class
Foo
{
    use
A, B, C {
       
C::bar insteadof A, B;
    }
}

$foo = new Foo();
$foo->bar(); //C::bar
up
0
balbuf
12 days ago
(It's already been said, but for the sake of searching on the word "relative"...)

The "use" keyword to import a trait into a class will resolve relative to the current namespace and therefore should include a leading slash to represent a full path, whereas "use" at the namespace level is always absolute.
up
1
artur at webprojektant dot pl
3 years ago
Trait can not have the same name as class because it will  show: Fatal error: Cannot redeclare class
up
0
heli
2 months ago
class first_class
   {
     // Using the Trait Here
     use first_trait;
   }

   $obj = new first_class();

   // Executing the method from trait
   $obj->first_method(); // valid
   $obj->second_method(); // valid
up
-1
vijit at mail dot ru
4 months ago
Example #9 "Static Variables" is useless. Variable $c in function will be static anyway, this is provided by scope of function. And the result will be the same without directive "static".
up
0
Nanhe Kumar
9 months ago
<?php

//Precedence Order Example with base class
trait T {

    public function
foo() {
        echo
"T";
    }

}

class
A {

    public function
foo() {
        echo
"A";
    }

}

class
B extends A {

    use
T;
}

$o = new B();
$o->foo(); //Prints : T
?>
up
0
84td84 at gmail dot com
10 months ago
A note to 'Beispiel #9 Statische Variablen'. A trait can also have a static property:

trait Counter {
    static $trvar=1;

    public static function stfunc() {
        echo "Hello world!"
    }
}

class C1 {
    use Counter;
}

print "\nTRVAR: " . C1::$trvar . "\n";   //prints 1

$obj = new C1();
C1::stfunc();   //prints  Hello world!
$obj->stfunc();   //prints Hello world!

A static property (trvar) can only be accessed using the classname (C1).
But a static function (stfunc) can be accessed using the classname or the instance ($obj).
up
0
aram dot petrosyan dot 88 at gmail dot com
1 year ago
It's possible to define abstract function in a trait as static and implement non-static version of the function , and it will works. Like this

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

class traitTest
{
    use B;

    public static function talk()
    {
        echo 111;
    }
}

Also, it's possible to define abstract non static , and implement static version.

Can't understand , is this a bug or it's a feature :)
up
0
angel dot ayora at gmail dot com
1 year ago
The traits can be used if are inherited from a parent class, but the trait still belong to parent class:

<?php

trait Singleton
{
    private static
$instance = null;

    public static function
singleton()
    {
        if(
self::$instance == null )
        {
           
self::$instance = new self();
        }
        return
self::$instance;
    }
}

class
A
{
    use
Singleton;
    private function
__construct(){}
}

class
B extends A
{
    private function
__construct(){}
}

$b = B::singleton();
echo
get_class($b); //Output: A

?>
up
-4
Serafim
3 years 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
-6
contato at williamsantana dot com dot br
2 years ago
Please note that a trait cannot extend a class. Traits can only contain another traits by using 'use' keyword. Things like

<?php
   
trait DetailedException extends Exception {}
?>

will not work. Be careful.

Cheers.
up
-3
tomasz at marcinkowski dot pl
1 year ago
Unlike the __CLASS__ constant, which returns name of a class implementing a trait, the __METHOD__ constant returns the trait method name. You might find it useful.

Example:

<?php

namespace XXX;

trait
Ta {
  public function
test1() {
    return
sprintf('class: %s, method: %s, trait: %s', __CLASS__, __METHOD__, __TRAIT__);
  }
}

class
A {
  use
Ta;
}

$a = new A();
var_dump($a->test1()); // class: XXX\A, method: XXX\Ta::test1, trait: XXX\Ta

?>
To Top