Lesson 77 of 100
Classes15 min5 checksPHP 8.5

Name Domain Values with Class Constants

Learn how PHP 8.4 class constants name business rules, control visibility, hold typed values and keep magic numbers out of your logic.

01 · THE IDEAREAD → TRY → LEARN

Why constants belong to a class

Suppose a shop gives free standard shipping at 5000 cents. If the number 5000 is scattered through your code, nobody knows what it means and changing it is risky. A class constant gives the value a name and a home. The value is fixed, it is stored once per class rather than once per object, and you read it without creating an instance.

Declaring and reading constants

You declare a constant with const inside a class body and read it with the scope resolution operator, ClassName::NAME. Inside the class you can use self::NAME. Constants are often used for a fixed vocabulary, such as statuses, and a constant may hold an array of other constants.

Example
<?php
class Status
{
    public const DRAFT = 'draft';
    public const PUBLISHED = 'published';
    public const ALL = [self::DRAFT, self::PUBLISHED];
}

echo Status::PUBLISHED, "\n";
echo json_encode(Status::ALL, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
published
["draft","published"]

Because ALL is built from the other constants, renaming a value later only requires one edit.

Visibility and types

Class constants are public by default. You can mark them private or protected to keep an internal rule hidden. Use public constants for values that callers legitimately need, such as a status name, and private ones for implementation details.

Since PHP 8.3 a constant can also declare a type such as int, string, bool, float or array. A typed constant documents intent and makes PHP reject a value of the wrong type.

Example
<?php
class Discount
{
    private const int MAX_PERCENT = 30;
    public const string LABEL = 'discount';

    public static function clamp(int $percent): int
    {
        return min(max($percent, 0), self::MAX_PERCENT);
    }
}

echo Discount::LABEL, ':', Discount::clamp(45), "\n";
echo Discount::clamp(-5), "\n";
Output
discount:30
0

Code outside the class can read Discount::LABEL, but touching Discount::MAX_PERCENT would throw an Error. The public static method is the only door to the rule.

Other ways to fetch a constant

The special ::class constant gives the class name as a string. Since PHP 8.3 you can also fetch a constant whose name is stored in a variable with Class::{$name}. The constant() function accepts a string such as 'Plan::FREE'.

Example
<?php
class Plan
{
    public const FREE = 0;
    public const PRO = 15;
}

$name = 'PRO';
echo Plan::{$name}, "\n";
echo constant(Plan::class . '::FREE'), "\n";
echo Plan::class, "\n";
Output
15
0
Plan

Dynamic lookup is handy for mapping input to a rule, but validate the name first, because an unknown constant throws an Error.

Inheritance and final

A child class may redefine a parent's constant. If the parent declares it final, which is possible since PHP 8.1, the child cannot. Mark a constant final when its value is a rule that subclasses must never change. Interfaces can also declare constants, and since PHP 8.3 an implementing class must not make an interface constant less visible.

Common mistakes

  • Writing $this->MAX or $MAX instead of self::MAX. Constants have no dollar sign and are not object properties.
  • Using self:: where a child should be able to override the value. self:: always points at the class that wrote the code.
  • Putting changing data in a constant. A constant is a rule, not state.
  • Leaving a number unnamed in a comparison. Name it, then compare against the name.
  • Using a loose boundary such as > when the rule says "at least". Test the exact boundary value.

Exercise contract

Write shippingCostCents(int $subtotalCents, string $method): ?int, using a ShippingRules class for its numbers.

  • A negative subtotal returns null.
  • Method standard costs 499, but is free (0) when the subtotal is at least 5000.
  • Method express always costs 1299.
  • Any other method returns null.

The starter already declares the constants. Your work is to use them in the function instead of repeating the numbers. Tests check the returned values, including the 4999 and 5000 boundary.

Recap

Class constants name fixed domain values, are shared by the whole class and are read with ::. Control access with visibility, protect rules with final, and describe values with types in PHP 8.3 and later. Reference them everywhere instead of repeating literals.

Before you start

Functions · Arrays · Types

You’ll practice
  • Use visible constants to define stable domain rules
  • Implement and test a deterministic PHP 8.4 function
Your task

Make shippingCostCents() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.