Do's and Don'ts
Don't overuse macros. They're neat, but can obstrue debugging once turned into lengthy substitution code.
- Trivial code generation tasks are also provided by most IDEs. Unless you need customizations and iterative extensibility, just use basic code templates / copy + paste.
- Phrep isn't meant as PHP/HTML templating engine. Can't stress this enough. While yes, you may simplify even Twig templates further; it's important to use the right tool for the job in the first place.
- Same goes for localization. Preprocessor constants are even worse than in-application constants. Just use any gettext-style scheme.
While
#ifdef
,#include
and friends can simplify project packaging and configurability, it's not always suitable for everyday web apps or genericized libraries.- Few projects need anything but classic/olden runtime configuration options (config.php, SQL table, ini, json, yaml) or in-code library setup (constructor params, plain props or constants).
- Introducing a make script for PHP projects should add significant advantages. Else you're just introducing a new dependency where historically there wasn't - and complicate its use for newcomers.
- PHP, albeit less so than Ruby or Python, already provides heaps of dynamic runtime capabilities. For example variable variables are a core feature of PHP. And with some care even dynamic method or class creation are often an option. Don't use preprocessing just to eschew newbie-focused "Xyz is evil" and microoptimization memes.
Yet feature branching is actually pretty simple with existing tools. For example
diff
can not just create patches, but also inject macroprocessor#ifdef
rules per -D flag:diff -D PKG_PREMIUM page.php page-extras.php > page.src
That'll generate a source file suitable for
phrep
or any preprocessor. Oftentimes works for diffing multiple variants even. Which can be simpler than managing diversifying VCS branches for each variation.And of course code templating is a practical phrep use case.
- For example the slim PARAMETERIZE@() macro might be usable as-is for many database APIs. It allows to manage a terser table gateway collection.
- Same goes for
HTML@()
whenever inline HTML shortcuts reduce code bloat. - Macros can also add extra readability to generated output. For example
a simple
RX@()
handler that auto-comments regexps (e.g. via YAPE), or perhaps aPSIX@()
wrapper compacting regexps to PCRE syntax.
Foremost code templating can help with swapping out a concrete implementation without having to adapt source definitions.
Consuming C header
.h
files is an accidential by-feature of phrep. Albeit the use cases within PHP are pretty rare, since most system calls are abstracted away.- However
#include <errno.h>
could be used withfsockopen
s $errno instead of plain boolean checks. - Or
#include <ext/mysqlnd/mysqlnd_priv.h>
bound for a few PDO error codes likeCR_OUT_OF_MEMORY
.
But if it's just a few constants, copy+pasting them in or just codifying magic values remains preferrable to preprocessing.
- However
Making authorization-related code paths preprocessor-dependant is a triple edged sword. - Most PHP frameworks tightly integrate authorization facilities already. And therefore should just be left to themselves.
Adding conditional
#ifdef
sections to cement code paths and reduce runtime ambiguity is tempting, but in fact just adds another configurability layer. If code is made dependant on preprocessing before deployment, then at least always add fallback code:#ifdef AUTH_CLIENT_CERT $perm->default = SSLAuthPerm::from($_SERVER->list["SSL_*"]); #else ł(":auth", ":crit", "unconfigured", ":trace"); crash(); #endif
Personally I'd be very wary of such uses. Getting the basics right isn't difficult nowadays, which is why most security woes arise from unobvious logic faults. → Complexity doesn't abet security.
The primary use case for preprocessing of course are packaging tasks. Phrep for instance works as library, or as CLI utility. To simplify distribution it's just merged into a single script then:
#ifdef PKG_COMBINED #include <macro.php> #endif
Which is why stripping PHP tags is an
#include
directive default.A common use pattern for directives are conditional debug builds. Which can benefit PHP code just as well (in place of inline workarounds), such as:
#ifdef USE_DEBUG #define DEBUG(x) print_r(x) #else #define DEBUG // #endif
Using
DEBUG($var);
is somewhat more visual than literring plainprint_r
calls. (That regularily are forgotten about then).Same goes for logging. It's quite uncommon for libraries to have any preparation for application level logging. If, it's at best an abstract interface which rarely gets utilized.
With a plain
#define LOG(msg...)
binding to a concrete implementation it's heaps simpler, but doesn't complicate instantion when unneeded.phrep itself also works for simple search and replace jobs like
phrep -D strpos=stripos -i file.php -o=-i
Or even
#define mysql_query die
.
Just saying.