DEV Community

Jefferson Silva
Jefferson Silva

Posted on

What if PHP had its own Jupyter Notebook?

Every PHP developer has been there. You need to test a quick idea, run a query, check how a service behaves with specific data. So you do one of these:

  • Open Tinker and lose framework context after every typo
  • Create a throwaway route, hit it from the browser, delete it later
  • Write an artisan command for something you'll run once
  • Add dd() somewhere, refresh, remove it, repeat None of these are good. They're just the least bad options we've learned to live with.

A REPL that actually knows your project

I built a Task Runner inside DDLess that works differently. It boots your framework β€” Laravel, Symfony, WordPress, or any PHP project β€” and gives you a persistent environment where everything is available. Models, services, helpers, config, database connections. All live, all ready.

You write PHP, you run it, you see the output. No throwaway files. No fake routes. No restarting.

Real problems it solves

Quick data exports without writing commands

A client needed a CSV export of 17,000 records with specific formatting. Instead of creating an artisan command, registering it, running it, and deleting it later, I wrote this directly in the Task Runner:

$this->export('points_of_sale', function ($page) {
    $records = PointOfSale::with(['segment', 'adfLevel'])
        ->offset($page * 500)
        ->limit(500)
        ->get();

    if ($records->isEmpty()) return null;

    return $records->map(fn ($r) => [
        'Name' => $r->business_name,
        'Segment' => $r->segment?->name ?? '-',
        'Active' => $r->active ? 'Yes' : 'No',
    ])->toArray();
});
Enter fullscreen mode Exit fullscreen mode

Progress bar, pagination, and a download button at the end. 17,415 rows in minutes.

Testing ideas before committing code

You're not sure if a service behaves correctly with edge case data. Instead of writing a test or hitting the endpoint manually, you run it directly:

$service = app(OrderService::class);
$result = $service->calculate(userId: 42, coupon: 'EXPIRED_CODE');
$this->json($result);
Enter fullscreen mode Exit fullscreen mode

Full framework context. Real dependency injection. Real database. No mocking.

Interactive output

The Task Runner isn't just text. It renders charts, interactive fields, validation feedback, and formatted tables. You can build quick internal tools without creating a single Blade view.

Import and transform data

Need to process a CSV and push it to the database? The Task Runner supports $this->import() as a generator, so you stream large files without loading everything into memory:

foreach ($this->import('users.csv') as $row) {
    User::updateOrCreate(
        ['email' => $row['email']],
        ['name' => $row['name'], 'role' => $row['role']]
    );
}
Enter fullscreen mode Exit fullscreen mode

It's free

The Task Runner is included in DDLess at no cost. No Pro subscription, no trial, no limits. Download and use it.

ddless.com

DDLess is a PHP development workbench that also includes step debugging without Xdebug, method testing, and an AI copilot. But the Task Runner alone is worth the download.


If you want to read the full technical story behind DDLess, including the AST instrumentation approach and why it doesn't need Xdebug, check the blog post that was featured in PHP Reads Issue #6 by Stefan Priebsch and Sebastian Bergmann: ddless.com/blog/technical-journey-building-php-debugger

Top comments (0)