Skip to main content

Course Progress

Loading...

PHP Variables and Data Types

Duration: 45 minutes
Module 2: Variables & Data Types

Learning Objectives

  • Understand PHP variables and constants
  • Master PHP data types
  • Learn variable scope and lifetime
  • Apply best practices for naming and usage

Introduction to PHP Variables and Data Types

Welcome to our exploration of variables and data types in PHP! Understanding these concepts is fundamental to programming in any language, and PHP offers a particularly flexible approach to working with different kinds of data.

In this session, we'll learn how to declare and use variables, explore the various data types that PHP supports, and see how PHP's type system influences the way we write code.

Diagram
> C[Naming Rules] A > E[Type Handling] E > G[Scalar Types] F > I[Special Types] G > G2[Float] G > G4[Boolean] H > H2[Object] I PHP Variables Declaration Naming Rules Scope Type Handling Data Types Scalar Types Compound Types Special Types Integer Float String Boolean Array Object NULL Resource

Analogy: Think of variables as labeled containers that can hold different types of data. The label (variable name) helps you find and access the container, while the type of data is like the contents of the container. Some containers hold simple items (scalar types), others hold collections (compound types), and some have special purposes (special types).

PHP Variables Basics

Variables are used to store data that can be referenced and manipulated throughout your program. Let's explore the basic concepts of PHP variables.

Variable Declaration and Assignment

In PHP, variables are declared using the dollar sign ($) followed by the variable name. Unlike some other languages, PHP doesn't require a specific declaration statement - variables are created when you first assign a value to them.

<?php
// Variable declaration and assignment
$username = "john_doe";  // String
$age = 25;               // Integer
$price = 19.99;          // Float/Double
$isActive = true;        // Boolean

// You can also declare a variable without assigning a value
$temporaryVar;           // This is declared but has no value (technically NULL)

// Later, you can assign or change its value
$temporaryVar = "Now I have a value";

// Variables can change types dynamically
$dynamicVar = "This is a string";
echo $dynamicVar . "<br>";  // Outputs: This is a string

$dynamicVar = 42;
echo $dynamicVar . "<br>";  // Outputs: 42

$dynamicVar = true;
echo $dynamicVar . "<br>";  // Outputs: 1 (true is displayed as 1)
?>

Variable Naming Rules

When naming variables in PHP, follow these rules:

  • A variable name must start with a dollar sign ($)
  • Following the dollar sign, it must start with a letter or underscore (_)
  • It can only contain alphanumeric characters and underscores (A-z, 0-9, and _)
  • Variable names are case-sensitive ($name and $Name are different variables)
<?php
// Valid variable names
$name = "John";
$_name = "John";
$name1 = "John";
$first_name = "John";
$firstName = "John";    // Camel case (common convention)
$first_Name = "John";   // Valid but not conventional
$_1name = "John";       // Valid but not conventional

// Invalid variable names (would cause errors)
// $1name = "John";     // Cannot start with a number
// $name-first = "John"; // Cannot contain hyphens
// $name.first = "John"; // Cannot contain periods
// $name first = "John"; // Cannot contain spaces
?>

Naming Convention Best Practices

While PHP allows flexible naming, consistent conventions improve code readability:

  • camelCase: First word lowercase, subsequent words capitalized (e.g., $firstName)
  • snake_case: All lowercase with underscores between words (e.g., $first_name)
  • Choose one convention and stick with it throughout your project
  • Use descriptive names that indicate the variable's purpose
  • WordPress generally uses snake_case for variables

Variable Scope

The scope of a variable determines where in your code the variable can be accessed. PHP has several variable scopes:

Local Scope

Variables declared within a function have local scope and can only be accessed within that function.

<?php
function testFunction() {
    $localVar = "I'm local to this function";
    echo $localVar . "<br>";  // This works
}

testFunction();  // Outputs: I'm local to this function

// echo $localVar;  // This would cause an error - $localVar only exists inside the function
?>

Global Scope

Variables declared outside all functions have global scope but are not automatically available inside functions.

<?php
$globalVar = "I'm a global variable";

function testGlobal() {
    // echo $globalVar;  // This would cause an error
    
    // To use a global variable inside a function, use the global keyword
    global $globalVar;
    echo $globalVar . "<br>";  // Now this works
    
    // Alternatively, use the $GLOBALS superglobal array
    echo $GLOBALS['globalVar'] . "<br>";  // This also works
}

testGlobal();
?>

Static Variables

Static variables retain their value between function calls.

<?php
function countCalls() {
    // Normal local variable - resets each time the function is called
    $normalCount = 1;
    
    // Static variable - keeps its value between function calls
    static $staticCount = 0;
    $staticCount++;
    
    echo "Normal count: $normalCount, Static count: $staticCount <br>";
}

countCalls();  // Outputs: Normal count: 1, Static count: 1
countCalls();  // Outputs: Normal count: 1, Static count: 2
countCalls();  // Outputs: Normal count: 1, Static count: 3
?>

Superglobal Variables

PHP provides several predefined variables called "superglobals" that are always available in all scopes.

<?php
// Superglobals can be accessed anywhere, including inside functions
function checkSuperglobals() {
    echo "Server name: " . $_SERVER['SERVER_NAME'] . "<br>";
    echo "PHP version: " . $_SERVER['PHP_SELF'] . "<br>";
    
    if (isset($_GET['name'])) {
        echo "Name from URL: " . $_GET['name'] . "<br>";
    }
    
    if (isset($_POST['email'])) {
        echo "Email from form: " . $_POST['email'] . "<br>";
    }
}

checkSuperglobals();
?>

Common superglobals include:

  • $_GET - Contains variables passed via URL parameters
  • $_POST - Contains variables passed via HTTP POST method
  • $_SESSION - Contains variables stored in the session
  • $_COOKIE - Contains variables passed via HTTP cookies
  • $_SERVER - Contains server and execution environment info
  • $_FILES - Contains info about uploaded files
  • $_REQUEST - Contains data from $_GET, $_POST, and $_COOKIE
  • $_ENV - Contains environment variables
  • $GLOBALS - Contains all global variables
Diagram
> C[Global Scope] A > E[Superglobals] B > C1["Available throughout script but must use 'global' keyword in functions"] D PHP Variable Scope Local Scope Global Scope Static Variables Superglobals Limited to function where declared Available throughout script but must use 'global' keyword in functions Retain value between function calls Available in all scopes without declaration

Variable Variables

PHP supports a feature called "variable variables" where the value of one variable can be used as the name of another variable.

<?php
// Basic variable
$name = "John";

// Variable variable - using the value of $name as a variable name
$varName = "name";
$$varName = "David";  // This is effectively the same as $name = "David"

echo $name . "<br>";     // Outputs: David
echo $$varName . "<br>";  // Also outputs: David
?>

This advanced feature is useful in some dynamic programming scenarios but should be used with caution as it can make code harder to understand and debug.

Scalar Data Types

Scalar types represent single values. PHP has four scalar data types: integers, floats, strings, and booleans.

Integers

Integers are whole numbers without decimal points. They can be positive or negative.

<?php
// Integer declarations
$positiveInt = 42;
$negativeInt = -17;
$zeroInt = 0;

// Integer can be specified in different bases
$decimalInt = 1234;        // Decimal (base 10)
$octalInt = 0777;          // Octal (base 8) - starts with 0
$hexadecimalInt = 0xFF;    // Hexadecimal (base 16) - starts with 0x
$binaryInt = 0b1010;       // Binary (base 2) - starts with 0b

// Integer size depends on platform (32-bit or 64-bit)
echo "Maximum integer value: " . PHP_INT_MAX . "<br>";
echo "Minimum integer value: " . PHP_INT_MIN . "<br>";

// Check if a value is an integer
$checkValue = 123;
var_dump(is_int($checkValue));  // Outputs: bool(true)

// Integer overflow - exceeding PHP_INT_MAX will convert to float
$bigNumber = PHP_INT_MAX + 1;
var_dump($bigNumber);  // Will show as float on 32-bit systems
?>

Floats (Doubles)

Floats (also called doubles) are numbers with decimal points or numbers in exponential form.

<?php
// Float declarations
$simpleFloat = 3.14;
$negativeFloat = -2.718;
$scientificNotation = 1.2e3;  // 1.2 × 10³ = 1200

// Float precision issues
$precisionIssue = 0.1 + 0.2;
echo $precisionIssue . "<br>";  // Might output something like 0.30000000000000004

// Comparing floats safely
$a = 1.23;
$b = 1.23000001;

// Direct comparison can be problematic
var_dump($a == $b);  // Might be true or false depending on precision

// Better to use a small epsilon value for comparison
$epsilon = 0.00001;
var_dump(abs($a - $b) < $epsilon);  // More reliable comparison

// Check if a value is a float
var_dump(is_float(3.14));  // Outputs: bool(true)
?>

Float Precision Warning

Floats in PHP (and most programming languages) have limited precision. Never rely on exact float comparisons, especially for financial calculations. Consider using dedicated libraries like BCMath for precise decimal math.

Strings

Strings are sequences of characters. PHP offers several ways to create and manipulate strings.

<?php
// String declarations
$singleQuoted = 'This is a single-quoted string';
$doubleQuoted = "This is a double-quoted string";

// String with variable interpolation
$name = "John";
$greeting = "Hello, $name!";  // Variable is expanded in double quotes
echo $greeting . "<br>";  // Outputs: Hello, John!

$greeting2 = 'Hello, $name!';  // No variable expansion in single quotes
echo $greeting2 . "<br>";  // Outputs: Hello, $name!

// Escaping characters
$escapedSingle = 'It\'s a nice day';  // Escaping a single quote in single-quoted string
$escapedDouble = "She said, \"Hello!\"";  // Escaping double quotes in double-quoted string

// Special escape sequences (work only in double quotes)
$withNewline = "First line
Second line";  // 
 is a newline
$withTab = "Column1	Column2";  // 	 is a tab
echo nl2br($withNewline) . "<br>";  // nl2br converts 
 to HTML break tags

// Heredoc syntax (works like double quotes)
$heredocString = <<<EOT
This is a heredoc string.
It can span multiple lines.
Variables like $name are expanded.
EOT;

// Nowdoc syntax (works like single quotes)
$nowdocString = <<<'EOD'
This is a nowdoc string.
It can also span multiple lines.
But variables like $name are not expanded.
EOD;

// String concatenation
$firstName = "John";
$lastName = "Doe";
$fullName = $firstName . " " . $lastName;  // Using the dot operator

// String functions
echo strlen($fullName) . "<br>";  // String length: 8
echo strtoupper($fullName) . "<br>";  // Converts to uppercase: JOHN DOE
echo substr($fullName, 0, 4) . "<br>";  // Extracts first 4 characters: John
echo str_replace("John", "Jane", $fullName) . "<br>";  // Replaces text: Jane Doe

// Check if a value is a string
var_dump(is_string("Hello"));  // Outputs: bool(true)
?>

Booleans

Booleans represent truth values: they can be either true or false.

<?php
// Boolean declarations
$isTrue = true;   // Note: true and false are case-insensitive
$isFalse = false; // (TRUE, True, FALSE, False are all valid)

// Boolean type casting
echo "true cast to int: " . (int)true . "<br>";   // Outputs: 1
echo "false cast to int: " . (int)false . "<br>";  // Outputs: 0
echo "true cast to string: " . (string)true . "<br>";   // Outputs: 1
echo "false cast to string: " . (string)false . "<br>";  // Outputs: "" (empty string)

// Expressions that evaluate to boolean
$boolResult1 = 5 > 3;   // true
$boolResult2 = 10 === "10";  // false (strict comparison, different types)
$boolResult3 = 10 == "10";   // true (loose comparison, converts types)

// Check if a value is a boolean
var_dump(is_bool(true));  // Outputs: bool(true)

// Values considered false in conditional contexts:
// - The boolean false itself
// - The integer 0
// - The float 0.0
// - The empty string "" and the string "0"
// - An array with zero elements
// - The special NULL value
// All other values are considered true

// Examples
if (0) {
    echo "This won't be printed.<br>";
}

if ("0") {
    echo "This won't be printed either.<br>";
}

if ("") {
    echo "Nor will this.<br>";
}

if (1) {
    echo "This will be printed.<br>";
}

if ("any non-empty string except 0") {
    echo "This will also be printed.<br>";
}
?>
PHP Scalar Data Types Integer Whole numbers $age = 25; $hex = 0x1A; $bin = 0b1010; Range depends on system (32/64-bit) Float Decimal numbers $price = 9.99; $sci = 1.2e3; Limited precision Use BCMath for financial calculations String Text data 'Single quotes' "Double quotes" Heredoc <<<EOT Nowdoc <<<'EOD' Binary safe Boolean Truth values $active = true; $deleted = false; true = 1 false = 0 Case-insensitive

Compound Data Types

Compound types can store multiple values in a single variable. PHP has two main compound types: arrays and objects.

Arrays

Arrays in PHP are ordered maps that can associate values with keys. PHP arrays are incredibly versatile and can be used as simple lists, dictionaries, stacks, queues, and more.

Indexed Arrays

Indexed arrays use numeric keys, usually starting from 0.

<?php
// Creating indexed arrays
$fruits = ["apple", "banana", "cherry"];  // Short array syntax (PHP 5.4+)
$vegetables = array("carrot", "broccoli", "spinach");  // Traditional syntax

// Accessing elements
echo $fruits[0] . "<br>";  // Outputs: apple
echo $vegetables[1] . "<br>";  // Outputs: broccoli

// Adding elements to the end
$fruits[] = "orange";  // Adds "orange" to the end of $fruits

// Counting elements
echo count($fruits) . "<br>";  // Outputs: 4

// Looping through an indexed array
foreach ($fruits as $fruit) {
    echo $fruit . " ";
}
// Outputs: apple banana cherry orange

// Loop with index
foreach ($fruits as $index => $fruit) {
    echo "$index: $fruit<br>";
}
// Outputs:
// 0: apple
// 1: banana
// 2: cherry
// 3: orange
?>

Associative Arrays

Associative arrays use named keys instead of numeric indices.

<?php
// Creating associative arrays
$person = [
    "name" => "John Doe",
    "age" => 30,
    "email" => "john@example.com"
];

// Alternative syntax
$car = array(
    "make" => "Toyota",
    "model" => "Corolla",
    "year" => 2020
);

// Accessing elements
echo $person["name"] . "<br>";  // Outputs: John Doe
echo $car["model"] . "<br>";  // Outputs: Corolla

// Adding or modifying elements
$person["phone"] = "555-1234";  // Adds a new element
$car["year"] = 2021;  // Modifies an existing element

// Looping through an associative array
foreach ($person as $key => $value) {
    echo "$key: $value<br>";
}
// Outputs:
// name: John Doe
// age: 30
// email: john@example.com
// phone: 555-1234
?>

Multidimensional Arrays

Arrays can contain other arrays, creating multidimensional structures.

<?php
// Two-dimensional array
$contacts = [
    [
        "name" => "John Doe",
        "email" => "john@example.com",
        "phone" => "555-1234"
    ],
    [
        "name" => "Jane Smith",
        "email" => "jane@example.com",
        "phone" => "555-5678"
    ]
];

// Accessing elements
echo $contacts[0]["name"] . "<br>";  // Outputs: John Doe
echo $contacts[1]["email"] . "<br>";  // Outputs: jane@example.com

// More complex multidimensional array
$store = [
    "products" => [
        "electronics" => [
            ["id" => 1, "name" => "TV", "price" => 499.99],
            ["id" => 2, "name" => "Laptop", "price" => 899.99]
        ],
        "clothing" => [
            ["id" => 3, "name" => "T-Shirt", "price" => 19.99],
            ["id" => 4, "name" => "Jeans", "price" => 59.99]
        ]
    ],
    "locations" => [
        "New York" => ["address" => "123 Broadway", "phone" => "212-555-1234"],
        "Los Angeles" => ["address" => "456 Hollywood Blvd", "phone" => "213-555-5678"]
    ]
];

// Accessing deeply nested elements
echo $store["products"]["electronics"][1]["name"] . "<br>";  // Outputs: Laptop
echo $store["locations"]["New York"]["phone"] . "<br>";  // Outputs: 212-555-1234

// Looping through multidimensional arrays
foreach ($contacts as $contact) {
    echo "Name: " . $contact["name"] . ", Email: " . $contact["email"] . "<br>";
}

// More complex loops
foreach ($store["products"] as $category => $items) {
    echo "Category: $category<br>";
    foreach ($items as $item) {
        echo "- " . $item["name"] . ": $" . $item["price"] . "<br>";
    }
}
?>

Array Functions

PHP provides a rich set of functions for working with arrays.

<?php
$numbers = [5, 3, 8, 1, 9, 4];

// Sorting
sort($numbers);  // Sorts in ascending order
print_r($numbers);  // Outputs: Array ( [0] => 1 [1] => 3 [2] => 4 [3] => 5 [4] => 8 [5] => 9 )

$fruits = ["apple" => "red", "banana" => "yellow", "grape" => "purple"];

// Sorting associative arrays
asort($fruits);  // Sorts by value, maintains key association
print_r($fruits);

ksort($fruits);  // Sorts by key
print_r($fruits);

// Array operations
$a = [1, 2, 3];
$b = [4, 5, 6];
$merged = array_merge($a, $b);  // Combines arrays
print_r($merged);  // Outputs: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 )

$diff = array_diff($merged, $a);  // Returns elements in first array not in second
print_r($diff);  // Outputs: Array ( [3] => 4 [4] => 5 [5] => 6 )

$slice = array_slice($merged, 2, 3);  // Extract a portion of an array
print_r($slice);  // Outputs: Array ( [0] => 3 [1] => 4 [2] => 5 )

// Checking for elements
$search = "apple";
$inArray = in_array($search, $fruits);  // Checks if value exists
$keyExists = array_key_exists($search, $fruits);  // Checks if key exists

// Filtering arrays
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$evens = array_filter($numbers, function($n) {
    return $n % 2 === 0;
});
print_r($evens);  // Outputs even numbers only

// Transforming arrays
$squared = array_map(function($n) {
    return $n * $n;
}, $numbers);
print_r($squared);  // Outputs squared numbers

// Reducing arrays to a single value
$sum = array_reduce($numbers, function($carry, $item) {
    return $carry + $item;
}, 0);
echo "Sum: $sum<br>";  // Outputs: Sum: 55
?>

Analogy: Think of arrays as organized storage containers. An indexed array is like a set of numbered mailboxes where you access contents by box number. An associative array is like a filing cabinet where folders are labeled with names instead of numbers. A multidimensional array is like a building with floors, rooms, and cabinets - you need multiple coordinates to find what you're looking for.

Objects

Objects in PHP are instances of classes, which define properties (variables) and methods (functions) that operate on those properties.

<?php
// Defining a simple class
class Person {
    // Properties
    public $name;
    public $age;
    
    // Constructor - automatically called when creating a new instance
    public function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
    
    // Method
    public function greet() {
        return "Hello, my name is {$this->name} and I am {$this->age} years old.";
    }
    
    // Method with parameters
    public function birthday() {
        $this->age++;
        return "Happy Birthday! Now I'm {$this->age}.";
    }
}

// Creating an object
$person1 = new Person("John", 30);
$person2 = new Person("Jane", 25);

// Accessing properties
echo $person1->name . "<br>";  // Outputs: John
echo $person2->age . "<br>";   // Outputs: 25

// Calling methods
echo $person1->greet() . "<br>";  // Outputs: Hello, my name is John and I am 30 years old.
echo $person2->birthday() . "<br>";  // Outputs: Happy Birthday! Now I'm 26.

// Check if a variable is an object
var_dump(is_object($person1));  // Outputs: bool(true)

// Get the class of an object
echo get_class($person1) . "<br>";  // Outputs: Person
?>

We'll explore object-oriented programming in PHP in more detail in later sessions. For now, understand that objects provide a way to bundle data and functionality together into reusable components.

Special Data Types

PHP has two special data types that don't fit neatly into the scalar or compound categories: NULL and resource.

NULL

NULL represents a variable with no value. A variable is NULL if:

  • It has been assigned the constant NULL
  • It has not been set to any value yet
  • It has been unset()
<?php
// Variables with NULL value
$var1 = NULL;  // Explicitly set to NULL
$var2;         // Implicitly NULL (uninitialized variable)

var_dump($var1);  // Outputs: NULL
var_dump($var2);  // Outputs: NULL

// Checking for NULL
if (is_null($var1)) {
    echo "Variable is NULL<br>";
}

// Alternative check using === operator
if ($var1 === NULL) {
    echo "Variable is NULL<br>";
}

// Converting to NULL using unset()
$var3 = "Hello";
unset($var3);
// var_dump($var3);  // This would cause an error because $var3 no longer exists

// Nullish coalescing operator (PHP 7+)
$username = $_GET['user'] ?? 'Guest';  // If $_GET['user'] is not set or is NULL, use 'Guest'
echo "Welcome, $username<br>";
?>

Analogy: NULL is like an empty plot of land. It exists as a location in memory, but nothing has been built on it yet. It's different from zero (which is a specific value) or an empty string (which still contains data - just zero characters).

Resource

A resource is a special variable that holds a reference to an external resource, such as a database connection, file handle, or image canvas.

<?php
// File resource example
$file = fopen("example.txt", "w");  // Open file for writing
var_dump($file);  // Outputs: resource(5) of type (stream)

// Writing to the file
fwrite($file, "Hello, World!");

// Close the resource when done
fclose($file);

// Database resource example (using MySQLi)
$conn = mysqli_connect("localhost", "username", "password", "database");
var_dump($conn);  // Outputs something like: object(mysqli)#1

// Check if variable is a resource
$file2 = fopen("example.txt", "r");
if (is_resource($file2)) {
    echo "This is a valid resource<br>";
    fclose($file2);
}

// Note: As of PHP 8, many resources have been converted to objects
// For example, MySQLi connections were resources in older PHP versions
// but are now objects
?>

Resources are typically created by special functions and need to be properly managed. Most resource types provide a specific function to close or free the resource when you're done with it.

Resource Management

Always close or free resources when you're finished using them. Failing to do so can lead to memory leaks or locked files, especially in long-running scripts or applications.

Type Juggling and Type Casting

PHP is a loosely typed language, which means variables can change types automatically depending on context. This feature is called type juggling or type coercion.

Automatic Type Juggling

PHP will automatically convert values from one type to another when needed.

<?php
// String and number in a mathematical operation
$result = "10" + 5;  // "10" is converted to the integer 10
echo $result . "<br>";  // Outputs: 15

// Boolean in a string operation
$greeting = "Hello, " . true;  // true is converted to the string "1"
echo $greeting . "<br>";  // Outputs: Hello, 1

// Numeric strings compared as numbers
$comparison = "10" == 10;  // Automatic conversion for comparison
var_dump($comparison);  // Outputs: bool(true)

// But strict comparison checks type too
$strictComparison = "10" === 10;  // No conversion with strict comparison
var_dump($strictComparison);  // Outputs: bool(false)
?>

Explicit Type Casting

You can force a value to be converted to a specific type using type casting.

<?php
// Type casting examples
$strNumber = "42";

// Cast to integer
$intNumber = (int)$strNumber;  // or intval($strNumber)
var_dump($intNumber);  // Outputs: int(42)

// Cast to float
$floatNumber = (float)$strNumber;  // or floatval($strNumber)
var_dump($floatNumber);  // Outputs: float(42)

// Cast to boolean
$boolValue = (bool)$strNumber;  // or boolval($strNumber)
var_dump($boolValue);  // Outputs: bool(true) (any non-zero/non-empty value is true)

// Cast to string
$intValue = 123;
$strValue = (string)$intValue;  // or strval($intValue)
var_dump($strValue);  // Outputs: string(3) "123"

// Cast to array
$scalar = "hello";
$arrayValue = (array)$scalar;
var_dump($arrayValue);  // Outputs: array(1) { [0]=> string(5) "hello" }

// Cast to object
$assocArray = ["name" => "John", "age" => 30];
$objValue = (object)$assocArray;
var_dump($objValue);  // Outputs: object(stdClass)#1 (2) { ["name"]=> string(4) "John" ["age"]=> int(30) }
?>

Type Casting Rules

When PHP converts between types, it follows specific rules:

To Integer

  • Booleans: true becomes 1, false becomes 0
  • Floats: rounded toward zero (e.g., 3.7 becomes 3)
  • Strings: parsed until non-numeric character (e.g., "42abc" becomes 42)
  • Empty strings become 0
  • Arrays: empty array becomes 0, non-empty array becomes 1
  • NULL becomes 0

To Float

  • Booleans: true becomes 1.0, false becomes 0.0
  • Integers: converted directly (e.g., 3 becomes 3.0)
  • Strings: parsed until non-numeric character (e.g., "3.14abc" becomes 3.14)
  • Arrays: similar to integer conversion
  • NULL becomes 0.0

To String

  • Booleans: true becomes "1", false becomes "" (empty string)
  • Integers and Floats: converted to their string representation
  • Arrays: converted to the string "Array"
  • NULL becomes an empty string
  • Objects: becomes "Object" unless the class implements __toString()

To Boolean

  • Integers and Floats: 0 and 0.0 become false, all others become true
  • Strings: empty string and "0" become false, all others become true
  • Arrays: empty array becomes false, non-empty array becomes true
  • NULL becomes false
Diagram
> C[Explicit Type Casting] B > E[Automatic Type Conversion] C > G[Type Conversion Functions] F PHP Types Automatic Type Juggling Explicit Type Casting Loose Comparisons == Automatic Type Conversion Type Casting Syntax Type Conversion Functions (int), (float), (string), (bool), etc. intval(), floatval(), strval(), boolval(), etc.

Type Safety Considerations

While PHP's type juggling offers flexibility, it can also lead to subtle bugs. Here are some tips for safer code:

<?php
// Use strict comparison operators when type matters
$value1 = 0;
$value2 = "0";

// Loose comparison (== and !=) only check value
var_dump($value1 == $value2);   // Outputs: bool(true)

// Strict comparison (=== and !==) check value AND type
var_dump($value1 === $value2);  // Outputs: bool(false)

// Validate user input carefully
$userId = $_GET['id'] ?? '';

// Dangerous approach - could lead to SQL injection
// $query = "SELECT * FROM users WHERE id = $userId";

// Better approach - force integer type
$userId = (int)$userId;
$query = "SELECT * FROM users WHERE id = $userId";

// Or better yet, use prepared statements
// $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
// $stmt->execute([$userId]);

// Be explicit about types when necessary
function addNumbers(int $a, int $b): int {
    return $a + $b;
}

// This works fine
echo addNumbers(5, 10) . "<br>";  // Outputs: 15

// This also works, with automatic type conversion
echo addNumbers("5", "10") . "<br>";  // Outputs: 15

// PHP 7+ allows for more strict typing
declare(strict_types=1);  // Must be the first statement in the file

function strictAdd(int $a, int $b): int {
    return $a + $b;
}

// With strict_types=1, this would cause a TypeError
// echo strictAdd("5", "10");
?>

Practical Applications in WordPress

Let's explore how variables and data types are used in real-world WordPress development.

WordPress Post Data

WordPress stores post data in a combination of scalar and compound types. Here's how you might work with post data:

<?php
// Get a WordPress post
$post_id = 123;
$post = get_post($post_id);

// $post is an object with various properties
echo $post->post_title . "<br>";   // String: Title of the post
echo $post->post_content . "<br>";  // String: Content of the post
echo $post->post_status . "<br>";   // String: publish, draft, etc.
echo $post->post_type . "<br>";     // String: post, page, etc.
echo $post->post_date . "<br>";     // String: post date in Y-m-d H:i:s format

// Get post meta (custom fields)
$views_count = get_post_meta($post_id, 'views_count', true);  // Returns string or array
$views_count = (int)$views_count;  // Cast to integer for calculation
$views_count++;
update_post_meta($post_id, 'views_count', $views_count);

// Get post categories (returns array of term objects)
$categories = wp_get_post_categories($post_id, ['fields' => 'all']);
foreach ($categories as $category) {
    echo "Category: " . $category->name . "<br>";
}

// Get post tags (returns array of term objects)
$tags = wp_get_post_tags($post_id);
if (!empty($tags)) {
    echo "Tags: ";
    foreach ($tags as $tag) {
        echo $tag->name . ", ";
    }
    echo "<br>";
}
?>

WordPress Options API

WordPress stores site-wide settings in the options table, handling various data types automatically:

<?php
// Store different types of data
update_option('site_name', 'My WordPress Site');  // String
update_option('show_avatars', true);  // Boolean
update_option('posts_per_page', 10);  // Integer
update_option('featured_posts', [1, 2, 3, 4, 5]);  // Array

// Retrieve the options (WordPress automatically handles serialization/deserialization)
$site_name = get_option('site_name');  // Returns "My WordPress Site"
$show_avatars = get_option('show_avatars');  // Returns true (boolean)
$posts_per_page = get_option('posts_per_page');  // Returns 10 (integer)
$featured_posts = get_option('featured_posts');  // Returns array([0] => 1, [1] => 2, ...)

// Default values if option doesn't exist
$custom_option = get_option('custom_option', 'default value');
?>

WordPress Theme Customizer

Theme customizers often work with different data types:

<?php
// In a theme's functions.php or customizer file

// Add setting with various data types
$wp_customize->add_setting('header_text', [
    'default' => 'Welcome to our site',  // String default
    'sanitize_callback' => 'sanitize_text_field',
]);

$wp_customize->add_setting('show_search', [
    'default' => true,  // Boolean default
    'sanitize_callback' => 'rest_sanitize_boolean',
]);

$wp_customize->add_setting('footer_columns', [
    'default' => 3,  // Integer default
    'sanitize_callback' => 'absint',
]);

$wp_customize->add_setting('header_colors', [
    'default' => [  // Array default
        'background' => '#ffffff',
        'text' => '#000000',
    ],
    'sanitize_callback' => 'sanitize_header_colors',
]);

// Retrieving the settings in a template
$header_text = get_theme_mod('header_text', 'Welcome to our site');
$show_search = get_theme_mod('show_search', true);
$footer_columns = get_theme_mod('footer_columns', 3);
$header_colors = get_theme_mod('header_colors', ['background' => '#ffffff', 'text' => '#000000']);
?>

WordPress Custom API Responses

When building custom REST API endpoints in WordPress, you'll work with various data types:

<?php
// Register a custom REST API endpoint
add_action('rest_api_init', function () {
    register_rest_route('my-plugin/v1', '/stats/', [
        'methods' => 'GET',
        'callback' => 'get_site_stats',
        'permission_callback' => function () {
            return current_user_can('edit_posts');
        },
    ]);
});

// Callback function returns various data types as an array
function get_site_stats() {
    // Return various data types that will be converted to JSON
    return [
        'site_name' => get_bloginfo('name'),  // String
        'post_count' => (int)wp_count_posts()->publish,  // Integer
        'is_multilingual' => has_filter('locale'),  // Boolean
        'recent_posts' => get_recent_posts_data(),  // Array of objects
        'post_types' => get_post_types(['public' => true], 'names'),  // Array of strings
        'last_updated' => date('Y-m-d H:i:s'),  // String (date format)
    ];
}

// Helper function that creates an array of post objects
function get_recent_posts_data() {
    $posts = get_posts(['numberposts' => 5]);
    $result = [];
    
    foreach ($posts as $post) {
        $result[] = [
            'id' => $post->ID,
            'title' => $post->post_title,
            'url' => get_permalink($post->ID),
            'date' => $post->post_date,
        ];
    }
    
    return $result;
}
?>

Best Practices for PHP Variables and Types

Let's wrap up with some best practices for working with variables and types in PHP.

Naming and Style

  • Be Consistent: Choose a naming convention (camelCase or snake_case) and stick with it
  • Be Descriptive: Use meaningful variable names that describe the stored value
  • Avoid Abbreviations: Unless they're extremely common ($id, $url), spell out names
  • Prefix Special Types: Consider prefixes for certain types (e.g., $is_ for booleans)
  • Follow Framework Conventions: If using WordPress, follow its conventions (snake_case)
<?php
// Good naming in WordPress context
$post_id = get_the_ID();
$is_published = ($post->post_status === 'publish');
$comment_count = get_comments_number();
$user_meta = get_user_meta($user_id);

// Poor naming
$x = get_the_ID();  // Not descriptive
$flag = ($post->post_status === 'publish');  // Unclear what the boolean represents
$cc = get_comments_number();  // Unclear abbreviation
$data = get_user_meta($user_id);  // Too generic
?>

Type Safety

  • Use Strict Comparisons: Prefer === and !== over == and != when possible
  • Validate Input: Always validate and sanitize external data
  • Be Explicit: Use explicit type casting when the type is important
  • Consider Type Declarations: Use parameter and return type declarations (PHP 7+)
  • Document Types: Use PHPDoc comments to document expected types
<?php
/**
 * Calculate the total price including tax.
 *
 * @param float $price      The base price.
 * @param float $tax_rate   The tax rate (e.g., 0.08 for 8%).
 * @param bool  $round      Whether to round the result to 2 decimal places.
 * @return float The total price with tax.
 */
function calculate_total_price(float $price, float $tax_rate, bool $round = true): float {
    $total = $price * (1 + $tax_rate);
    
    if ($round) {
        $total = round($total, 2);
    }
    
    return $total;
}

// Using the function
$item_price = 19.99;
$tax_rate = 0.08;
$total = calculate_total_price($item_price, $tax_rate);
echo "Total with tax: $" . number_format($total, 2) . "<br>";
?>

Array Handling

  • Check Existence: Use array_key_exists() or isset() before accessing array elements
  • Provide Defaults: Use the null coalescing operator (??) or a default value
  • Use Array Functions: Leverage PHP's built-in array functions for manipulation
  • Avoid array_push(): For single elements, $array[] = $item is faster
  • Consider Specialized Collections: For complex data, consider custom classes over arrays
<?php
// Getting values safely
$user_data = [
    'name' => 'John Doe',
    'email' => 'john@example.com',
];

// Bad - might cause "Undefined array key" notice
// $phone = $user_data['phone'];

// Good - check if key exists
if (array_key_exists('phone', $user_data)) {
    $phone = $user_data['phone'];
} else {
    $phone = 'Not provided';
}

// Better - use null coalescing operator (PHP 7+)
$phone = $user_data['phone'] ?? 'Not provided';

// Working with multidimensional arrays safely
$settings = [
    'display' => [
        'theme' => 'dark',
    ],
];

// Bad - might cause error if keys don't exist
// $font_size = $settings['display']['font']['size'];

// Good - nested null coalescing
$font_size = $settings['display']['font']['size'] ?? 12;

// Alternative approach with optional chaining (PHP 8+)
// $font_size = $settings['display']['font']['size'] ?? 12;
?>

Memory Management

  • Unset Unused Variables: Free memory for large variables when no longer needed
  • Use References for Large Data: Pass by reference to avoid copying large arrays
  • Close Resources: Always close file handles, database connections, etc.
  • Be Careful with Circular References: These can prevent garbage collection
<?php
// Processing a large file line by line
$file = fopen('large_log_file.txt', 'r');
if ($file) {
    while (($line = fgets($file)) !== false) {
        // Process the line
        process_log_line($line);
    }
    
    // Close the resource when done
    fclose($file);
}

// Unset large variables when done
$large_array = get_very_large_dataset();
process_data($large_array);
unset($large_array);  // Free memory

// Pass by reference for large arrays
function process_large_array(array &$data) {
    // Modifying $data directly
    foreach ($data as &$item) {
        $item *= 2;
    }
    // Important: unset the reference after use to avoid issues
    unset($item);
}
?>

WordPress-Specific Practices

  • Use WordPress Functions: Prefer functions like absint(), sanitize_text_field(), etc.
  • Prefix Global Variables: Use a plugin/theme prefix for any global variables
  • Use WordPress Data Structures: Leverage WP_Query, WP_User, etc.
  • Sanitize User Input: Always sanitize input with appropriate WordPress functions
  • Escape Output: Use esc_html(), esc_attr(), etc. for displaying data
<?php
// Sanitizing input in WordPress
$user_input = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
$user_email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
$user_url = isset($_POST['website']) ? esc_url_raw($_POST['website']) : '';
$user_number = isset($_POST['count']) ? absint($_POST['count']) : 0;

// Escaping output in WordPress
echo '<h1>' . esc_html($post_title) . '</h1>';
echo '<a href="' . esc_url($post_url) . '" title="' . esc_attr($post_title) . '">Read more</a>';
echo '<div class="description">' . wp_kses_post($post_content) . '</div>';
?>

Practical Exercise: WordPress User Profile Data

Let's apply what we've learned with a practical exercise involving various data types in a WordPress context. We'll create a function to collect and display a user's profile data using different types of variables.

<?php
/**
 * Get and format a user's profile data.
 *
 * This function demonstrates working with various PHP data types
 * to collect and format a WordPress user's profile information.
 *
 * @param int $user_id The WordPress user ID.
 * @return array|WP_Error An array of user data or WP_Error if user doesn't exist.
 */
function get_formatted_user_profile($user_id) {
    // Validate input
    $user_id = absint($user_id);
    
    // Get user object
    $user = get_userdata($user_id);
    
    // Check if user exists
    if (!$user) {
        return new WP_Error('invalid_user', 'User does not exist');
    }
    
    // Initialize result array (associative array)
    $profile = [];
    
    // Basic user info (strings)
    $profile['display_name'] = $user->display_name;
    $profile['email'] = $user->user_email;
    $profile['website'] = esc_url($user->user_url);
    $profile['bio'] = wp_kses_post($user->description);
    
    // User registration date (string to DateTime object)
    $registration_date = new DateTime($user->user_registered);
    $profile['registered_since'] = $registration_date->format('F j, Y');
    
    // Account age in days (integer)
    $now = new DateTime();
    $interval = $registration_date->diff($now);
    $profile['account_age_days'] = (int)$interval->days;
    
    // User role (string)
    $profile['role'] = $user->roles[0] ?? 'subscriber';
    
    // User capabilities (associative array of booleans)
    $profile['capabilities'] = [];
    foreach (['edit_posts', 'publish_posts', 'manage_options', 'upload_files'] as $cap) {
        $profile['capabilities'][$cap] = user_can($user_id, $cap);
    }
    
    // Post counts (integers)
    $post_count = count_user_posts($user_id, 'post', true);
    $page_count = count_user_posts($user_id, 'page', true);
    $profile['content_stats'] = [
        'posts' => $post_count,
        'pages' => $page_count,
        'total' => $post_count + $page_count
    ];
    
    // Last login timestamp (integer or null)
    $last_login = get_user_meta($user_id, 'last_login', true);
    $profile['last_login'] = $last_login ? (int)$last_login : null;
    
    // Is account active (boolean)
    $is_active = !get_user_meta($user_id, 'inactive', true);
    $profile['is_active'] = (bool)$is_active;
    
    // Social profiles (array of strings)
    $social_profiles = [];
    foreach (['facebook', 'twitter', 'instagram', 'linkedin'] as $platform) {
        $profile_url = get_user_meta($user_id, $platform . '_profile', true);
        if ($profile_url) {
            $social_profiles[$platform] = esc_url($profile_url);
        }
    }
    $profile['social_profiles'] = $social_profiles;
    
    // Additional contact methods (array or null)
    $contact_methods = wp_get_user_contact_methods($user);
    if (!empty($contact_methods)) {
        $profile['contact_methods'] = [];
        foreach ($contact_methods as $method => $label) {
            $value = $user->get($method);
            if ($value) {
                $profile['contact_methods'][$method] = $value;
            }
        }
    } else {
        $profile['contact_methods'] = null;
    }
    
    return $profile;
}

/**
 * Display user profile information.
 *
 * @param array $profile The user profile data.
 * @return string HTML markup for the profile.
 */
function display_user_profile(array $profile): string {
    // Initialize output variable (string)
    $output = '';
    
    // Basic info section
    $output .= '<div class="user-profile">';
    $output .= '<h2>' . esc_html($profile['display_name']) . '</h2>';
    
    if (!empty($profile['bio'])) {
        $output .= '<div class="bio">' . wp_kses_post($profile['bio']) . '</div>';
    }
    
    $output .= '<ul class="user-details">';
    $output .= '<li><strong>Email:</strong> ' . esc_html($profile['email']) . '</li>';
    
    if (!empty($profile['website'])) {
        $output .= '<li><strong>Website:</strong> <a href="' . esc_url($profile['website']) . '">' . esc_html($profile['website']) . '</a></li>';
    }
    
    $output .= '<li><strong>Registered:</strong> ' . esc_html($profile['registered_since']) . ' (' . esc_html($profile['account_age_days']) . ' days)</li>';
    $output .= '<li><strong>Role:</strong> ' . esc_html(ucfirst($profile['role'])) . '</li>';
    
    // Last login info (handling null)
    if ($profile['last_login'] !== null) {
        $last_login_date = date('F j, Y g:i a', $profile['last_login']);
        $output .= '<li><strong>Last Login:</strong> ' . esc_html($last_login_date) . '</li>';
    } else {
        $output .= '<li><strong>Last Login:</strong> Never</li>';
    }
    
    // Account status (boolean displayed as text)
    $status_text = $profile['is_active'] ? 'Active' : 'Inactive';
    $status_class = $profile['is_active'] ? 'active' : 'inactive';
    $output .= '<li><strong>Status:</strong> <span class="status-' . $status-class . '">' . $status_text . '</span></li>';
    
    $output .= '</ul>';
    
    // Content stats (numeric data)
    if (!empty($profile['content_stats'])) {
        $output .= '<div class="content-stats">';
        $output .= '<h3>Content Statistics</h3>';
        $output .= '<ul>';
        $output .= '<li>Posts: ' . (int)$profile['content_stats']['posts'] . '</li>';
        $output .= '<li>Pages: ' . (int)$profile['content_stats']['pages'] . '</li>';
        $output .= '<li>Total: ' . (int)$profile['content_stats']['total'] . '</li>';
        $output .= '</ul>';
        $output .= '</div>';
    }
    
    // Capabilities (boolean data shown as Yes/No)
    if (!empty($profile['capabilities'])) {
        $output .= '<div class="capabilities">';
        $output .= '<h3>User Capabilities</h3>';
        $output .= '<ul>';
        foreach ($profile['capabilities'] as $cap => $allowed) {
            $cap_text = str_replace('_', ' ', $cap);
            $cap_value = $allowed ? 'Yes' : 'No';
            $output .= '<li>' . esc_html(ucwords($cap_text)) . ': ' . $cap_value . '</li>';
        }
        $output .= '</ul>';
        $output .= '</div>';
    }
    
    // Social profiles (array of strings)
    if (!empty($profile['social_profiles'])) {
        $output .= '<div class="social-profiles">';
        $output .= '<h3>Social Profiles</h3>';
        $output .= '<ul class="social-links">';
        foreach ($profile['social_profiles'] as $platform => $url) {
            $output .= '<li>';
            $output .= '<a href="' . esc_url($url) . '" target="_blank" rel="noopener noreferrer">';
            $output .= esc_html(ucfirst($platform));
            $output .= '</a>';
            $output .= '</li>';
        }
        $output .= '</ul>';
        $output .= '</div>';
    }
    
    // Close the main container
    $output .= '</div>';
    
    return $output;
}

// Example usage:
// $user_id = get_current_user_id();
// $profile_data = get_formatted_user_profile($user_id);
// if (!is_wp_error($profile_data)) {
//     echo display_user_profile($profile_data);
// } else {
//     echo 'Error: ' . $profile_data->get_error_message();
// }
?>

This exercise demonstrates:

  • Working with different scalar types (strings, integers, booleans)
  • Working with complex compound types (arrays, objects)
  • Handling null values and providing defaults
  • Type casting to ensure expected types
  • WordPress-specific data handling and escaping
  • Documenting types in function documentation
  • Using type declarations in function signatures (PHP 7+)

Try implementing this in your WordPress development environment and experiment with different ways to display and format the data.

Summary and Key Takeaways

We've covered a lot of ground in our exploration of PHP variables and data types. Here are the key points to remember:

  • Variables in PHP are declared using the dollar sign ($) and are dynamically typed
  • Scalar types include integers, floats, strings, and booleans
  • Compound types include arrays and objects for more complex data structures
  • Special types include NULL (absence of value) and resource (external resource handle)
  • Type juggling allows PHP to automatically convert between types as needed
  • Explicit type casting gives you control over type conversions
  • Variable scope determines where variables can be accessed (local, global, static)
  • WordPress uses a mix of data types and provides specific functions for handling them

Final Analogy: Programming with PHP's variables and types is like working with clay. The material is flexible and can be molded into different shapes (types) as needed. You can start with a simple lump (scalar type), shape it into more complex forms (compound types), or even leave it empty (NULL). What makes you a skilled potter/programmer is knowing when to use different techniques, how to shape the clay effectively, and when to let it harden into a fixed form (use strict types) for stability.

Understanding variables and data types is fundamental to PHP programming. As you continue your PHP and WordPress development journey, you'll find yourself working with these concepts every day. The flexibility of PHP's type system can be powerful, but remember to use it judiciously and follow best practices for clean, maintainable, and secure code.

Additional Resources

PHP Official Documentation

WordPress Documentation

Books and Tutorials

  • "PHP & MySQL: Novice to Ninja" by Kevin Yank and Tom Butler
  • "Modern PHP: New Features and Good Practices" by Josh Lockhart
  • "Professional WordPress Plugin Development" by Brad Williams, Justin Tadlock, and John James Jacoby

Online Courses and Tutorials