Traits
PHP classes can only inherit from one parent — but real apps often need the same behaviour (logging, timestamps, slugs) across unrelated classes. Traits are PHP's answer: reusable bundles of methods you mix into any class, no shared parent required.
Learn Traits in our free PHP course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Your First Trait
Declare a trait just like a class, but with the trait keyword. Inside it lives one or more methods. To use it, write use TraitName; at the top of a class body — PHP effectively copies the trait's methods into that class. Two completely unrelated classes can both use the same trait and gain the behaviour.
2️⃣ Traits With State
Traits aren't limited to methods — they can declare properties too, and even abstract methods. When the trait is mixed in, those properties become part of the class. Inside the trait, $this refers to whatever object is using it, so the trait can read and write the host's state.
3️⃣ Composing Multiple Traits
A single class can use several traits at once, separated by commas (or in separate use lines). This is the real power: you build a class up from small, focused, reusable behaviours instead of one giant inheritance tree.
4️⃣ Resolving Conflicts
What if two traits both define a method called log() ? PHP won't guess — it raises a fatal error and asks you to choose. Inside the use block, A::method insteadof B picks the winner, and B::method as alias keeps the other version available under a new name.
Now you try — fill in each ___ using the 👉 hint, then run it and check against the Output panel.
🧩 Reorder Challenge
These lines define a trait, mix it into a class, and call its method — but they're scrambled. Put them in the order PHP needs.
The trait must be declared first: open it ( C ), define its method ( B ), close it ( E ). Only then can a class mix it in ( A ) and call the method ( D ), which prints pong .
🧠 Quick Recall — Predict the Output
hihi — both unrelated classes gained the same hi() method from the trait, with no shared parent.
21 — the trait's property belongs to each instance , so $a reaches 2 and $b reaches 1 independently.
A fatal error — both traits define go() , an unresolved conflict. You must add an insteadof rule in the use block to choose a winner.
Common Errors (and the fix)
- "Trait method ... has not been applied as ... collision" — two traits define the same method. Add A::method insteadof B; in the use block.
- "Cannot instantiate trait" — you tried new SomeTrait() . Traits aren't classes; mix them into a class and instantiate that.
- "Undefined property" inside a trait — the trait references $this->name but the host class never defines it. Declare the property, or make the trait require it via an abstract method.
- A trait method clashes with one already in the class — the class's own method wins. Rename to avoid confusion, or alias the trait method with as .
Pro Tips
- 💡 Keep traits small and focused. One capability per trait (logging, timestamps) composes far better than a kitchen-sink trait.
- 💡 Pair a trait with an interface. The interface declares the contract; the trait provides a default implementation many classes can share.
- 💡 Use an abstract method in the trait to demand a piece from the host class — it documents the dependency and fails fast if it's missing.
📋 Quick Reference — Traits
Syntax
Example
What It Does
trait X {}
trait Loggable { ... }
Declare a trait
use X;
class Order { use Loggable; }
Mix a trait into a class
use A, B;
use Greetable, Farewell;
Mix in several traits
A::m insteadof B;
FileLogger::log insteadof DbLogger;
Resolve a method conflict
B::m as alias;
DbLogger::log as logToDb;
Keep loser under a new name
abstract function
abstract public function name(): string;
Require host to implement
Frequently Asked Questions
Mini-Challenge: Reusable Counter Trait
No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments.
🎉 Lesson Complete!
- ✅ A trait is a reusable bundle of methods mixed in with use
- ✅ Traits sidestep single inheritance — share behaviour across unrelated classes
- ✅ They can hold properties and abstract methods, not just concrete code
- ✅ A class can compose several traits at once
- ✅ Resolve clashes with insteadof and rename with as
- ✅ Next lesson: Generators — produce values lazily with yield
Practice quiz
Which keyword mixes a trait into a class?
- extends
- implements
- use
- import
Answer: use. Inside a class body you write 'use TraitName;' to mix the trait's methods in.
Why do traits exist in PHP?
- To share behaviour across classes despite single inheritance
- To replace interfaces entirely
- To allow multiple inheritance of classes
- To make classes abstract
Answer: To share behaviour across classes despite single inheritance. PHP has no multiple inheritance, so traits let unrelated classes share the same methods.
What happens if two traits used in one class define the same method name?
- The last trait silently wins
- PHP merges both method bodies
- Nothing — both are kept under the same name
- A fatal conflict error unless you resolve it
Answer: A fatal conflict error unless you resolve it. PHP refuses to guess; you must resolve it with insteadof (and optionally as) in the use block.
Which syntax resolves a method conflict between FileLogger and DbLogger?
- FileLogger::log override DbLogger;
- FileLogger::log insteadof DbLogger;
- use FileLogger over DbLogger;
- FileLogger::log replaces DbLogger;
Answer: FileLogger::log insteadof DbLogger;. insteadof picks the winning method; 'DbLogger::log as logToDb;' keeps the loser under a new name.
Can a trait declare properties, not just methods?
- Yes — properties and even abstract methods
- No — methods only
- Only constants
- Only static properties
Answer: Yes — properties and even abstract methods. Traits can hold properties and abstract methods; mixed-in properties become part of the host class.
Two unrelated classes A and B both 'use Hi' (returns 'hi'). What does (new A)->hi() . (new B)->hi() print?
- hi
- An error
- hihi
- AB
Answer: hihi. Both classes gained the same hi() method from the trait, with no shared parent.
Does a trait property belong to the class or each instance?
- All instances share one value
- Each instance keeps its own independent value
- It is read-only
- It is static by default
Answer: Each instance keeps its own independent value. A trait's property belongs to each instance, so two objects keep independent state.
What is the difference between a trait and an interface?
- An interface carries code; a trait only declares signatures
- They are identical
- A trait can be instantiated but an interface cannot
- A trait carries real method bodies; an interface only declares signatures
Answer: A trait carries real method bodies; an interface only declares signatures. An interface is a contract of signatures; a trait carries actual implementations copied into the class.
What happens if you try new SomeTrait()?
- It creates an empty object
- An error — traits cannot be instantiated
- It returns null
- It works like a class
Answer: An error — traits cannot be instantiated. Traits aren't classes; you mix them into a class with use and instantiate that class instead.
How can a trait force the host class to supply a method?
- Use a private method
- Throw an exception
- Declare an abstract method in the trait
- It cannot require anything
Answer: Declare an abstract method in the trait. An abstract method in a trait forces any class using it to implement that method.
Continue this course
- Previous: Working with JSON (json_encode/decode)
- Next: Generators (yield)