PHP · Beginner

Variables and Types in PHP

8 min readUpdated September 24, 2026Every example verified

In short: A PHP variable is a name starting with $ that holds a value; it is created by assignment and needs no declaration. Every value has a type: int, float, string, bool, null, array or an object. Text read from input is always a string, so cast it with (int) or (float) before doing arithmetic, and compare with === when the type matters.

Variables hold values, values have types

A variable name starts with $ followed by a letter or underscore, then any mix of letters, digits and underscores. Assigning with = creates the variable; there is no separate declaration step and no fixed type. The same variable can hold a string on one line and an integer on the next. That flexibility is convenient, but it means the type of a variable is a fact about the value currently in it, not about the name, so you need to know what your values are.

PHP has four scalar types. int is a whole number, 64 bits on the platforms this site runs on, so it ranges up to PHP_INT_MAX, 9223372036854775807. float is a double-precision decimal such as 2.75; whole-number floats print without a decimal point, so echo 4.0 shows 4. string is text in quotes. bool is true or false. A fifth type, null, has the single value null and means "no value". Beyond the scalars there are arrays and objects, each with its own lesson.

var_dump($x) prints a value together with its type, which makes it the right tool when you are unsure what you are holding: int(14), float(2.75), string(5) "hello", bool(true), NULL. get_debug_type($x) (PHP 8.0) returns just the type name as a short string.

Input is where types matter first. fgets(STDIN) always returns a string. "3" * 2 still works, because PHP converts a numeric string in arithmetic, but "3" === 3 is false and "10" < "9" compares as numbers while "abc" < "abd" compares as text. Rather than rely on these rules, convert deliberately: (int) $text, (float) $text, (string) $number, (bool) $value. Casting a non-numeric string to int gives 0, and casting "3.9" to int gives 3, not 4.

Arithmetic follows the usual rules, with two PHP specifics. / returns an int when both operands are ints and the division is exact (8 / 2 is int(4)), and a float otherwise (7 / 2 is float(3.5)); intdiv(7, 2) gives the integer 3 and 7 % 2 the remainder 1. Strings are joined with ., never +. Comparison has two forms: == converts both sides to a common type first, === also requires the types to match. Since PHP 8.0 a comparison such as 0 == "abc" is false, because a non-numeric string is compared as text rather than being turned into 0.

A value you never intend to change goes in a constant: const MAX_LOAVES = 48; defines a name without $ that cannot be reassigned. Constants are conventionally uppercase.

Syntax

 PHP · syntax
$name = "Green Hill";     // string
$crates = 14;              // int
$rate = 2.75;              // float
$open = true;              // bool
$manager = null;           // null

$total = (float) $text * $crates;   // cast before arithmetic
$label = "Crates: " . $crates;      // join with a dot
var_dump($total);                    // shows type and value
const VAT = 0.2;                     // constant: no $, cannot change

Names are case-sensitive. Casting operators are (int), (float), (string), (bool) and (array).

The scalar types under var_dump

A market stall's details stored in five variables, each shown with its type.

 PHP
<?php
$stall = "Green Hill Produce";
$crates = 14;
$pricePerKilo = 2.75;
$openToday = true;
$manager = null;

var_dump($stall);
var_dump($crates);
var_dump($pricePerKilo);
var_dump($openToday);
var_dump($manager);
echo get_debug_type($crates), " ", get_debug_type($pricePerKilo), "\n";

Output

string(18) "Green Hill Produce"
int(14)
float(2.75)
bool(true)
NULL
int float

var_dump shows the type, and for strings the length in bytes as well. null is the value of a variable that has been assigned nothing meaningful; reading a variable that was never assigned at all also yields null, but with a warning. get_debug_type gives the same names as the type declarations you will later write on functions.

Input is text until you convert it

Two numbers arrive as strings; the program converts them before multiplying.

 PHP
<?php
$kilos = trim(fgets(STDIN));
$rate = trim(fgets(STDIN));
var_dump($kilos);

$total = (float) $kilos * (float) $rate;
echo "Cost: ", $total, "\n";
echo "Rounded: ", round($total, 2), "\n";
echo "Whole kilos: ", (int) $kilos, "\n";
var_dump($kilos === "3.5", $kilos == 3.5);

Input given to the program: 3.52.75

Output

string(3) "3.5"
Cost: 9.625
Rounded: 9.63
Whole kilos: 3
bool(true)
bool(true)

The first var_dump proves the point: $kilos is string(3), not a number. The casts make the multiplication explicit, and round limits the decimals. (int) "3.5" truncates to 3. The final line shows both comparison operators: === succeeds only against the identical string, while == converts the numeric string and compares it with the float. Knowing which one you mean avoids a class of subtle bugs.

Reassignment and type juggling

One variable changes type twice, and division shows when PHP returns an int or a float.

 PHP
<?php
$count = "12";
$count = $count + 3;
var_dump($count);

$label = "Boxes: " . $count;
var_dump($label);

var_dump(7 / 2);
var_dump(8 / 2);
var_dump(intdiv(7, 2), 7 % 2);
var_dump("12" == 12, "12" === 12, 0 == "abc");

Output

int(15)
string(9) "Boxes: 15"
float(3.5)
int(4)
int(3)
int(1)
bool(true)
bool(false)
bool(false)

"12" + 3 converts the numeric string and produces an int, so $count changes type on the second line. Joining it to text with . turns it back into part of a string. 7 / 2 cannot be exact, so the result is a float; 8 / 2 is exact and stays an int. The last line is the PHP 8 comparison rule in action: "12" == 12 is true, === is false because the types differ, and 0 == "abc" is false since PHP 8.0 (it was true in PHP 7).

Common mistakes

  • Comparing input to a number with ===

    Why it goes wrong: trim(fgets(STDIN)) === 5 is always false: the left side is the string "5" and === requires equal types.

    Fix: Cast the input first, then compare.

     PHP · fix
    <?php
    $choice = (int) trim(fgets(STDIN));
    if ($choice === 5) {
        echo "five\n";
    }
  • Using . when you meant + (or the reverse)

    Why it goes wrong: $a . $b with the inputs 3 and 4 gives the string "34"; $a + $b gives 7. Both run without error, so the wrong one produces a wrong answer silently.

    Fix: Use + for sums of numbers and . for joining text; cast inputs so the intent is obvious.

  • Mixing the case of a variable name

    Why it goes wrong: $Total and $total are different variables. Reading the one you never assigned gives null with a warning, and arithmetic on null gives 0.

    Fix: Pick one naming style, for example camelCase, and keep it consistent.

  • Testing floats for exact equality

    Why it goes wrong: 0.1 + 0.2 == 0.3 is false because binary floats cannot represent those decimals exactly.

    Fix: Compare rounded values, or keep money in integer cents.

     PHP · fix
    <?php
    $cents = 1050 + 275;
    echo $cents / 100, "\n";   // 13.25
    var_dump(round(0.1 + 0.2, 2) == 0.3);

Scalar types at a glance

TypeLiteralvar_dump showsCast with
int42, -7, 0int(42)(int)
float2.75, 1e3float(2.75)(float)
string"text", 'text'string(4) "text"(string)
booltrue, falsebool(true)(bool)
nullnullNULLnone; assign null

Where you use this

Every exercise begins with values arriving as strings. A price of "4.20" and a quantity of "3" need to become a float and an int before the total makes sense, and the total needs to become text again, formatted, before it is printed. Knowing which type you hold at each step is what makes number_format receive a number, strlen receive a string, and === compare what you think it compares. For money, many programs avoid floats entirely by storing cents as integers and dividing by 100 only when printing.

 PHP · in practice
$price = (float) trim(fgets(STDIN));
$qty = (int) trim(fgets(STDIN));
echo number_format($price * $qty, 2), "\n";

Key points

  • A variable is created by assigning to $name; its type is the type of its current value.
  • The scalar types are int, float, string and bool; null means no value.
  • var_dump shows type and value; get_debug_type gives the type name.
  • Input from fgets is always a string; cast with (int) or (float) before arithmetic.
  • / gives an int only when the division is exact; intdiv and % work on integers.
  • == converts before comparing; === also checks the type. Prefer ===.
  • Constants are declared with const and written without $.

Try it yourself

The program reads a unit price and a quantity but prints them unchanged. Convert them to the right types and print the total cost with exactly two decimals using number_format.

Your program
<?php
$price = trim(fgets(STDIN));
$qty = trim(fgets(STDIN));
echo $price, " ", $qty, "\n";
Input the program receives: 4.20 ↵ 3
Expected output: 12.60

Practise this

Open the PHP playground

Frequently asked questions

What is the difference between == and === in PHP?

== converts both operands to a common type and then compares values, so "12" == 12 is true. === compares value and type, so "12" === 12 is false. Since PHP 8.0, == between a number and a non-numeric string compares them as strings, which is why 0 == "abc" is now false. Use === unless you specifically want the conversion.

Why does 8 / 2 give int(4) but 7 / 2 give float(3.5)?

The division operator returns an int when both operands are ints and the result is a whole number, and a float in every other case. If you always want an integer, use intdiv($a, $b); if you always want a float, cast one operand with (float) or divide by 2.0.

Does PHP have type declarations?

Variables are not declared with a type, but function parameters, return values and class properties can be: function area(float $w, float $h): float. Those declarations are checked when the function is called. The functions lesson covers them, including declare(strict_types=1), which turns off automatic conversion for those calls.

Progress is stored only in this browser.

How this page was checked. Every program on it was run with PHP 8.4 at build time by the publishing checks, and the output shown is what it printed. Running PHP inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with PHP 8.4 locally.