Variables and Types in PHP
Learn how PHP handles variables, data types, type juggling, casting, and modern type declarations with Docker-ready examples
PHP is a dynamically typed language with weak typing: variables do not require a type declaration, and the interpreter happily converts between types when operations demand it. A single variable can hold an integer one moment and a string the next.
That flexibility is part of why PHP became the dominant language of the early web — it simply got out of your way. But the trade-off is that type-related bugs can be subtle. Modern PHP (7.0+) addresses this with optional scalar type hints, return types, union types, and declare(strict_types=1) to opt into stricter behavior. This tutorial covers both the traditional dynamic style and the modern typed style you’ll see in professional PHP codebases today.
By the end, you will know how to declare variables with the $ prefix, recognize PHP’s core scalar types, inspect types at runtime, cast between them deliberately, understand the type juggling that happens automatically, and define constants and type-hinted classes.
Variables, Scalar Types, and Type Juggling
Every PHP variable is prefixed with a dollar sign ($). PHP recognizes four scalar types — int, float, string, bool — plus null, array, and object. The type is determined by what you assign, not by any declaration.
Create a file named variables.php:
| |
A few details worth calling out:
gettype($price)returns"double"— a historical quirk. PHP floats are IEEE-754 doubles, and the name stuck even though the language keyword isfloat.- Dollar sign in a double-quoted string must be escaped as
\$, otherwise PHP tries to interpolate it as a variable name. constvsdefine()—constis evaluated at compile time and works inside classes;define()is a runtime function and can accept a computed name. Both produce constants that cannot be reassigned.
Modern Type Declarations
Since PHP 7, function parameters, return values, and class properties can be annotated with types. Adding declare(strict_types=1) at the top of a file disables the implicit conversions you saw above — passing a string where an int is expected becomes a TypeError instead of a silent coercion.
Create a file named typed_variables.php:
| |
Under strict_types=1, calling greet("Alice", "30") would throw a TypeError because "30" is not an int — even though it could be converted to one. Without the declaration, PHP would coerce silently. Most modern PHP projects enable strict types in every file.
Running with Docker
| |
Expected Output
Output of variables.php:
Name: Alice
Age: 30
Price: $19.99
Active: yes
Nothing: NULL
--- Types ---
age is integer
price is double
name is string
isActive is boolean
nothing is NULL
--- Type Conversion ---
(int) '42' = 42
(float) '3.14' = 3.14
(string) 100 = '100'
(bool) 0 = false
--- Type Juggling ---
'5' + 3 = 8 (integer)
'5' . 3 = '53' (string)
--- Comparison ---
bool(true)
bool(false)
--- Constants ---
MAX_USERS = 100
SITE_NAME = CodeArchaeology
Output of typed_variables.php:
Hello, Alice! You are 30 years old.
Hello, Bob! You are 25 years old.
User #42
No user
ID: 7
ID: abc-123
Book: $12.99 (stock: 5)
Key Concepts
- Sigil-prefixed variables — every variable is written with a leading
$, and names are case-sensitive. Function and class names are case-insensitive; variables are not. - Dynamic and weak by default — assigning to a variable determines its type, and arithmetic or concatenation will coerce operands silently.
"5" + 3is8;"5" . 3is"53". - Seven primary types —
int,float,string,bool,array,object, andnull.gettype()returns"double"for floats and"NULL"for null, for historical reasons. - Explicit casting uses parenthesized type names:
(int),(float),(string),(bool),(array). Prefer explicit casts over relying on juggling in real code. - Strict vs loose equality —
==applies type juggling before comparing;===requires identical types as well as values. Default to===to avoid surprises. - Type declarations are optional but encouraged — PHP 7+ supports scalar type hints, return types, nullable types (
?int), and union types (int|string). Adddeclare(strict_types=1)to turn silent coercions intoTypeErrors. constanddefine()both create constants, butconstis compile-time and scope-aware, whiledefine()is a runtime function. Constants are written without the$sigil when referenced.- Readonly and typed properties (PHP 7.4 / 8.1) bring immutability and type safety to classes, making modern PHP feel closer to statically typed languages without giving up its scripting roots.
Running Today
All examples can be run using Docker:
docker pull php:8.4-cli-alpine
Comments
Loading comments...
Leave a Comment