Объясните мне как & $school ссылается на объект, а не на какую-то копию?
Чтобы перейти к работе с объектами, давай попробуем поработать с другими типами данных, например, с массивом.
$array = [1, 2, 3];

Здесь мы задали переменной $array значение в виде массива с числами 1, 2 и 3.
Далее создадим функцию, которая добавит в конец новый элемент со случайным значением.
$array = [1, 2, 3];
pushRandomInt($array);
function pushRandomInt($collection)
{
    $collection[] = rand(1, 1000);
}

Когда вызывается pushRandomInt, PHP копирует значение переменной и передает его в функцию. На текущий момент будут существовать 2 разных переменных, но значения у них будут идентичные ($array содержит массив из 1, 2 и 3, и $collection содержит массив из 1, 2 и 3).
Функция добавляет в конец ($collection[]) новый элемент со случайным значением (rand(1, 1000)).
Теперь значение переменной $collection будет массив из 1, 2, 3 и случайного числа в диапазоне от 1 до 1000. $array же не изменился.

Функция pushRandomInt ничего не возвращает, так что ее работа сейчас совершенно бесполезна. Чтобы сделать ее работу полезной, есть 2 способа:
1. Вернуть результат функции
function pushRandomInt($collection)
{
    $collection[] = rand(1, 1000);
    
    return $collection;
}
Этот вариант более предпочтительнее, потому что он не изменит значение переменной, которую  передали в функцию. Такую функцию называют чистой функцией. Это правило хорошего тона написания кода.

Разберем это на примере:
$array = [1, 2, 3];
$newArray = pushRandomInt($array);
var_dump($array);
var_dump($newArray);
function pushRandomInt($collection)
{
    $collection[] = rand(1, 1000);

    return $collection;
}

Результатом работы данной программы будет следующее:
array() { 0 => 1, 1 => 2, 2 => 3 }
array() { 0 => 1, 1 => 2, 2 => 3, 3 => {случайное число}}
Как видим, переменная $array не была изменена и результат работы функции pushRandomInt был присвоен в новую переменную.

2. Сделать передачу значения по ссылке
function pushRandomInt(&$collection)
{
    $collection[] = rand(1, 1000);
}
Такую функцию называют грязной функцией, потому что она имеет побочный эффект: функция изменяет значения оригинальных переменных (те, которые были переданы как аргументы функции (pushRandomInt($array);, здесь $array является аргументом функции pushRandomInt))

Разберем это на примере:
$array = [1, 2, 3];
pushRandomInt($array);
var_dump($array);
function pushRandomInt(&$collection)
{
    $collection[] = rand(1, 1000);
}
Теперь этот код выведет array() {0 => 1, 1 => 2, 2 => 3, 3 => {случайное число}}
Как видим, оригинальная переменная $array после вызова функции pushRandomInt была изменена.

---------------

С объектами в PHP работа всегда ведется с передачей значения по ссылке.

Пример:
$object = new \stdClass();
setRandomId($object);
function setRandomId($object)
{
    $object->id = rand(1, 1000);
}
echo "ID объекта: {$object->id}\n";

То есть не нужно указывать знак амперсанда, чтобы работать с объектом по ссылке. Это работает по умолчанию.
Бывает моменты, когда не нужно работать со значение объекта по ссылке. Для этого применяют клонирование объекта.

Пример:

$object = new \stdClass();
$newObject = setRandomId($object);
function setRandomId($object)
{
    $newObject = clone $object;
    $newObject->id = rand(1, 1000);

    return $newObject;
}
echo "ID объекта: {$newObject->id}\n";
echo "ID объекта: {$object->id}\n";

Результат будет следующий:
ID объекта: {случайное число}
<br />
<b>Notice</b>:  Undefined property: stdClass::$id in <b>[...][...]</b> on line <b>12</b><br />
ID объекта:

Что произошло:
Функция setRandomId принимает объект, создает его копию ($newObject) и в дальнейшем работает только с копией. У копии создается новое свойство id и присваивается случайное число.
С оригинальным объектом ($object) никаких изменений не производится, и, соответственно, свойство id у него не создается.

Надеюсь, смог донести информацию.
Скажем так, объекты всегда передаются по ссылке. Разница между с & и без & в том что без & это будет 2 разных переменных (со своими участками памяти), которые ссылаются на один объект, а с & это будет две переменных которые ссылаются на один участок памяти, который, в свою очередь, ссылается на объект.