This might feel familiar
PHP can embed server-side code in HTML. Cow uses a similar approach, but the code inside a Cow page is JavaScript or TypeScript. See the PHP introduction for PHP’s model.
<?php $name = 'herd'; ?>
<h1>Hello, <?= htmlspecialchars($name) ?>!</h1><?js const name = 'herd' ?>
<h1>Hello, <?= name ?>!</h1>Both examples produce HTML for the browser. Cow's
<?= ?> escapes text for HTML output, so it needs no htmlspecialchars(). To print HTML that your code built, use raw(). HTML escaping does not make a value safe inside JavaScript, CSS, or URLs.What stays the same
- The file is the URL.
about.cowanswers/about. - Every request starts fresh. A variable that you set in one request is gone in the next, as in PHP.
nullprints nothing.<?= title; ?>works with the trailing semicolon.- A
//comment ends at?>. The final?>in a file is optional. - Edit a page, refresh the browser, and see the change. No build step.
PHP to Cow
Find the PHP that you know on the left. The Cow equivalent is on the right.
| In PHP | In Cow | Guide |
|---|---|---|
<?php ... ?> | <?js ... ?> or <?ts ... ?> | Language |
<?= htmlspecialchars($name) ?> | <?= name ?> (escapes automatically) | Language |
<?= $html ?> | <?= raw(html) ?> | Language |
$_GET['name'] | req.get('name') | API reference |
$_POST and $_FILES | await req.formData() | Forms & uploads |
$_SERVER['REQUEST_METHOD'] | req.method() | API reference |
include 'header.php'; | await include('./_header.cow', { title }) | Modules & includes |
require 'functions.php'; | import { greet } from './_functions.cow' | Modules & includes |
header('Location: /thanks'); | res.redirect('/thanks') | Responses & files |
http_response_code(404); | res.status(404) | API reference |
echo json_encode($data); | res.json(data) | Responses & files |
session_start(); and $_SESSION | await session(db, req, res), then visitor.data | Cookies & sessions |
setcookie() and $_COOKIE | setCookie(res, ...) and cookies(req) | Cookies & sessions |
password_hash() and password_verify() | hashPassword() and verifyPassword() | Cookies & sessions |
| PDO with prepared statements | db.all(sql, [values]) from cow:sqlite | SQLite |
phpinfo(); | cow.info() | Errors & debugging |
php -S 127.0.0.1:8000 | cow site | Get started |
php -l page.php | cow check site | Errors & debugging |
What changes
Use
const, let, JavaScript objects, async/await, and JavaScript imports. Use <?ts when you want TypeScript syntax.<?= ?> escapes what it prints, where PHP prints it unchanged. Wrap HTML that your code built in raw().Cow supplies its own request, response, session, and database APIs. It does not run PHP code or PHP packages. npm support is subject to Cow’s compatibility limits.
Serve a directory with
cow site. Cow provides the web server and maps page files to URLs.A few differences can surprise you:
- An include does not see the variables of the page that calls it. Pass values as the second argument, and read them from
locals.include()is asynchronous, soawaitit. - There are no superglobals. Pages receive
req,res, andcow. To use them in an imported helper, pass them as arguments. - Cow keeps the line break after a closing
?>, where PHP removes it. Browsers ignore the extra blank line in HTML. echo('a', 'b')joins its values with a space. PHP'secho 'a', 'b';does not.- To keep a file private, start its name with an underscore, such as
_db.cow. Cow never serves it, so you do not need a folder outside the web root.