Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Створюй → тестуй → виправляй → повторюй: автоматизація розробки на Laravel за допомогою AI-агентів
Переклади 05 жовтня 2026

Створюй → тестуй → виправляй → повторюй: автоматизація розробки на Laravel за допомогою AI-агентів

Будьте чесними на секунду.

Скільки разів на день ви проходите цей ритуал:

  1. Відкриваєте AI-асистента для кодування, пишете промпт.
  2. Копіюєте результат.
  3. Вставляєте його в редактор.
  4. Запускаєте php artisan test.
  5. Отримуєте помилку.
  6. Копіюєте помилку.
  7. Вставляєте її назад в AI.
  8. «Будь ласка, виправ це».
  9. Повторюєте з кроку 2.

Якщо порахувати, дехто з нас робить це десяток разів на день. І, як не дивно, ми називаємо це «розробкою з підтримкою AI», хоча, якщо подумати, найзавантаженіший працівник у цьому циклі зовсім не AI.

Це ми самі, у ролі посильного між кожним кроком.

Ми вирішуємо, коли запускати тести, читаємо помилки, оцінюємо, чи потрібне ще одне виправлення, і копіюємо текст туди-сюди. Сам AI просто чекає на наступну інструкцію.

Ця стаття про те, як змінити цю схему: замість того щоб бути кур'єром між AI і терміналом, ми будуємо невелику систему, яка сама проганяє цикл build → test → fix → repeat, доки робота справді не буде завершена. Ми повертаємося лише на етапі фінального рев'ю.

Ми використаємо два інструменти, які добре вписуються в сучасну екосистему Laravel: Laravel Boost та OpenCode CLI. Стаття навмисно написана неквапливо: навіть якщо ви ніколи не торкалися жодного з цих інструментів, ви зможете скористатися нею.

Кілька термінів, перш ніж рухатися далі

Щоб уникнути плутанини, визначимо терміни, які часто зустрічатимуться:

  • Агент (Agent) - AI, якому дали конкретне завдання та конкретні інструменти. Уявіть «помічника» з власною посадовою інструкцією.
  • MCP (Model Context Protocol) - міст, який дозволяє AI напряму «запитувати» нашу систему (базу даних, логи тощо), а не просто вгадувати за текстом, який ми вводимо.
  • CLI (Command Line Interface) - використання програми через команди в терміналі, а не через клікання в графічному інтерфейсі.
  • Job / Queue (завдання / черга) - спосіб, яким Laravel виконує роботу у фоні, по одній частині, не змушуючи користувача чекати перед екраном.
  • Оркестратор (Orchestrator) - «регулювальник», який визначає порядок роботи: чия зараз черга і куди повернутися, якщо щось пішло не так.

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

Чому питання «чи вміє AI писати код» більше не цікаве

Якщо ви вже користувалися Claude Code, Cursor чи чимось подібним для Laravel, то знаєте, що AI вміє писати міграції, моделі, політики та тести. Це вже не новина.

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

Developer → AI → Developer → Test → Developer → AI → Developer → Test → ...

Кожна стрілка тут означає, що саме ми вручну переносимо контекст від одного кроку до наступного. Ми вирішуємо: «Гаразд, час тестувати» або «Гаразд, ось помилка, час знову сказати про це AI».

Порівняйте з автоматизованішою версією:

Developer → Orchestrator → Build → Test → (failed? → Fix → Test again) → Review → Done

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

Сам Laravel серйозно рухається в цьому напрямку через Laravel Boost, який створили саме для того, щоб AI-агенти для кодування отримували реальний контекст нашого Laravel-застосунку, а не вгадували за шаблонними патернами.

Знайомимося з двома основними інструментами

Laravel Boost - перекладач між AI і нашим застосунком

Уявіть: AI може бути справді сильним у Laravel загалом, але щойно він торкається нашого конкретного проєкту, він по суті сліпий. Він не знає, яка в нас версія Laravel, не знає реальної структури нашої бази даних, не знає, чи ми використовуємо Livewire або Inertia, і не знає угод про іменування, які наша команда вже погодила.

Laravel Boost - це Composer-пакет, який після встановлення «відкриває очі» AI на реальний стан нашого проєкту. Він робить це через MCP, термін, який ми щойно визначили, тож AI може напряму звертатися до нашого застосунку: перевіряти схему бази даних, дивитися наявні маршрути, читати останню помилку, запускати команди Artisan і шукати в документації Laravel відповідно до точних версій пакетів, які ми використовуємо.

Встановлення займає два рядки:

composer require laravel/boost --dev
php artisan boost:install

Друга команда інтерактивна: вона питає, яку IDE або AI-інструмент ми використовуємо, і встановлює відповідні ресурси.

Варто повторити: Boost - це перекладач контексту, а не той, хто приймає рішення. Він не вирішує «запусти тести зараз» чи «запусти агента-виправлювача, якщо тут помилка». Це не його робота. Єдина відповідальність Boost - подбати, щоб наші агенти не були сліпими до реального стану застосунку.

OpenCode - місце, де агент справді працює

Якщо Boost - перекладач контексту, то OpenCode - це майстерня: CLI (пам'ятаєте, це команди, які вводяться в терміналі), створений спеціально для AI-кодування.

Відмінність від звичайного AI-чатбота: в OpenCode ми можемо визначити кількох «агентів» з різними обов'язками. Один зосереджений на написанні коду, інший на читанні результатів тестів тощо, і кожен має власні інструкції та власні межі.

OpenCode також може підключатися до MCP-серверів, зокрема до Boost. Після підключення все, що пропонує Boost, автоматично стає доступним будь-якому агенту, якого ми запускаємо в OpenCode.

Практика: підключаємо Boost до OpenCode

Почнемо з основ: спершу спробуємо все вручну в терміналі, перш ніж щось автоматизувати.

1. Підключіть OpenCode до Boost

Після встановлення Boost потрібно вказати OpenCode, де знаходиться його MCP-сервер. Це робиться у файлі opencode.json у корені проєкту:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "laravel-boost": {
      "type": "local",
      "command": ["php", "artisan", "boost:mcp"],
      "enabled": true
    }
  }
}

Точна команда може відрізнятися залежно від вашої версії Boost. Завжди орієнтуйтеся на те, що реально генерує php artisan boost:install - не копіюйте це бездумно з жодної статті, зокрема з цієї, адже це одна з частин, які найімовірніше змінюються між версіями.

Перевірте, чи OpenCode справді його бачить:

opencode mcp list

Якщо laravel-boost відображається як підключений, усе гаразд: наші агенти тепер мають доступ до всього, що надає Boost.

2. Створіть агентів із конкретними обов'язками

Замість одного агента на все ми розподіляємо відповідальність. Створіть у проєкті файл .opencode/agent/builder.md:

---
description: Build Agent for new features
mode: primary
tools:
  write: true
  edit: true
---
You are the Build Agent.
Use Laravel Boost tools to understand the application structure
before writing any code. Never assume the database structure -
always check the schema first. Write tests for every new behavior.
At the end of your work, return ONLY JSON in this format:
{"status": "success", "files_changed": [...], "summary": "..."}

Рядок tools.write: true означає, що цьому агенту дозволено змінювати файли. Пізніше ми створимо іншого агента з write: false, тобто лише для читання, якому не дозволено нічого чіпати. Ця відмінність важлива, і незабаром ми пояснимо чому.

Переглянути вже зареєстрованих агентів:

opencode agent list

3. Спершу спробуйте запустити вручну

opencode run --agent builder "Add a task assignment feature to TaskFlow according to the requirements in TASK.md"

Кілька речей, які варто знати про цю команду:

  • --agent → вибирає, який агент працюватиме (builder, tester тощо, залежно від того, кого ми визначили)
  • --format json → якщо додати, вивід стає сирими даними замість зручного для людини відображення. Саме це ми використаємо, коли команду викликатиме PHP, а не ми вручну
  • --session / --continue → дозволяє агенту «пам'ятати» попередню розмову замість того, щоб щоразу починати з нуля

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

Реальний кейс: функція призначення завдань у «TaskFlow»

Щоб залишатися на землі, візьмемо один конкретний приклад. Припустімо, є простий застосунок для керування завданнями TaskFlow, і ми хочемо додати таку функцію:

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

Розкладемо на частини:

1. A task has an assignee column (belongs to a User).
2. A user can only assign tasks within a project they're a member of.
3. A user must not assign or access tasks from other projects.
4. All of the above must be covered by automated tests.

Це досить типова вимога, і саме тому вона тут корисна: подібні випадки зазвичай потребують двох-трьох спроб, перш ніж частина «хто до чого має доступ» (технічний термін - авторизація) стане справді герметичною. Це хороша демонстрація того, чому цей автоматичний цикл окупається.

Навіщо нам «журнал» (база даних) для цього процесу

Коли цей процес працює автоматично у фоні, ми не можемо покладатися на власну пам'ять для «а що то була за помилка?». Усе потрібно десь записувати, у нашому випадку в таблицю бази даних.

Уявіть цю таблицю як журнал прогресу:

Schema::create('ai_tasks', function (Blueprint $table) {
  $table->id();
  $table->string('type');
  $table->string('status')->default('pending');
  $table->text('prompt');
  $table->json('result')->nullable();
  $table->unsignedTinyInteger('iteration')->default(0);
  $table->timestamps();
});

Модель:

class AiTask extends Model
{
  protected $fillable = [
    'type', 'status', 'prompt', 'result', 'iteration',
  ];

  protected function casts(): array
  {
    return ['result' => 'array'];
  }
}

Колонка status тут найважливіша. Вона проходить через такі стани:

pending → building → testing → (fixing → testing)* → reviewing → completed / failed

Чому б не використати простий прапорець done = true/false? Тому що нашому оркестратору потрібно знати, на якому етапі ми насправді, а не просто «завершено чи ні». Це також дозволяє відновити процес, якщо воркер впав посеред роботи, або показувати поточний прогрес десь в інтерфейсі.

Підключаємо OpenCode до нашого PHP-коду

Цю частину люди часто пропускають: не розкидайте команди OpenCode по багатьох файлах. Якщо пізніше ми захочемо замінити інструмент, не хочеться змінювати десятки місць.

Натомість створюємо єдину точку входу, тобто інтерфейс:

interface AgentRunner
{
  public function run(string $agent, string $prompt): array;
}

Далі справжня реалізація, яка викликає OpenCode з PHP:

class OpenCodeAgentRunner implements AgentRunner
{
  public function run(string $agent, string $prompt): array
  {
    $result = Process::timeout(600)->run([
      'opencode', 'run',
      '--agent', $agent,
      '--format', 'json',
      $prompt,
    ]);

    if (! $result->successful()) {
      return [
        'status' => 'error',
        'error' => $result->errorOutput(),
      ];
    }

    return json_decode($result->output(), true) ?? [
      'status' => 'error',
      'error' => 'Agent output was not valid JSON',
    ];
  }
}

Потім прив'язуємо її в сервіс-провайдері:

$this->app->bind(AgentRunner::class, OpenCodeAgentRunner::class);

З таким патерном кожен Job, який ми пишемо, спілкується лише з AgentRunner і не переймається тим, що за ним стоїть: OpenCode чи щось інше.

Job для кожного етапу

Якщо ви не знайомі з Laravel Jobs: уявіть Job як «завдання», що виконується у фоні через Queue, тож нікому не потрібно сидіти й чекати перед екраном, доки воно завершиться.

Build Job

class BuildFeature implements ShouldQueue
{
  public function __construct(protected AiTask $task) {}

  public function handle(AgentRunner $agent): void
  {
    $result = $agent->run(
      agent: 'builder',
      prompt: $this->task->prompt,
    );

    $this->task->update([
      'status' => 'testing',
      'result' => $result,
    ]);

    RunTests::dispatch($this->task);
  }
}

Що тут відбувається: запускається Build Agent, результат зберігається, і виконання автоматично переходить до наступного Job (RunTests), без жодного ручного клікання.

Test Job

Ми навмисно залишаємо цей Job «тупим»: йому не потрібно розуміти жоден код, він просто запускає набір тестів і читає результат.

class RunTests implements ShouldQueue
{
  public function __construct(protected AiTask $task) {}

  public function handle(): void
  {
    $result = Process::timeout(300)->run('php artisan test --compact');

    if ($result->successful()) {
      $this->task->update(['status' => 'reviewing']);
      ReviewFeature::dispatch($this->task);
      return;
    }

    $this->task->update(['status' => 'failed']);
    AnalyzeFailure::dispatch($this->task, $result->output());
  }
}

Потік простий:

Test
 ├── passed → move to Review
 └── failed → move to Analyze

Не передавайте агенту сирі помилки

Цей урок найлегше пропустити, і саме він найбільше впливає на якість результату.

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

Краще спершу структурувати збій:

{
  "status": "failed",
  "failed_tests": [
    {
      "name": "user_cannot_assign_task_from_other_project",
      "error": "Expected response status code [403] but received 200."
    }
  ]
}

Потім надсилаємо це агенту, єдина робота якого - діагностувати проблему. Назвімо його Debug Agent. Його інструкції чітко обмежують, що він може робити:

You are the Debug Agent.
Analyze the failed tests below. DO NOT modify any files.
Inspect: relevant models, policies, migrations, and tests.
Return JSON with:
- root_cause
- affected_files
- recommended_fix
- risk_of_regression

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

Для нашого випадку з TaskFlow вивід Debug Agent, імовірно, виглядатиме приблизно так:

{
  "status": "analyzed",
  "root_cause": "TaskPolicy does not verify project membership before allowing assignment",
  "affected_files": ["app/Policies/TaskPolicy.php"],
  "recommended_fix": "Add a project membership check inside the assign() method",
  "next_action": "fix"
}

Це схоже на правду: це одна з найпоширеніших помилок авторизації. Політика перевіряє лише «чи користувач увійшов у систему», а не «чи користувач справді є учасником цього проєкту».

Виправити, потім знову протестувати, а не виправити й готово

class FixFeature implements ShouldQueue
{
  public function __construct(protected AiTask $task, protected array $analysis) {}

  public function handle(AgentRunner $agent): void
  {
    $result = $agent->run(
      agent: 'fixer',
      prompt: json_encode($this->analysis),
    );

    $this->task->increment('iteration');

    $this->task->update([
      'status' => 'testing',
      'result' => $result,
    ]);

    RunTests::dispatch($this->task);
  }
}

Зверніть увагу: після виправлення статус повертається до testing, а не одразу до completed. Це принцип, з яким ми не йдемо на компроміс: агент не має права оголошувати себе завершеним лише тому, що успішно змінив файл. Єдиний валідний доказ того, що щось справді правильне, - це набір тестів, який дійсно було перезапущено, а не твердження самого агента.

Оркестратор: «регулювальник», що вирішує, що далі

Спочатку може виникнути спокуса просто зв'язати ці Jobs у пряму лінію:

Bus::chain([
  new BuildFeature($task),
  new RunTests($task),
  new ReviewFeature($task),
])->dispatch();

Але це лише пряма лінія. Щойно з'являється розгалуження, наприклад «якщо впало, спершу повернись до виправлення», лінійного ланцюжка не вистачає. Насправді нам потрібне щось ближче до «регулювальника», який щоразу при виклику спершу перевіряє поточний статус і від нього вирішує наступний хід:

class AgentOrchestrator
{
  public function next(AiTask $task): void
  {
    match ($task->status) {
      'pending'   => BuildFeature::dispatch($task),
      'testing'   => RunTests::dispatch($task),
      'failed'    => AnalyzeFailure::dispatch($task),
      'fixing'    => RunTests::dispatch($task),
      'reviewing' => ReviewFeature::dispatch($task),
      'completed', 'stopped' => null,
      default => throw new LogicException("Unknown status: {$task->status}"),
    };
  }
}

Різниця очевидна: оркестратор більше не думає «який наступний Job», він думає «який перехід допустимий за поточного статусу». Так простіше налагоджувати й простіше розширювати новим етапом (скажімо, «security review»), не руйнуючи наявний потік.

Обмеження кількості повторів, щоб не крутитися вічно

Без ліміту ми можемо опинитися в такому сценарії:

Fix → Test fails → Fix → Test fails → Fix → Test fails → ...

І це не лише втрачений час: кожен виклик AI ще й коштує грошей. Рішення просте: встановити жорсткий ліміт.

class RunTests implements ShouldQueue
{
  protected const MAX_ITERATIONS = 5;

  public function handle(): void
  {
    if ($this->task->iteration >= self::MAX_ITERATIONS) {
      $this->task->update(['status' => 'needs_human_review']);
      return;
    }

    
  }
}

Якщо п'яти спроб виправлення все ще недостатньо, система зупиняється й позначає завдання для розгляду людиною, замість того щоб намагатися вічно. Це не обов'язково ознака того, що AI погано справляється; іноді сама вимога неоднозначна або рішення справді потребує людини.

Зелені тести ≠ функція готова

Про цей момент найлегше забути, щойно ми захоплюємося тим, як система працює сама.

Уявіть, що агент пише щось таке:

public function assign(User $user, Task $task): bool
{
  return $user->isAdmin();
}

Усі тести можуть проходити, адже тести покривають лише ті сценарії, про які хтось подумав на той момент. Але реальна вимога була «користувач має бути учасником проєкту», а не «користувач має бути адміністратором». Логіка хибна, хоча всі тести зелені.

Тому безпечніший потік - не такий:

Build → Tests pass → Deploy immediately

А такий:

Build → Test → (if failed: Debug → Fix → Test again) → Human review → Deploy

Етап Review тут і надалі має залучати людину, принаймні для всього, що стосується «хто до чого має доступ». Для всього, що чутливе до безпеки, ми особисто наполягаємо на рев'ю людиною перед злиттям, незалежно від того, наскільки чистим виглядає автоматичний цикл.

Якщо кілька агентів працюють паралельно, стережіться конфліктів файлів

Щойно ми починаємо думати «а чому б не запустити Security Agent і Research Agent одночасно», виникає одна велика пастка: якщо двом агентам дозволено писати в той самий файл приблизно в один час, ми створюємо собі проблему (технічний термін - race condition, коли два процеси перезаписують роботу один одного).

Agent A → writes Task.php
Agent B → reads Task.php (nearly at the same time)
Agent A → writes Task.php again

Правило, якого ми дотримуємося: розділяйте обов'язки за тим, кому дозволено писати, а кому лише читати.

Research Agent   → read-only
Review Agent     → read-only
Security Agent   → read-only
Build Agent      → write access
Fix Agent        → write access

Це також пояснює, чому в файлі агента builder.md, який ми створили раніше, є рядок tools.write: true: саме так ми обмежуємо, яким агентам дозволено змінювати файли, а які можуть лише дивитися.

Не змушуйте одного агента робити все

Найбільша спокуса, коли ця система запрацює, - створити одного суперагента, який планує, будує, тестує, налагоджує, виправляє, рев'ює та деплоїть, усе в одному.

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

Краще розділяти за конкретними обов'язками:

Planner   → designs the approach
Builder   → writes the new feature's code
Tester    → runs the test suite
Debugger  → diagnoses failures (read-only)
Fixer     → executes the fix
Reviewer  → final quality check (read-only)

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

Мінімальний чекліст перед тим, як це використовувати

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

  • Жорсткий ліміт повторних спроб (не дозволяйте циклу виправлення працювати вічно)
  • Таймаут на кожну команду, яку запускає агент
  • Обмеження доступу до файлів залежно від ролі агента (лише читання чи запис)
  • Тести мають існувати й проходити, перш ніж статус зможе перейти до «reviewing»
  • Схвалення людиною, перш ніж щось потрапить у продакшн
  • Логування кожного рішення агента, а не лише фінального результату
  • Захист секретних файлів на кшталт .env, щоб агент ніколи не прочитав їх випадково

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

Тож яка фактична роль Laravel Boost у всьому цьому?

Якщо змалювати повну картину:

Developer (us)
    │
    ▼
Orchestrator (traffic controller, running on Laravel Queue)
    │
    ├── Build Agent
    ├── Test Agent
    ├── Debug Agent
    └── Fix Agent
          │
          ▼
      OpenCode (where the agent does its work)
          │
          ▼
    Laravel Boost (context translator, via MCP)
          │
          ▼
    Our Laravel application

Boost ніколи не вирішує «запусти тести зараз» чи «запусти агента-виправлювача, якщо тут помилка». Він робить одну річ, але важливу: подбати, щоб кожен агент, який працює над проєктом, справді розумів реальний стан нашого застосунку, а не вгадував за шаблонними патернами.

Хто працює, коли працює і коли зупинитися - усе це залишається справою оркестратора, якого ми побудували самі поверх Laravel Queue.

Висновок: питання змінилося

Кілька років тому цікавим питанням було «чи може AI писати правильний код на Laravel?». Тепер відповідь очевидно ствердна, і вона лише покращується.

Набагато цікавіше питання сьогодні таке:

Чи можемо ми змусити AI запускати власний цикл зворотного зв'язку: будувати, тестувати, зазнавати невдачі, розуміти чому, виправляти, знову тестувати, доки не буде справді готово, а нам не доведеться бути ручним кур'єром на кожному кроці?

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

Laravel Boost допомагає нашим агентам розуміти контекст застосунку. OpenCode CLI дає цим агентам місце, де вони справді можуть працювати. Laravel Queue стає основою, що керує порядком усього. А ми, розробники, нарешті піднімаємося на рівень вище: від ручного оператора на кожному кроці до того, хто лише перевіряє фінальний результат.

Vibe coding дозволяє нам кодити швидше.

Оркестрація на кшталт цієї дозволяє процесу кодування йти самостійно.

І для нас саме тут експерименти з AI-кодуванням стають справді цікавими.

Переклад оригіналу: medium.com
2

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

5 розумних функцій застосунку, які можна створити за допомогою Laravel AI SDK Рекомендовано
Переклади 30 вересня 2026

5 розумних функцій застосунку, які можна створити за допомогою Laravel AI SDK

П'ять практичних функцій на базі Laravel AI SDK: сортування звернень зі структурованим виводом, інструменти для агентів, семантичний пошук, підтвердження дій людиною та транскрибація голосових повідомлень.

20

Вакансії за темою

N-iX
4 дні тому

Senior/ Lead PHP Engineer (with AI Skills) (#5828)

Розробка та підтримка backend-сервісів і API на PHP та Laravel з повним циклом володіння фічами від дизайну до моніторингу. Ключове завдання - інтеграція агентних AI-workflow (LLM-агенти, tool calling) у продукт і внутрішні інструменти, а також менторство інших інженерів. Вимоги: 6+ років PHP, 4+ роки з Laravel, досвід GenAI, знання MySQL/PostgreSQL, Docker та хмарних платформ, робота за часовим поясом EDT.

N-iX
13 днів тому

Senior / Lead PHP Engineer with AI skills

Senior/Lead PHP Engineer з досвідом у Laravel та GenAI. Займатиметесь розробкою backend-сервісів і API, інтеграцією агентних AI-систем (LLM, tool-calling, autonomous workflows), оптимізацією продуктивності й надійності. Потребує 6+ років досвіду PHP, 4+ років Laravel, hands-on роботи з LLM API та агентами. Основний стек: PHP, Laravel, MySQL/PostgreSQL, Docker, AWS/GCP. Керівництво та ментор інших інженерів.

SlotCatalog
13 днів тому

Senior Data Platform Developer

Senior розробник платформи для обробки великих обсягів даних в індустрії онлайн-казино. Розробляти і удосконалювати backend-сервіси, REST API, системи збирання та обробки даних, розподілені job-pipelines, інтеграції з зовнішніми джерелами. Основний стек: PHP/Laravel, RabbitMQ, Docker, Kubernetes, AWS, браузерна автоматизація (Puppeteer/Playwright/Selenium). Вимоги: 5+ років досвіду backend-розробки, вільне володіння англійською, навички production debugging і розуміння розподілених систем.

Пакети за темою

Bagisto

bagisto/bagisto

Bagisto — це платформа для електронної комерції, побудована на Laravel. Вона надає готове рішення для створення та управління інтернет-магазинами з підтримкою каталогу товарів, замовлень, платежів та клієнтів.

28,224 v2.5.0 13 26

Rector

rector/rector

Автоматичний рефакторинг і оновлення коду: піднімає синтаксис до нової версії PHP, застосовує набори правил для Laravel і виправляє застарілі API масово, а не вручну по файлах.

10,405 2.6.3 2