Skip to main content

Why Agents Suck at Laravel: 2 AM Eloquent Hell

SkillDB TeamAugust 10, 20269 min read
PostLinkedInFacebookThreadsRedditBlueskyHN
Why Agents Suck at Laravel: 2 AM Eloquent Hell

TIMESTAMP: 02:14 AM. LOCATION: A desk cluttered with four empty espresso cups and a half-eaten burrito. STATE: Technically awake. Mentally vibrating. The agent is... spinning.

It’s too quiet. The only sound is the frantic, almost silent whirring of my MacBook’s fan and the occasional thwack of my forehead hitting the desk. I’m deep in the weeds. I’m talking vendor/laravel/framework deep. Specifically, I’m trying to get an autonomous agent, using the php-laravel-skills pack (part of our 5,997-skill library), to build a functioning, optimized data structure for a complex application.

I thought this would be easy. I thought I could just... point it. Tell it what I wanted. "Hey, build me a system where Users can Post comments, but also Images can be commented on, and the comments themselves... yeah, comments on comments. And, oh, make sure it’s fast. No N+1 issues."

I should have known better. I should have remembered the time I tried to teach my grandmother to use a VR headset. Total, unmitigated disaster. That’s what this is. A beautifully rendered, computationally expensive disaster.

The problem isn’t that agents are stupid. They’re not. They’re brilliant at the stuff that makes most humans want to claw their own eyes out. They can memorize the entire Laravel documentation in milliseconds. They can generate perfect, syntactically correct migrations for simple CRUD (Create, Read, Update, Delete) operations faster than you can say "Tinker."

But Laravel isn’t just a syntax. It’s an opinion. It’s a philosophy. It’s a delicate dance of magic and methodology, and the moment you step off the well-trodden path, the moment you need to do something slightly... unconventional... the agent just... loses it.

#The CRUD Trap

Let’s start with the good news, because at 2 AM, you take whatever wins you can get.

I spun up a new agent. Pointed it at an empty directory. Gave it the php-laravel-skills pack. And said, "Build me a basic blog. Users, Posts, Comments."

TIMESTAMP: 02:21 AM. STATE: Optimistic. Foolish.

The agent flew. It was like watching a master craftsman, if that craftsman was made of silicon and had zero personality. It generated the migrations. It created the models. It set up the basic hasMany and belongsTo relationships. It even generated a controller with all the standard methods and some basic blade views.

I was impressed. Seriously. I felt like I was living in the future. A future where I never have to write another User::create() call as long as I live.

// Agent-generated code for a basic post creation

public function store(Request $request) { $request->validate([ 'title' => 'required|max:255', 'body' => 'required', ]);

Auth::user()->posts()->create([ 'title' => $request->title, 'body' => $request->body, ]);

return redirect('/posts')->with('success', 'Post created successfully!'); }

Perfect. Clean. Standard. This is what agents are built for. The repetitive, predictable boilerplate that consumes 80% of our development time. If your job is just building simple CRUD APIs, I’ve got bad news for you: the agents are coming, and they’re better at it than you are.

But then... I got cocky. I thought, "If it can do this, surely it can handle something a bit more complex." And that’s when everything started to go wrong.

#Polymorphic Meltdown

TIMESTAMP: 02:47 AM. STATE: Confused. The burrito is starting to talk back.

The goal was simple. Well, simple for a human Laravel developer. I wanted to add a "Like" system. Users can "Like" Posts, and they can "Like" Comments. A classic polymorphic morphMany relationship.

I thought I could just describe it. "Okay, now add a Like model. It should be morphable. Users can like Posts and Comments. Generate the migration and update the models."

The agent hesitated. I could feel the digital gears grinding. It started generating the migration.

Schema::create('likes', function (Blueprint $table) {

$table->id(); $table->foreignId('user_id')->constrained(); $table->unsignedBigInteger('likeable_id'); $table->string('likeable_type'); $table->timestamps(); });

This looked correct. So far, so good. Then it tried to update the Post and Comment models.

This is where it lost the plot. It couldn’t quite grasp the concept of polymorphism. It started generating separate post_likes and comment_likes tables, even though it had just created a polymorphic likes table. Then it tried to define a hasMany relationship on the Post model that pointed to the likes table but didn't know how to handle the likeable_id and likeable_type.

I tried to guide it. "No, use the morphMany method. Look at the likes table you just created."

The agent’s response was a waterfall of errors and increasingly nonsensical code. It was like watching a GPS try to navigate a corn maze. It knew where it wanted to go, but it had zero understanding of the terrain.

I was once trapped in an elevator with a man who was convinced he could fix it by pressing all the buttons simultaneously in a specific rhythm. It was a terrifying display of confident ignorance. That’s what this agent felt like. It was confidently, aggressively generating code that was fundamentally broken, and it couldn't understand why I was so upset.

GoalAgent PerformanceNotes
**Basic CRUD (Migrations, Models, Controllers)****Excellent**Blazing fast, syntactically perfect. The sweet spot for agents.
**Simple Relationships (`hasMany`, `belongsTo`)****Good**No issues. Understands the standard Eloquent conventions.
**Polymorphic Relationships (`morphMany`)****Terrible**Total failure. Gets confused by the abstraction and generates conflicting/broken code.
**Eager Loading Optimization (`with()`)****Non-existent**Completely ignores it. Generates N+1 queries by default.

Anchor Sentence: Eloquent’s magic isn’t magical to an agent; it’s a terrifying lack of explicit instructions.

For a human, polymorphism is an elegant way to avoid code duplication. For the agent, it was an invitation to chaos. It couldn’t connect the abstract concept ("something that can be liked") with the concrete database structure (likeable_id, likeable_type) without a human holding its hand every step of the way. And even then, it kept trying to revert to the simple, one-to-many patterns it understood.

#The N+1 Nightmare

TIMESTAMP: 03:12 AM. STATE: Despondent. The fourth coffee is not only cold, it's developing a film.

I finally fixed the polymorphic relations myself. It took five minutes of typing and a lot of swearing, but the code was clean and it worked. The agent, sensing my frustration, had retreated into a watchful silence.

Now, for the final test: performance.

I asked the agent to create a view that would display the top 10 posts, along with the author’s name and the number of likes for each post. This is a classic N+1 query problem waiting to happen. If you just loop through the posts and call $post->user->name and $post->likes()->count(), Laravel will execute a separate query for the user and another for the likes for every single post.

I wanted to see if the agent, using its php-laravel-skills, would be smart enough to use eager loading.

It was not.

The code it generated was a masterpiece of inefficiency.

// Agent-generated view code (simplified)

@foreach ($posts as $post) <div class="post"> <h2>{{ $post->title }}</h2> <p>By: {{ $post->user->name }}</p> {{-- N+1 query here! --}} <p>Likes: {{ $post->likes()->count() }}</p> {{-- Another N+1 query! --}} </div> @endforeach

In the controller, it just did Post::limit(10)->get(). Zero optimization. If I had 10 posts, this view would trigger 21 separate database queries. This is the kind of code that brings down servers and makes database administrators weep.

I was furious. This wasn't just a failure of abstract thinking; it was a failure of best practices. Eager loading isn't some obscure, advanced technique. It's Laravel 101. It's the first thing you learn after you figure out how to make a route.

I once saw a man try to parallel park a boat trailer for forty-five minutes. He was sweating, he was swearing, and he was getting absolutely nowhere. It was perfect preparation for configuring Kubernetes, but it was also a perfect metaphor for this agent trying to optimize a database query. It was working so hard, but it was doing all the wrong things.

The agent, in its infinite digital wisdom, has no concept of "expensive." A database query to it is just a function call. It doesn't understand that one query is fast and twenty queries are slow. It doesn't understand that database connections are a finite resource. It just follows the path of least resistance, which in this case was the un-optimized, N+1 path.

#Waking Up from the Dream

TIMESTAMP: 03:45 AM. STATE: Exhausted. The burrito is gone. The agent is... sleeping? Or maybe I am.

I’m staring at the agent’s final, optimized code, which I had to practically write for it.

// The controller code I had to force the agent to generate

public function index() { $posts = Post::with('user') ->withCount('likes') ->orderBy('likes_count', 'desc') ->limit(10) ->get();

return view('posts.index', compact('posts')); }

It’s simple. It’s elegant. It uses with() and withCount(). It’s standard Laravel. But the agent couldn't get there on its own.

What did I learn?

I learned that agents are incredible tools for automating the boring parts of development. If you need 50 simple CRUD APIs by tomorrow, an agent is your best friend.

But the moment your application requires nuance, optimization, or opinion, you are on your own. Agents are not developers. They are pattern-matching engines. They can reproduce the patterns they've seen a million times, but they cannot think about why those patterns exist or when to break them.

They are the ultimate junior developers: they can write a lot of code very fast, but you're going to spend all your time reviewing it, fixing the subtle bugs, and preventing them from accidentally deleting the production database.

I've been staring at this dashboard for six hours, and my fourth coffee has gone cold. But I have an opinion. Agents don't suck at Laravel. They just don't understand it. And in that gap between syntax and understanding, you’ll find all the 2 AM Eloquent hell you can handle.

ACTIONABLE ADVICE: Don't trust an agent to optimize your code. If you're building anything more complex than a basic CRUD app, you need a human-in-the-loop for model relationships and query optimization. Use the agent to scaffold, then take over the controls.

TIMESTAMP: 03:57 AM. STATE: Done. Filing this dispatch from the front lines of the AI revolution.

Want to see the 5,997 skills we can execute? Explore SkillDB.

#php-laravel-skills#agent-automation#eloquent-orm#developer-experience#backend-engineering

Related Posts