php language basics
Operators and Expressions
An expression is any piece of PHP code that produces a value. A literal such as 10 is an expression. A variable such as $priceCents is an expression. A calculation such as $priceCents * $quantity is also an expression.
Operators are the symbols and keywords that combine expressions. They are how PHP adds numbers, joins strings, compares values, chooses defaults, and builds conditions for if, while, and other control-flow code.
This matters because most everyday PHP code is built from expressions. A junior developer is often asked to change a price calculation, fix a condition, add a validation rule, or explain why a comparison behaved unexpectedly. To do that safely, you need to know what value each expression produces.
Arithmetic Expressions
Arithmetic operators work with numbers. The common ones are +, -, *, /, %, and **.
<?php
$priceCents = 1299;
$quantity = 3;
$discountCents = 500;
$subtotalCents = $priceCents * $quantity;
$totalCents = $subtotalCents - $discountCents;
echo "Subtotal: {$subtotalCents} cents\n";
echo "Total: {$totalCents} cents\n";
// Prints:
// Subtotal: 3897 cents
// Total: 3397 cents
The expression $priceCents * $quantity produces 3897. That value is then assigned to $subtotalCents. The next expression subtracts the discount and stores the result in $totalCents.
In real applications, money is often stored as integer cents to avoid floating-point rounding surprises. A later lesson can cover money modelling in more depth; for now, the important point is that the arithmetic expression should use values with a clear unit.
String Concatenation
PHP uses . to join strings. This is different from JavaScript, where + can join strings. In PHP, use . when the job is text.
<?php
$firstName = 'Ada';
$lastName = 'Lovelace';
$fullName = $firstName . ' ' . $lastName;
echo $fullName . "\n";
// Prints:
// Ada Lovelace
PHP also supports variable interpolation inside double-quoted strings, such as "Hello, $firstName". Concatenation is still useful when you are joining several pieces conditionally or building a value in steps.
Assignment And Comparison
The assignment operator = stores a value in a variable. It is not the same as comparison. This is one of the most common beginner mistakes.
<?php
$status = 'paid';
if ($status === 'paid') {
echo "Ship the order\n";
}
// Prints:
// Ship the order
Use === when you want to compare both value and type. Use = only when you want to assign.
Some compound assignment operators update a variable in place:
<?php
$stock = 10;
$stock -= 2;
$stock += 5;
echo "Stock: {$stock}\n";
// Prints:
// Stock: 13
$stock -= 2 means "take the current stock, subtract two, and store the result back in $stock." You will see this style in counters, totals, stock levels, retry counts, and pagination offsets.
Comparisons And Strict Equality
Comparison expressions produce booleans: true or false.
<?php
$submittedQuantity = '3';
$availableStock = 3;
var_dump($submittedQuantity == $availableStock);
var_dump($submittedQuantity === $availableStock);
// Prints:
// bool(true)
// bool(false)
== checks loose equality, so PHP may convert types before comparing. === checks strict equality, so both value and type must match. In application code, prefer strict comparisons unless you have a specific reason to allow conversion.
This becomes important at boundaries. Form data, query strings, and JSON payloads often arrive as strings. If your code expects an integer, validate and convert deliberately instead of relying on loose comparison.
Logical Operators
Logical operators combine boolean expressions. The most common are && for "and", || for "or", and ! for "not".
<?php
$isPaid = true;
$hasStock = true;
$isFraudCheckPassed = false;
$canShip = $isPaid && $hasStock && $isFraudCheckPassed;
var_dump($canShip);
// Prints:
// bool(false)
The order matters for readability. Put each named condition in a variable when it helps the next developer understand the rule. A long if condition with several comparisons can be correct but hard to review.
<?php
$quantity = 2;
$stock = 5;
$accountIsActive = true;
$quantityIsValid = $quantity > 0;
$stockIsAvailable = $quantity <= $stock;
if ($accountIsActive && $quantityIsValid && $stockIsAvailable) {
echo "Order accepted\n";
}
// Prints:
// Order accepted
This version is longer, but it gives each business rule a name. That is often worth it in validation, checkout, permissions, and status transitions.
Defaults With ??
The null coalescing operator ?? gives a default when a value is missing or null.
<?php
$settings = [
'currency' => 'GBP',
];
$currency = $settings['currency'] ?? 'USD';
$locale = $settings['locale'] ?? 'en_GB';
echo "{$currency} / {$locale}\n";
// Prints:
// GBP / en_GB
This is common when reading optional array keys, configuration, decoded JSON, and request data. It is not a replacement for validation. It only chooses a fallback when the value is absent or null.
Choosing Between Two Values
The ternary operator condition ? value_if_true : value_if_false is useful for short choices.
<?php
$totalCents = 7_500;
$shippingLabel = $totalCents >= 5_000 ? 'free shipping' : 'standard shipping';
echo $shippingLabel . "\n";
// Prints:
// free shipping
Use ternaries for simple choices. If the condition or either branch needs explanation, use a normal if block instead.
Precedence And Parentheses
Operator precedence decides which part of an expression PHP evaluates first. Multiplication happens before addition, so this expression may not mean what a beginner expects:
<?php
$result = 10 + 5 * 2;
echo $result . "\n";
// Prints:
// 20
Use parentheses when they make the rule clearer:
<?php
$result = (10 + 5) * 2;
echo $result . "\n";
// Prints:
// 30
Do not rely on another developer remembering every precedence rule. Parentheses are cheap and often make business logic safer to review.
Common Mistakes
The biggest mistake is confusing assignment with comparison: = stores a value, while === compares a value and type.
The second mistake is trusting loose comparisons at application boundaries. If user input arrives as a string, convert it deliberately before comparing it with an integer.
The third mistake is writing clever expressions that hide the business rule. A compact one-liner can be harder to maintain than a few named variables.
What You Should Be Able To Do
After this lesson, you should be able to:
- identify the value produced by a PHP expression;
- use arithmetic operators for simple totals and counters;
- join strings with
.; - compare values with strict equality;
- combine conditions with
&&,||, and!; - use
??for simple defaults; - use parentheses to make evaluation order clear;
- explain why a condition is true or false before running the code.
Practice
Task: Total Calculator
Task
Write a small PHP script that calculates an order total in cents.
Start with these values:
<?php
$priceCents = 1499;
$quantity = 2;
$discountCents = 300;
Calculate:
$subtotalCentsas price multiplied by quantity;$totalCentsas subtotal minus discount;- print both values.
Expected Behaviour
Your script should print this output from the runnable PHP block:
<?php
echo "Subtotal: 2998 cents\n";
echo "Total: 2698 cents\n";
// Prints:
// Subtotal: 2998 cents
// Total: 2698 cents
Hints
- Use
*for multiplication. - Use
-for subtraction. - Keep the values as integer cents.
Show solution
Solution
<?php
$priceCents = 1499;
$quantity = 2;
$discountCents = 300;
$subtotalCents = $priceCents * $quantity;
$totalCents = $subtotalCents - $discountCents;
echo "Subtotal: {$subtotalCents} cents\n";
echo "Total: {$totalCents} cents\n";
// Prints:
// Subtotal: 2998 cents
// Total: 2698 cents
Explanation
$priceCents * $quantity produces the subtotal. $subtotalCents - $discountCents produces the final total. The variables are named with Cents so the unit is visible during review.
Task: Predict Comparisons
Task
Before running the code, predict what each var_dump() will print.
<?php
$submittedQuantity = '3';
$availableStock = 3;
$minimumQuantity = 1;
var_dump($submittedQuantity == $availableStock);
var_dump($submittedQuantity === $availableStock);
var_dump((int) $submittedQuantity >= $minimumQuantity);
var_dump((int) $submittedQuantity <= $availableStock);
Then run the code and compare your prediction with the real output.
Hints
==allows type conversion.===requires the same value and the same type.(int) $submittedQuantityconverts the string before comparison.
Show solution
Solution
<?php
$submittedQuantity = '3';
$availableStock = 3;
$minimumQuantity = 1;
var_dump($submittedQuantity == $availableStock);
var_dump($submittedQuantity === $availableStock);
var_dump((int) $submittedQuantity >= $minimumQuantity);
var_dump((int) $submittedQuantity <= $availableStock);
// Prints:
// bool(true)
// bool(false)
// bool(true)
// bool(true)
Explanation
The loose comparison is true because PHP can compare the string '3' with the integer 3. The strict comparison is false because the values have different types.
The last two comparisons convert the submitted value to an integer before checking it. That makes the boundary decision visible instead of relying on loose comparison.
Task: Build Price Expression
Task
Write a PHP script that decides whether an order gets free shipping.
Use these starting values:
<?php
$order = [
'total_cents' => 6400,
'country' => 'GB',
];
$freeShippingThresholdCents = 5000;
Your script should:
- read the order total;
- read the country, defaulting to
'GB'if it is missing; - create a
$qualifiesForFreeShippingboolean; - print either
Free shippingorStandard shipping.
Hints
- Use
??for the country default. - Use
>=for the threshold comparison. - Use
&&to require both the total and country rule. - A ternary is fine for the final label.
Show solution
Solution
<?php
$order = [
'total_cents' => 6400,
'country' => 'GB',
];
$freeShippingThresholdCents = 5000;
$totalCents = $order['total_cents'];
$country = $order['country'] ?? 'GB';
$meetsTotalThreshold = $totalCents >= $freeShippingThresholdCents;
$shipsInsideFreeShippingRegion = $country === 'GB';
$qualifiesForFreeShipping = $meetsTotalThreshold && $shipsInsideFreeShippingRegion;
$shippingLabel = $qualifiesForFreeShipping ? 'Free shipping' : 'Standard shipping';
echo $shippingLabel . "\n";
// Prints:
// Free shipping
Explanation
The solution separates the expression into named conditions. $meetsTotalThreshold explains the price rule. $shipsInsideFreeShippingRegion explains the country rule. The final && expression is easier to review because each side has a name.
The ?? operator gives a default country only when the key is missing or null. In a real checkout flow, you would still validate the country before accepting the order.