PHP Manual

Апострофи та лапки

22. 08. 2019

Obsah článku

Для розділення рядків можна використовувати лапки або апострофи. Особисто я віддаю перевагу тільки **апострофам**, якщо це не спеціальний символ розриву рядка або табуляція.

На це є низка причин, давайте пройдемося по них конструктивно.

Основною причиною відмови від лапок є безпека та некоректна робота з типами даних.

Використання HTML-тегів всередині рядка

Якщо нам потрібно повернути HTML-код в рядку, а ми загортаємо рядок в лапки, то доводиться досить незручно ескейпити:

return "<a href=\"{$link}\">{$text}</a>";

Або зробити те ж саме у більш читабельному вигляді, зберігши цитати без втеч:

return '<a href="' . $link . '">' . $text . '</a>';

Більша візуальна відстань рядка від змінної

Немає нічого гіршого, ніж розміщення змінних всередині рядка безпосередньо один над одним, де ви не можете швидко візуально визначити, що є змінною, а що рядком:

$url = "{$baseImageUrl}/{$dirName}/{$basename}.{$ext}";

Така нотація не має негативного впливу на функціональність, лише окремі змінні та фіксовані символи з рядка розташовуються занадто близько один до одного, що погіршує читабельність.

Спробуємо ще раз зробити його більш читабельним:

$url = $baseImageUrl . '/' . $dirName . '/' . $basename . '.' . $ext;

Основна перевага, яку я бачу - це чистота навколо змінних, де не заважають зайві символи в назві.

Крім того, буде легше обгортати і в рядку не буде символів обгортання ;)

$url = $baseImageUrl
. '/' . $dirName
. '/' . $basename . '.' . $ext;

Неможливо викликати функцію всередині лапок

А от змінна може, саме тому "щось" додається за межами рядка (особливо функції), а змінні записуються назад всередину. А іноді програміст навіть додає змінну після рядка. Словом, плутанина через плутанину.

Чому ми не можемо робити все однаково?

Некоректне приведення іншого типу даних до рядка

Розглянемо наступний виклик функції:

echo getFullName("{$user->name}");
function getFullName(string $name): string
{
// ... впровадження ...
}

Є можливість вставляти змінні в лапки, що призведе до їх перезапису у вигляді рядка. Однак, якщо змінна знаходиться в самому рядку і має тип даних, відмінний від рядка, то інформація про початковий тип даних може бути пошкоджена. Наприклад, якщо конструкція $user->name поверне false або null, ми не зможемо сказати, що це була помилка.

Програма завжди повинна розпізнавати стан помилки та належним чином виходити з ладу, а не ігнорувати його. Належна звітність про помилки призводить до кращого налагодження в майбутньому.

Іноді ви можете зіткнутися з перевизначеннями, особливо якщо функція вимагає певного типу даних:

trim("{$returnText}");

В такому випадку я більш схильний це записати:

trim ((string) $returnText);

яка не є такою "магічною" і навіть для менш досвідчених користувачів очевидно, що сталося зі змінною.

Видалення значення null з бази даних

Припустимо, ми отримуємо назву готелю з бази даних:

return "{$row->hotel->name}";

Але що робити, якщо імені не існує і воно є "нульовим"? Використовуючи лапки, ми створили потенційно важко виявлену помилку, оскільки вона буде переписана в порожній рядок. Однак ми хотіли б повернути реальний "нуль". Має значення, якщо запис не існує, або існує, але не заповнений.

Тому правильніше було б нічого не вказувати:

return $row->hotel->name;

Чи вимагає функція повернення певного типу даних і чи є вона суворою щодо цього? Якщо ми не можемо задовольнити специфікацію, ми повинні зробити виняток.

function getHotelName(int $hotelId): string
{
// імплементація
if ($row->hotel->name === null) {
throw new \Exception('Назва готелю не існує.');
}
return $row->hotel->name;
}

Неузгодженість кодування символів і типів даних

Нерідко можна зустріти конструкції на кшталт:

echo "{$returnCode}" . self::CRLF;

Що краще написати як:

echo $returnCode . "\n";

Використання лапок навколо змінної в даному випадку є зайвим і лише ускладнює читання, оскільки є зайвими символами. В той же час, обгортка рядка типу CRLF не є сучасною і краще використовувати тільки \n, яка є рідною для кодування UTF-8.

Насправді, ми все ще можемо перевірити тип даних для коду. Наприклад, що це номер і, можливо, повернути заміну. Це можна зробити за допомогою термінального оператора:

echo (is_int($returnCode) ? $returnCode : '?') . "\n";

Примітка: Використання функції is_int() свідчить про погане проектування програми, тому що ніколи не повинно статися так, що ми не знаємо тип даних змінної.

Обертання виведеного рядка в апострофи

Часто в тексті виключення виникає необхідність заключити рядок виводу зі змінної в лапки або апострофи. Однак, це невиправдано створює "виграш" для обох типів роздільників рядків, і якщо рядок починається і закінчується одним і тим же символом, неможливо швидко визначити однозначно, де рядок починався і закінчувався у випадку декількох рядків, якщо всередині з'являється апостроф:

throw new \Exception(__METHOD__ . ": Unsupported data type '{$fileType}'");

Особисто я вирішую цю проблему, укладаючи його в інший тип символів (мені добре підходять квадратні дужки), так що початок і кінець рядка можна елегантно побачити:

throw new \Exception(__METHOD__ . ': Непідтримуваний тип даних [' . $fileType . ']');

Або:

throw new \Exception("Status '{$status}' is invalid");

Можливий обмін на:

throw new \Exception('Статус [' . $status . '] є недійсним');

Парсинг по рядках

Лапки корисні, наприклад, для розбору з нового рядка:

foreach(explode("\n", $text) as $line) {
// імплементація
}

Вони були спеціально створені для цієї мети.

Однак, якщо вам потрібно обробити більш складний документ (наприклад, вихідний код мови програмування або HTML-сторінку), рекомендую використовувати Tokenizer разом з регулярними виразами.

Не поєднувати два способи огородження

Якщо з якихось причин ви все одно збираєтесь використовувати лапки, принаймні, дотримуйтесь їх послідовності в усьому тексті.

Це стримуючий випадок:

throw new \Exception("Зображення за URL-адресою не існує. ResponseSize:" . strlen($result) . ')');

Де початок рядка виділяється лапками, а кінець - апострофами.

Цей дефект виникає особливо при використанні інструментів автоматичного форматування (таких як Code Sniffer), які намагаються уніфікувати конвенції, але не завжди досягають успіху.

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.
4.
Status:
All systems normal.
2024