PHP and Twig
Next release
How midcode runs a PHP site with PHP's built-in server and edits the HTML written in its .php and .twig templates, leaving what PHP prints alone.
This ships with the next release of midcode. The version you can download today (1.1.2) doesn’t have it yet.
midcode opens a PHP site that isn’t Laravel or WordPress (plain PHP pages, or a framework with a front controller and Twig templates) and edits the HTML written in its templates: text, classes, attributes, new elements and their order. What PHP or Twig prints (<?= $title ?>, {{ title }}) is edited where the value is written, not on the canvas.
PHP renders the page, so midcode finds each element in your template files after the page loads. Sites a server renders explains how. Laravel and WordPress have their own pages.
At a glance
| PHP and Twig | |
|---|---|
| Detected by | index.php at the top of the folder, or in public/, web/ or webroot/ |
| Runs with | php -S 127.0.0.1:$PORT, with -t <folder> when index.php is in one of those folders |
| Elements are marked by | midcode, after each page loads, by matching it against the project’s .php, .phtml and .twig files |
| Editing | Text, classes, attributes and tag; insert, move, duplicate and remove |
| Pages | Not listed. Type the path |
| Styles | Tailwind 4 classes, or mid: utilities with midcode.css next to index.php |
| Tried with | Plain PHP with includes and a loop, and PHP with Twig. Every element written in the templates was found |
How midcode runs it
midcode looks for index.php and starts PHP’s built-in server where it is:
Where index.php is | Command |
|---|---|
| The top of the folder | php -S 127.0.0.1:$PORT |
public/ | php -S 127.0.0.1:$PORT -t public |
web/ | php -S 127.0.0.1:$PORT -t web |
webroot/ | php -S 127.0.0.1:$PORT -t webroot |
$PORT is a free port midcode picks. The command runs in your login shell, in the project’s folder, so php is the one your terminal would use. Its output is in the Dev server log in the top bar.
public/, web/ and webroot/ are where frameworks like Symfony, Slim, CodeIgniter, Craft, Drupal and CakePHP keep their front controller. midcode recognises them by that folder only. None of those frameworks was tried.
A folder is checked for Laravel (artisan) and WordPress (wp-load.php) first. Nothing in your project is changed to run it, and nothing is installed.
You need PHP on your Mac, on your shell’s PATH, and whatever the site itself needs to answer: its Composer packages installed, its database running.
What you can edit
Anything written as HTML in a .php, .phtml or .twig file. Code between <?php and ?> (and <?= ?>) is never touched. In Twig, neither are {{ }} and {% %}; {# #} is a comment.
<?php include 'partials/header.php'; ?>
<main class="page">
<h1>Our menu</h1>
<ul class="menu">
<?php foreach ($dishes as $dish): ?>
<li class="dish"><?= htmlspecialchars($dish['name']) ?></li>
<?php endforeach; ?>
</ul>
</main>
<?php include 'partials/footer.php'; ?>“Our menu” is written in the file: double-click it on the canvas to change it.
The
<li>is one line shown once per dish. Its classes can be edited, and the change applies to every dish. Its text is PHP’s.What
partials/header.phpwrites is edited in that file. Click an element of the header and the right panel showspartials/header.phpand the line under Code.
Changing the heading and giving the list more room, in a site without Tailwind:
- <h1>Our menu</h1>- <ul class="menu">+ <h1>Today's menu</h1>+ <ul class="menu mid:p-6">In an attribute, the written part and the computed part are told apart. Here the panel can add a class next to button and can’t change the href:
<a class="button" href="{{ path('menu') }}">See the menu</a>After each edit midcode reloads the page in every breakpoint: PHP has no live reload of its own. A change you make in your editor shows when you press Reload breakpoints.
Pages
midcode doesn’t read a PHP site’s routes. Pages in the top bar shows the home page; type a path there (for example /about.php) and press Enter to open another one. It doesn’t add pages either: a new one is a file, or a route, that you or your agent write.
Site settings
The globe in the top bar opens Site settings. The title, the description, the language, search engines, the favicon and the social image are written as tags in the <head> of your site: the first file that closes a <head>, in alphabetical order of its path (a header partial, usually). Images are copied to the folder PHP serves, next to index.php.
What PHP or Twig prints there (<title><?= $title ?></title>) shows as code and isn’t written. This wasn’t tried on a PHP site.
Styles
With Tailwind 4 in the project, midcode writes Tailwind’s classes. It starts only the PHP server: if a separate command compiles your CSS, keep it running yourself.
Without Tailwind, midcode writes mid: utilities and keeps their CSS in midcode.css, in the folder PHP serves (next to index.php). On your first style edit it adds one line to every file that closes a <head>:
<link rel="stylesheet" href="/css/site.css">+ <link rel="stylesheet" href="/midcode.css"> </head>See Without Tailwind for what’s in that file.
Limits
.htaccessrules don’t apply: PHP’s built-in server doesn’t read them. If your site depends on them, serve it your usual way and give midcode its address (Any other stack).Text that PHP or Twig prints is edited where the value is written. midcode’s own search for a text reads
.json,.js,.tsand.mdfiles, never.phpor.twig.HTML built inside a PHP string (
echo '<div class="card">') isn’t written as a tag in a template, so it isn’t found.A tag opened in one branch of an
ifand closed in another can’t be moved or removed from the canvas.Templates inside
vendor/are never read.If the project’s
package.jsonlists Vite, midcode opens it as a Vite project and starts Vite, not PHP. Laravel is the only PHP stack where it runs both. You can still see such a site by giving midcode its command or address in.midcode/server.json, but its templates aren’t matched.Smarty (
.tpl) and Latte (.latte) files aren’t read. Blade outside Laravel wasn’t tried.The free canvas is for Next.js projects.
Troubleshooting
“php” isn’t installed on this Mac (or not on your shell’s PATH). midcode runs the php your login shell finds. Install it, then press Restart in the dev server log.
Links that work on your own server don’t work here. The site expects rewrite rules. See the first limit above.
The site needs another command. Use Change how it runs on the error card to set the command and the address. $PORT in the command is the port midcode picked. It’s saved in .midcode/server.json:
{
"command": "php -S 127.0.0.1:$PORT -t public router.php",
"url": "http://127.0.0.1:$PORT"
}