How THT Compares to PHP
This page is a mostly-complete list of differences between THT and PHP.
For more background behind these changes, see the Design Notes.
Syntax
- No
<?php
tags. - No semicolons. One statement per line. Note
- No outer parens in control statements.
if true {...}
Note - Shorter function keyword
fun
. - No parens for empty function arguments.
fun foo {...}
- Introduces template functions for output.
tem myHtml { ... }
- Template expressions use
{{ ... }}
instead of<?= ... ?>
- Dot operator
.
for method calls.$foo.method()
Note - Separate Map and List types, instead of one Array type.
- JS literal notation for Maps.
{ key: value }
Note - Quote fences
'''
for multi-line strings. - Strings are single-quote only.
'my string'
. Note - Regex strings are 1st class objects.
rx'\d+'
No double-escaping slashes. - No variable references
&$foo
. - Natural 1-based indexing for Lists and Strings. Note
- Can use negative indexes to count from end of List.
$list[-1]
- List append syntax changed from
$list[] = $el
to$list #= $el
. - String concatenation operator changed from
.
to~
. - Only
//
for line comments. No#
. - Nested block comments
/* ... */
are supported. - No C-style
for
loop. Useforeach
instead. Note - No C-style
while
loop. Useloop
instead. Note switch
replaced withmatch
. (coming soon)- Bitwise operators are prefixed with
+
. e.g.+|
,+&
Note - Boolean arguments must be named via an Option Map.
- Closures capture all outer variables. No need for the
use
keyword.
Safety
- Each THT file has its own namespace. No implicit globals.
- Variables and functions are validated at compile time.
- No “variable variables”. (e.g.
$$myVar
) - Full stack trace on all runtime errors.
- PHP-level errors and warnings are fatal.
- Standard library uses exceptions, not error codes.
- No database, file, or system calls allowed within templates.
- All string methods support UTF-8 via
mbstring
. - No
===
. Instead,==
does a strict comparison. - The only falsey values are:
false
,0
,''
,{}
,[]
,null
- String zero
'0'
does not evaluate to booleanfalse
. - String concactenation only works with strings, numbers, & booleans.
- Booleans stringify as
'true'
and'false'
instead of'1'
and''
- Need to use
:=
for assignment inside of conditionalsif a := 1
- Declared argument types are always run in strict mode.
- No warning suppression via
@
. - Error if too many arguments are passed to a function.
- Function arguments are non-nullable by default.
Consistency
- Standard library is organized into modules and classes.
- Standard library is curated, with more consistent interfaces.
- Function names are case sensitive.
- Only camelCase format for variable and function names. Note
- Default charset is UTF-8.
- Date methods default to UTC timezone.
- Numeric database results are returned as numbers, not strings.
- Unified code formatting via the Format Checker.
Convenience
New Syntax
||=
and&&=
for OR and AND assignment.||:
and&&:
for OR and AND value coalescing.- One-line block syntax. e.g.
if true: $a = 1
- Lambda expressions via
x{...}
- Quoted lists via
q[...]
- Self-assignment via
$str = .upperCase()
>>
for quick printing.
See Shortcuts
HTML Syntax
- Closing tags do not need a label. e.g.
</>
- Selector style tags. e.g.
<h1.myclass>
- Auto-closing line tags. e.g.
<h1> My Heading
See HTML-C Shortcuts
Performance
- Assets & images are automatically optimized, reducing sizes by up to 70%.
- Images and iframes are automatically set to loading=“lazy”.
- HTML document is structured to include
script
tags at the bottom, andstyle
tags at the top. - Perf Panel provided for benchmarking.
- Cache module provided.
Security
Strings
- Introduces TypeStrings to prevent injection attacks.
- Db module requires TypeStrings. Uses PDO placeholders underneath.
- Web, File, and System modules escape output automatically. (XSS)
- All Litemark hyperlinks add
rel="nofollow noopener"
to deter link spam and tabnapping.
Files
- File functions do not work on URLs.
- Source files are hosted outside of Document Root.
- Only source files in the
pages
dir are directly executable. Module files can not be executed directly.
Input
- Input data (GET & POST) requires the website to be served as HTTPS.
- Input from different HTTP methods (GET, REQUEST, etc.) are not intermixed.
- Input data is only accessible through validation methods.
- Form fields are validated on both the server and client.
- Input data is stripped of NULL bytes to prevent Null Byte Poisoning.
- File uploads are validated and sandboxed with random names.
- Uploaded images are re-processed and resized, stripping possible attack payloads.
Response
- Default HTTP response headers are set to secure defaults.
- CSP response headers added to prevent client script injection.
- HSTS response headers added to all non-localhost apps.
- Redirects to external URLs are restricted.
Cross Origin
- Non-GET requests are protected with a per-request CSRF token.
- Non-GET requests must come from the local domain, by default.
- Cross-origin requests are protected with Fetch metadata.
Sessions
- All cookie data is kept server-side. Uses a single client-side cookie ID.
- Session config has secure defaults.
Passwords / Crypto
- Randomization functions use cryptographically strong methods.
- Password inputs are automatically hashed with
bcrypt
and wrapped in a Password object. - Password checks use
password_verify
to prevent timing attacks. - Password checks are rate-limited to limit brute force attacks.
Config
- Database config (with passwords) is stored in a local-only config file.
- THT & PHP config are read-only, not changeable at runtime.
Auditing
- High-risk methods are prefixed “xDanger-” for easier auditing.
- Internal THT security functions are in a single module for easier auditing.
Misc
- High risk functions like
eval
are forbidden inPhp.call
. - JSON.decode does not allow INF or -INF. (JSON interop)