Створений щоб помирати
165 subscribers
30 photos
9 videos
43 links
Канал про PHP, розробку, проєктування і нескінченне навчання в циклі життя.
Download Telegram
#course #php #talks #4students #tips #tools

🧲 Один з інструментів DRY або єдиний дозволений copy/paste

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

Але суть в тому, що трейти — це всього лише інструмент, який треба застосовувати там, де від нього буде найбільше користі.

І найчастіше це не сервісні класи (хоча є ситуації коли і тут вони будуть доречні), а обʼєктні структури: сутності, DTO, VO, event'и тощо. Саме там трейти — ідеальний інструмент для роздачі типової поведінки без зайвої ієрархії і порушення DRY.

Гарний приклад — бібліотека knplabs/doctrine-behaviors. своїми інтерфейсами вона надає вашим сутностям типову поведінку (наприклад, Timestampable, SoftDeletable, Translatable тощо), але замість того, щоб реалізовувати інтерфейси в кожному класі, ви просто додаєте реалізацію — підключаючи відповідний трейт. Ніяких милиць у вигляді абстрактних батьківських класів, які «надають поведінку», тільки чистий код, лаконічний use TraitName і ніякого copy/paste

Хоча справедливості заради варто визнати: copy/paste все одно відбувається, просто не в коді, а на рівні інтерпретатора.

🎯 Висновок

Трейти — це спосіб дотримуватися DRY і не лізти в спадкування там, де воно недоречне. Це дуже потужний інструмент якщо використовувати його правильно і там де треба.


PS:
🧠 Порада: як зробити, щоб трейт гарантовано працював в будь-якому класі без помилок?

❗️ Ніколи не звертайтесь всередині трейту до властивостей або методів класу, в який трейт підключено. Трейт не знає, куди його вставлять — і тому контекст будь-якого трейту має бути самообмеженим. Це головна умова, щоб ваш трейт працював стабільно і не викликав помилки.


Погано:
trait BadTrait {
public function generateUniqueId(): void
{
$this->id = uniqid();
}
}


Добре:
trait GoodTrait {
protected string $id;

public function generateUniqueId(): void
{
$this->id = uniqid();
}
}
👍8💩1
#game #dictionary34

☀️ Доброго ранку!
Граємо в «Три-чотири» 🧠

Правила тут

🎯 Поняття дня:
Middleware


По одній з версій, це:
Магія поза Гоґвортсом


👇 Пиши свою версію в коментарях.

---

🇺🇦 Ранок без донату на ЗСУ — як request без response.
🎯 Закинь свої 2 гривні у return — підтримай наших захистників! 💛💙
👍1
#course #algorithm #series

🧵Наскільки ефективний мій код? 8/8

O(n!) – Факторіальна складність


Це — вершина обчислювального кошмару. Факторіальна складність означає, що кількість операцій зростає як добуток усіх цілих чисел до n. Для n = 10 — це вже 3 628 800 варіантів. І так, усе це треба обробити.
10! = 10 × 9 × 8 × 7 × 6 × 5 × 4 × 3 × 2 × 1 = 3 628 800


📌 Приклад: Генерація всіх можливих перестановок елементів
function permutations(array $items): array {
if (count($items) <= 1) return [$items];

$result = [];
foreach ($items as $key => $item) {
$remaining = $items;
unset($remaining[$key]);
foreach (permutations(array_values($remaining)) as $perm) {
$result[] = array_merge([$item], $perm);
}
}
return $result;
}

Цей код генерує всі можливі перестановки елементів масиву. І якщо їх 8 — то вже 40 320 варіантів. Це може виглядати невинно, поки не впаде прод у Black Friday.

📌 Факторіальна складність — це завжди крайній захід. Якщо задача передбачає перебір усіх варіантів, спершу шукайте апроксимацію, жадібний алгоритм або евристику.


🎬 На цьому серія завершується.
Якщо хочете ще серію подібну до цієї, пишіть в коментарях або в особисті.

⬅️ Попередня складність
👍8
This media is not supported in your browser
VIEW IN TELEGRAM
#humor

Коли йдеш за трендами і вирішив розробити свою ML модель але єдина мова, яку ти знаєш — це PHP
😁13
#game #dictionary34

🌥 Ранок!
Забув написати відкладений пост, тому трохи із затримкою граємо в «Три-чотири» 🧠 (правила)

🎯 Поняття дня:
Фреймворк


По одній з версій, це:
Батько твого контролера


👇 Пиши свою версію в коментарях.

---
🕯Задонать свої 47 гривень на ЗСУ, щоб люди не гинули увісні від кацапських шахедів, що залетають в багатоповерхівки.
❤2👍1
#game #dictionary34

🎂 Доброго ранку!
Граємо в «Три-чотири» 🧠 (правила)

🎯 Поняття дня:
Динамічна типізація


По одній з версій:
Тип змінюється як настрій


👇 Пиши свою версію в коментарях.

---
Мені сьогодні 4⃣2⃣, тому, у якості привітання, зкиньте 42 гривні на русоріз або на інший збір, якому ви довіряєте.
👍5🎉3❤1
#game #dictionary34

🌄 Доброго ранку!
Після змушеної переви, продовжую

Граємо в «Три-чотири» 🧠 (правила)

🎯 Поняття дня:
Лямбда функція


По одній з версій:
Виконавець для колбеків


👇 Напиши свою смішну або правильну версію в коментарях.

---
🎯 Кожна твоя думка в коментарях — це плюс у словник, а кожен донат — плюс до нашої Перемоги. Підтримай ЗСУ!
❤2
#course #php #talks #4students #tips

🧮 Який в тебе масив — асоціативний чи індексований?

В PHP масив — це універсальний інструмент, який не вимагає від тебе визначати розмір, тип елементів чи навіть структуру ключів. Це з одного боку ніби і зручно, але з іншого — є проблемою.
Більшість мов програмування виділяють масиви (indexed arrays) і словники/мапи (associative arrays), а в PHP це одна й та ж сама структура, будь-який масив може стати асоціативним або нумерованим в залежності від ключів, які ти використовуєш:
$a = [1, 2, 3, 4, 5];  // індексований
$b = ['foo' => 6]; // асоціативний
$c = [
...$a,
...$b
]; // змішаний

Часто виникає потреба по-різному обробляти масиви в залежності від їх типу. Але PHP не дає такої базової можливості, бо він взагалі не розрізняє індексовані та асоціативні масиви, про що прямо написано в документації.

Можна подумати, що array_is_list може допомогти зʼясувати хто є хто
array_is_list($a); // true  [0=>1, 1=>2, 2=>3, 3=>4, 4=>5]
array_is_list($b); // false [foo=>6]
array_is_list($c); // false [0=>1, 1=>2, 2=>3, 3=>4, 4=>5, foo=>6]

На перший погляд все добре, але ні.

Розширемо наш приклад, витягнемо з масиву $a тільки непарні числа
$a2 = array_filter($a, fn($x) => $x % 2 !== 0); // 1,3,5
array_is_list($a2); // false бо 0=>1, 2=>3, 4=>5

🙄 Що сталося з масивом? Невже він став асоціативним?

Ні. Просто array_filter зберігає оригінальні ключі. І хоч це все ще числові ключі, але через “дірки” в індексації array_is_list повертає false.
Тобто, PHP не ставить знак дорівнює між "нумерованим" та "індексованим" типами масивів.

Ще одна неприємність яка може вас очікувати: рядкові ключі — не гарантують “асоціативність”

Багато хто вважає, що якщо в масиві ключ рядковий — все, це асоціативний масив. Але якщо ключ виглядає як число, PHP конвертує його в int. Наприклад, штрихкоди товарів:
$products = [
"0123456789052" => "Товар",
"8018075001428" => "Ще товар"
];
print_r(array_keys($array));
//Array
//(
// [0] => "0123456789052"
// [1] => 8018075001428 // -- рядок став числом
//)

Тому на ключі типу “рядок чи число” теж покладатися не можна.

Висновок:
Я бачив багато коду, де масив використовують як list, а потім раптово додають рядковий ключ — і все, data integrity накрилась. Якщо твоя логіка дійсно залежить від того, який у тебе масив — перевіряй не array_is_list, а реально структуру ключів (через array_keys, is_int, is_string і т.д.). А ще краще — не лінуйся типізувати і перевіряти дані на вході, навіть якщо це PHP.


Чи стикаєтеся ви в роботі з такими складностями і як з них виходите?
👍9🗿1
😁11🤓1
#tools #symfony #course #4students

🔄 symfony-docker-installer v.2

Колись на одному з курсів зробив цей інсталятор щоб студенти не витрачали час на налаштування проєкту на Symfony в Docker. З тих пір багато що змінилося і я оновив інсталятор, тепер він повністю автоматизований і працює на make.

Що змінилось?
— Абсолютно новий інсталятор, вся рутина — поза вашою увагою
— В readme є коротка інструкція
— Жодних додаткових дій робити не треба

Як користуватись
1. Скопіюй .env.install.dist у .env.install
Вкажи PROJECT_NAME та, якщо треба, інші змінні

2. Запусти
make install-init

Введи версію Symfony (або просто натисни Enter — тоді буде остання)
Вкажи git-репозиторій для свого нового проєкту (або Enter, якщо не треба)
⚠️ Будь уважним, бо якщо вкажеш репозиторій, в якому вже є дані, вони видаляться!

3. Далі інсталятор все зробить сам

Для тих, хто хоче спитати чому не просто стандартний docker від Symfony
Відповідь проста: це саме та збірка, якою ми користуємось на курсі.
Тут вже налаштовані make-команди, дебагер, nginx, все для роботи й адекватної розробки.
Замість того, щоб 100500 разів пояснювати кожному, що і як налаштувати для старту — просто даю готовий інструмент, який працює як треба.
Поза курсом використовувати його не обов’язково, але особисто я юзаю подібну збірку у всіх своїх проєктах, бо інакше це марнування часу на одну і ту саму рутину.
🔥9❤1👍1
This media is not supported in your browser
VIEW IN TELEGRAM
#humor
Це я на курсі php-pro показую приклад як в Twig можна робити html верстку
😁20🥴2👍1
#tools #4students

🛠 Швейцарський ніж для розробника

Деякий час тому відкрив для себе DevToys — нереально крутий агрегатор інструментів розробника, який заміняє десятки відкритих вкладок у браузері.

Програма має український інтерфейс, працює офлайн і доступна для Windows, macOS, Debian / Ubuntu.

На борту:
— JSON / YAML / XML форматери
— base64 / URL / HTML енкодер/декодер
— Regex тестер
— Hash генератор (MD5, SHA...)
— UUID генератор
— JWT декодер
— Timestamp ↔️ дата
— Text diff
— Lorem Ipsum
— CSV ↔️ JSON
— тощо

ТОП-3 — Те що Doctor прописав:
🧪 Regex Tester — не зрівняється з regex101 по зручності проєктування і тестування складних шаблонів, але для простих регулярок — ідеальний
🔄 JSON / YAML / XML форматери — рятують, коли отримав щось кудлате і треба це привести до ладу
💻 base64 / URL / HTML енкодер/декодер — часто треба, і приємно, що це під рукою

❗️А ще DevToys має відкритий SDK який дозволяє додавати власні розширення

Дуже раджу спробувати
Встановив — і мінус кілька онлайн-сервісів із закладок.
❤‍🔥7👍6🥴1
#humor

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

Валентин, Тигран, ніхто не казав, що буде легко 😉
😁12
Дехто з вас питає, чому я перестав регулярно робити пости.
Причина проста — весь вільний час іде на створення нового відеокурсу по MongoDB, за аналогією з моїм курсом по MySQL.

#sql #course #4students

До речі, якщо ви з MySQL ще не на "ти" — дуже раджу мій курс Бази даних: SQL

В ньому:
• 6 годин відео
• 24 заняття українською мовою
• завдання з розбором, після яких SQL перестає бути страшним
• лише те, що реально потрібно в роботі

Для тих, хто знає мій стиль викладання — формат звичний.
А для інших — ось плейлист на YouTube з кількома відкритими уроками: три перші заняття і одне з фінальних, щоб ви могли зрозуміти чи підійде це для вас

👉 Поспішай поки діє знижка.
❤5👍3🔥1
#symfony #php #architecture #videoarchive

Symfony 🆚 Laravel

Знайшов і опублікував для вас запис вебінару, який я проводив в травні минулого року
В самому вебінарі не тільки порівняння вказаних фреймворків, а ще й зробив невеличкий огляд на історію розвитку фреймворків в PHP, саме порівняння стартує з 34:40

👍 Ставте лайки або дизлайки, підписуйтесь на канал і робіть все інше, що треба, щоб на YouTube ставало більше україномовного контенту

Приємного перегляду!
Альтернативні думки в коментарях до відео або цього посту вітаються
👍13
This media is not supported in your browser
VIEW IN TELEGRAM
#humor

$peppa = new Pig('Peppa');
$qa->test($peppa->spin()
->until('smoked'));
😁12🤣3😢1
#️⃣ #php #longread

💡 Майбутнє PHP: погляд на те, що принесе PHP 9

PHP — живіший, ніж будь-коли 😎
І хоча хтось досі вважає його “динозавром”, мова продовжує еволюціонувати. PHP 9.0 може стати тим самим моментом, коли “магія” поступиться місцем чистоті, а неочікувані трюки — передбачуваності.

🕒 Офіційної дати коли чекати PHP 9 ще немає, але RFC-дискусії вже киплять.
Після 8.5 (і можливо 8.6) ми отримаємо більш суворий, логічний і, що важливо, стабільний PHP.
Тож якщо ти ще не стежиш за RFC — то я поділюся з тобою цією інформацією 👀

1️⃣ Оператори ++ / -- стануть чеснішими
Тепер ніяких дивних перетворень рядків у цифри.
$a = 'a9';
$a++;
// PHP < 9.0 -> 'b0'
// PHP 9.0 -> TypeError

🧩 Менше “магії”

2️⃣ unserialize() кидатиме винятки
try {
$obj = unserialize($data);
} catch (UnserializationFailedException $e) {
// handle
}

🧠 Виключення замість warning

3️⃣ Менше перевизначень типив
$arr = false;
$arr[] = 2;
// PHP < 9.0 -> [2]
// PHP 9.0 -> Error

🙅‍♂️ Тепер буде помилка, а не постріл в коліно

4️⃣ Інтерполяція рядків — без зайвої магії
$name = "Alex";
echo "Hello $name"; // ✅
echo "Hello {$name}"; // ✅
echo "Hello ${name}"; // ❌ Deprecation

✨ Приведення до єдиного стандарту

5️⃣ Попередження == fatal error
Невизначені змінні, властивості чи звернення до null більше не проходитимуть "якось"
echo $undefinedVar;   
// PHP < 9.0 -> Попередження
// PHP 9.0 -> Фатальна помилка

🧱 PHP буде вимогливішим до якості коду — і це добре.

6️⃣ Прибирання старих “речей”
Старі конструктори, застарілі функції, нестандартна логіка — все це піде в архів 📦
Менше сміття, менше двозначностей.

🚀 Підсумок
PHP 9.0 — має кардинально змінити підхід до написання коду та його культури.
Менше вседозволеності, більше контролю.

Якщо твій код вже чистий, суворо типізований і без магії — тобі нема чого боятися 💪
🔥11👍6
#php #course #series

🚀 Чи знаєш ти, що PHP так вміє? 1/10
10 потужних інструментів, які тобі слід використовувати 🧠

Кожен реліз PHP приносить нові можливості, що роблять код коротшим, розумнішим і приємнішим у підтримці.
Але, як показує досвід численних співбесід і консультацій, більшість із них проходять повз увагу навіть досвідчених розробників.

Ця серія — для тих, хто, як і я, прагне по-справжньому розкрити потенціал PHP і кайфувати від розробки 💥

Ми розберемо 10 фіч, які:
🔹 доступні з PHP 5.5, але досі поза увагою
🔹 реально спрощують код
🔹 показують, наскільки PHP універсальний
——————

Перша стаття серії

⚙️ Property Promotion

Менше коду — легше читати 💡

📦 Додано у версії: PHP 8.0
💡 Що дає: можливість оголошувати властивості класу прямо в конструкторі — без дублювання й шаблонного коду.

🚀 Чому це крутіше за старий підхід

— не потрібно окремо описувати властивості та привласнювати їх значення у конструкторі;
— менше шуму — одразу видно структуру класу;
— ідеально підходить для DTO, запитів, VO, команд, конфігів тощо.
🧠 Фактично це "data class" по-PHPшному — коротко, без додаткових бібліотек чи автогенерації коду.

🧱 Реальний приклад застосування
// ❌ Раніше
readonly class Product {
public string $sku;
public string $name;
public float $price;

public function __construct(string $sku, string $name, float $price) {
$this->sku = $sku;
$this->name = $name;
$this->price = $price;
}
}

// ✅ Тепер
readonly class Product {
public function __construct(
public string $sku,
public string $name,
public float $price,
) {}
}

📌 У коді це зменшує бойлерплейт майже втричі, а клас стає самоочевидним.

🧩 Де це реально корисно
— DTO у запитах/відповідях API;
— командні об’єкти в CQRS;
— значення, які описують одну сутність без поведінки (Value Object);
— Symfony-форми, коли треба швидко пробросити дані.
class CreateUserCommand {
public function __construct(
public string $email,
public string $password,
public bool $isAdmin = false,
) {}
}


🧭 Висновок

✨ Property Promotion — не просто синтаксичний цукор, це офіційний перехід до декларативного стилю.
Код виглядає лаконічніше, без зайвих рядків.

———
Анонімні класи ➡️
👍9❤1🔥1
#question
Що виведе?
echo '-' . 1 + 4 - 2;
Anonymous Quiz
21%
1
0%
-1
4%
-7
0%
-5
54%
-3
5%
3
16%
Помилка
🤯3🤝2👍1