PHP Methods
What Are Methods? In simple terms: Methods are the actions an object can perform — functions that belong to a class. A shopping cart can add an item, remove an item, and calculate its total. Methods w
What Are Methods?
In simple terms: Methods are the actions an object can perform — functions that belong to a class. A shopping cart can add an item, remove an item, and calculate its total. Methods work with the object's own data through $this.
Technically: A method is a function declared inside a class, with a visibility (public, protected, private), parameters, an optional return type, and a body. Non-static methods are called on an object with $object->method(), and inside them $this refers to that object. Methods are how objects protect their data: properties stay private, and methods enforce the rules for reading and changing them.
Declaring and Calling Methods
Syntax
class ClassName
{
visibility function methodName(Type $param): ReturnType
{
// use $this to access the object's properties and other methods
}
}
Example
<?php
class Temperature
{
private float $celsius = 0.0;
public function setCelsius(float $celsius): void
{
if ($celsius < -273.15) {
throw new InvalidArgumentException('Temperature below absolute zero.');
}
$this->celsius = $celsius;
}
public function celsius(): float
{
return $this->celsius;
}
public function fahrenheit(): float
{
return round($this->celsius * 9 / 5 + 32, 1);
}
}
$chennai = new Temperature();
$chennai->setCelsius(34.5);
echo "{$chennai->celsius()} °C = {$chennai->fahrenheit()} °F\n";
try {
$chennai->setCelsius(-300);
} catch (InvalidArgumentException $e) {
echo $e->getMessage() . "\n";
}
Output
34.5 °C = 94.1 °F
Temperature below absolute zero.
How It Works
$celsiusis private; it can only be changed throughsetCelsius(), which rejects impossible values.celsius()andfahrenheit()return information without changing the object.fahrenheit()is a derived value: it is calculated from the stored data rather than stored separately, so it can never be out of sync.
Kinds of Methods
| Kind | Purpose | Typical Return | Example |
|---|---|---|---|
| Query | Answer a question; no side effects | A value | total(), isEmpty(), fahrenheit() |
| Command | Change the object's state | void or static (for chaining) | add(), remove(), setCelsius() |
| Private helper | Internal step used by other methods | Anything | assertQuantity() |
| Static | Belongs to the class, not an object | Anything | Product::fromArray() (see PHP Static Methods) |
Keeping queries free of side effects ("asking a question should not change the answer") makes classes easier to understand and test.
Getters and Setters vs Meaningful Methods
Generating a getter and setter for every property gives callers full control over the data and moves the rules out of the class:
$order->setStatus('shipped'); // Is shipping allowed now? The caller must know.
Methods named after behavior keep the rules inside the class:
$order->ship(); // The Order checks whether it is paid and not cancelled.
This principle is often summarized as "Tell, don't ask": tell an object what to do instead of pulling its data out, deciding, and pushing data back in.
Practical Example: A Shopping Cart Class
<?php
class ShoppingCart
{
private array $items = [];
public function add(string $sku, string $name, float $price, int $qty = 1): static
{
$this->assertQuantity($qty);
if (isset($this->items[$sku])) {
$this->items[$sku]['qty'] += $qty;
} else {
$this->items[$sku] = ['name' => $name, 'price' => $price, 'qty' => $qty];
}
return $this;
}
public function remove(string $sku): static
{
unset($this->items[$sku]);
return $this;
}
public function itemCount(): int
{
return array_sum(array_column($this->items, 'qty'));
}
public function total(): float
{
$total = 0.0;
foreach ($this->items as $item) {
$total += $this->lineTotal($item);
}
return $total;
}
public function isEmpty(): bool
{
return $this->items === [];
}
public function lines(): array
{
return array_map(
fn(array $item): string => sprintf('%s x %d = ₹%s', $item['name'], $item['qty'], number_format($this->lineTotal($item), 2)),
array_values($this->items)
);
}
private function lineTotal(array $item): float
{
return $item['price'] * $item['qty'];
}
private function assertQuantity(int $qty): void
{
if ($qty < 1) {
throw new InvalidArgumentException('Quantity must be at least 1.');
}
}
}
$cart = new ShoppingCart();
$cart->add('PEN-01', 'Gel Pen', 20, 10)
->add('NB-A5', 'Notebook', 60, 3)
->add('PEN-01', 'Gel Pen', 20, 5);
echo implode("\n", $cart->lines()) . "\n";
echo "Items: {$cart->itemCount()}, total: ₹" . number_format($cart->total(), 2) . "\n";
$cart->remove('NB-A5');
echo "After removing notebooks: {$cart->itemCount()} items, ₹" . number_format($cart->total(), 2) . "\n";
try {
$cart->add('BAG-01', 'Backpack', 1299, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage() . "\n";
}
Output
Gel Pen x 15 = ₹300.00
Notebook x 3 = ₹180.00
Items: 18, total: ₹480.00
After removing notebooks: 15 items, ₹300.00
Error: Quantity must be at least 1.
Step-by-Step Explanation
- Commands (
add(),remove()) change the cart and return$this, so calls can be chained. - Adding the same SKU again increases its quantity instead of creating a duplicate line — a rule that lives inside the class, so no caller can forget it.
- Queries (
itemCount(),total(),isEmpty(),lines()) calculate answers from the current state. - Private helpers (
lineTotal(),assertQuantity()) avoid duplicated logic and are hidden from callers, so they can be changed freely later. - The internal storage (an array keyed by SKU) is invisible to the outside. It could be replaced with
CartItemobjects without changing any code that uses the cart.
Method Parameters and Return Types
Methods use the same parameter features as functions: types, default values, nullable types, named arguments, and variadics (see the PHP Functions section).
<?php
class Greeter
{
public function greet(string $name, string $greeting = 'Hello', bool $shout = false): string
{
$message = "$greeting, $name!";
return $shout ? strtoupper($message) : $message;
}
}
$greeter = new Greeter();
echo $greeter->greet('Asha') . "\n";
echo $greeter->greet('Bala', shout: true) . "\n";
Output
Hello, Asha!
HELLO, BALA!
Special return types are common in classes:
| Return Type | Meaning |
|---|---|
void | Returns nothing (commands) |
static | Returns an instance of the called class — typically $this or a modified clone |
self | Returns an instance of the class where the method is defined |
?Product | Returns a Product or null |
never | Never returns (always throws or exits) |
Methods as Values and Dynamic Calls
<?php
class PriceFormatter
{
public function format(float $amount): string
{
return '₹' . number_format($amount, 2);
}
}
$formatter = new PriceFormatter();
print_r(array_map($formatter->format(...), [20, 1299.5]));
var_dump(method_exists($formatter, 'format'));
Output
Array
(
[0] => ₹20.00
[1] => ₹1,299.50
)
bool(true)
$formatter->format(...)(PHP 8.1+) turns a method into a closure that can be passed as a callback (see First-class Callable Syntax).method_exists()checks whether a method is defined;$object->$methodName()calls a method whose name is in a variable (see Variable Functions) — use an allow-list if the name comes from input.
The Nullsafe Operator
When an object may be null, ?-> calls the method only if the object exists:
$city = $order->customer()?->address()?->city();
If any step returns null, the whole expression becomes null instead of causing an error (see Nullsafe Operator).
Common Mistakes
Forgetting $this-> When Calling Another Method
Effect: lineTotal($item) inside the class calls a global function, which does not exist.
Fix: $this->lineTotal($item).
Public Setters for Everything
Effect: Business rules move out of the class and are duplicated (or forgotten) by callers.
Fix: Provide methods named after behavior that enforce the rules.
Queries With Hidden Side Effects
Effect: Calling total() twice gives different results or modifies data.
Fix: Keep query methods free of side effects.
Huge Methods
Effect: Hard-to-test methods doing many things.
Fix: Extract private helper methods with descriptive names.
Making Helpers Public
Effect: Other code starts depending on internal details, making them hard to change.
Fix: Keep internal methods private.
Best Practices
- Name methods with verbs for commands (
add,ship) and nouns or questions for queries (total,isEmpty). - Keep properties private and expose behavior through methods that enforce rules.
- Separate commands from queries.
- Use private helper methods to keep public methods short and readable.
- Declare parameter and return types on every method.
Official reference: https://www.php.net/manual/en/language.oop5.basic.php