objects namespaces and application architecture

Properties and Methods

Properties store an object's data. Methods are functions that belong to the object and use or change that data.

In professional PHP, properties and methods should make a class easier to understand. Properties should represent state the object owns. Methods should represent behaviour the object can perform or questions it can answer.

Typed properties describe object state

Typed properties make the expected value clear.

PHP example
<?php

declare(strict_types=1);

class Product
{
    public string $sku;
    public string $name;
    public int $pricePennies;
}

$product = new Product();
$product->sku = 'KB-101';
$product->name = 'Keyboard';
$product->pricePennies = 2499;

echo $product->sku . ' / ' . $product->name . PHP_EOL;

// Prints:
// KB-101 / Keyboard

Typed properties catch obvious mistakes, but they do not replace business validation. An integer price can still be negative unless your class prevents it.

Methods use $this

Inside a method, $this refers to the current object.

PHP example
<?php

declare(strict_types=1);

class ProductPrice
{
    public int $pricePennies;

    public function displayPrice(): string
    {
        return '£' . number_format($this->pricePennies / 100, 2);
    }
}

$price = new ProductPrice();
$price->pricePennies = 2499;

echo $price->displayPrice() . PHP_EOL;

// Prints:
// £24.99

The method reads the object's property and returns a display value.

Give properties useful defaults

Defaults are useful when a new object has a sensible initial state.

PHP example
<?php

declare(strict_types=1);

class ImportResult
{
    public int $importedRows = 0;
    public int $failedRows = 0;

    public function hasFailures(): bool
    {
        return $this->failedRows > 0;
    }
}

$result = new ImportResult();
$result->importedRows = 10;

echo $result->hasFailures() ? 'failed' : 'clean';
echo PHP_EOL;

// Prints:
// clean

Without defaults, reading a typed property before assigning it causes an error.

Methods can change object state

Some methods answer a question. Some methods change the object. Name them so the difference is clear.

PHP example
<?php

declare(strict_types=1);

class Basket
{
    public int $itemCount = 0;

    public function addItem(): void
    {
        $this->itemCount++;
    }

    public function isEmpty(): bool
    {
        return $this->itemCount === 0;
    }
}

$basket = new Basket();
$basket->addItem();

echo $basket->isEmpty() ? 'empty' : 'has items';
echo PHP_EOL;

// Prints:
// has items

addItem() changes state. isEmpty() returns information. Good names help reviewers predict side effects.

Avoid unrelated methods

A class should not become a random bag of functions.

PHP example
<?php

declare(strict_types=1);

class Invoice
{
    public int $totalPennies = 0;

    public function totalForDisplay(): string
    {
        return '£' . number_format($this->totalPennies / 100, 2);
    }
}

$invoice = new Invoice();
$invoice->totalPennies = 129950;

echo $invoice->totalForDisplay() . PHP_EOL;

// Prints:
// £1,299.50

Formatting an invoice total belongs close to invoice data. Sending emails, writing files, or querying a database probably belongs in a different class.

Watch uninitialised properties

Typed properties without defaults must be assigned before they are read.

PHP example
<?php

declare(strict_types=1);

class Customer
{
    public string $email;
}

$customer = new Customer();
$customer->email = 'nia@example.com';

echo $customer->email . PHP_EOL;

// Prints:
// nia@example.com

Later, constructors will make this safer by requiring important values when the object is created.

What to remember

Properties are the state an object owns. Methods are behaviour that reads or changes that state. Use types and defaults deliberately, name side-effecting methods clearly, and keep methods related to the class's responsibility.

Practice

Task: Track an import result

Create a class that tracks the result of an import.

Requirements

  • Use declare(strict_types=1);.
  • Create an ImportResult class.
  • Add typed public properties for imported row count, failed row count, and error messages.
  • Give the counts sensible default values.
  • Add a method that records a successful row.
  • Add a method that records a failed row with an error message.
  • Add a method that returns whether the import has failures.
  • Print the final counts and failure status.
  • Include the expected output as comments in the same PHP code block.

The goal is to show properties storing state and methods changing or reading that state.

Show solution
PHP example
<?php

declare(strict_types=1);

class ImportResult
{
    public int $importedRows = 0;
    public int $failedRows = 0;
    public array $errors = [];

    public function recordImportedRow(): void
    {
        $this->importedRows++;
    }

    public function recordFailedRow(string $message): void
    {
        $this->failedRows++;
        $this->errors[] = $message;
    }

    public function hasFailures(): bool
    {
        return $this->failedRows > 0;
    }
}

$result = new ImportResult();
$result->recordImportedRow();
$result->recordImportedRow();
$result->recordFailedRow('Line 3 is missing an email.');

echo 'Imported: ' . $result->importedRows . PHP_EOL;
echo 'Failed: ' . $result->failedRows . PHP_EOL;
echo $result->hasFailures() ? 'has failures' : 'clean';
echo PHP_EOL;
echo $result->errors[0] . PHP_EOL;

// Prints:
// Imported: 2
// Failed: 1
// has failures
// Line 3 is missing an email.

The properties hold the current state of the import. The methods make the allowed state changes explicit and keep the failure check in one place.