[Question]
  [
What general tips do you have for golfing in PHP? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to PHP (e.g. "remove comments" is not an answer). Please post one tip per answer.
  
[Answer]
**Understand how variables and whitespace interact with PHP's language constructs.**
In my (admittedly short) time golfing, I have found that PHP's language constructs (e.g. echo, return, for, while, etc) behave in a less-than-intuitive way when interacting with variables and whitespace.
`echo$v;`, for example, is perfectly valid, as are `return$v;` and other similar constructs. These small reductions in whitespace can lead to a significant cumulative decrease in length.
Keep in mind, though, that variables **before** language constructs require a space after, as in the following example:
```
foreach($a AS$b){}
```
Because `AS` is a language construct, a space is not required before the variable `$b`, but if one were to omit the space *before it*, resulting in `$aAS`, this would be parsed as a variable name and lead to a syntax error.
[Answer]
**Use strings wisely.**
This answer is two-fold. The first part is that when declaring strings, you can utilize PHP's implicit conversion of unknown constants to strings to save space, e.g:
```
@$s=string;
```
The `@` is necessary to override the warnings this will produce. Overall, you end up with a one-character reduction.
is that sometimes, it may be space effective to set a variable to the name of an often used function. Normally, you might have:
```
preg_match(..);preg_match(..);
```
But when golfing, this can be shortened easily to:
```
@$p=preg_match;$p(..);$p(..);
```
With only two instances of "preg\_match", you're only saving a single character, but the more you use a function, the more space you will save.
[Answer]
You don't always need to write out conditional checks. For example, some frameworks use this at the top of their files to block access:
```
<?php defined('BASE_PATH')||die('not allowed');
```
Or in normal functions
```
$value && run_this();
```
instead of
```
if($value) { run_this(); }
```
[Answer]
## Use short array syntax
Since PHP 5.4, arrays can be declared using square brackets (just like JavaScript) instead of the `array()` function:
```
$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');
```
It will save five bytes.
---
But It may cost bytes if you have "holes" in an associative array:
```
$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];
```
the disadvantage hits a little later if you can fill the holes with "empty" values:
```
// saves two bytes over array()
$arr=[0,1,0,3,0,5];
// but for a larger array
$arr=[0,1,0,3,0,5,0,7,0,9,0,11];
// costs two byte more than
$arr=array(,1,,3,,5,,7,,9,,11);
```
[Answer]
## Use ${0}, ${1}, ${2}, ... instead of $a[0], $a[1], $a[2], ...
Unless you're performing an array manipulation, most references to an array index `$a[$i]` can be replaced with simply `$$i`. This is even true if the index is an integer, as integers are valid variable names in PHP (although literals will require brackets, e.g. `${0}`).
Consider the following implementation of the Rabonowitz Wagon spigot:
```
3.<?for(;$g?$d=0|($a[$g]=$d*$g--/2+($a[$g]?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);
```
This can be improved by 6 bytes, simply by replacing both array references `$a[$g]` with `$$g` instead:
```
3.<?for(;$g?$d=0|($$g=$d*$g--/2+($$g?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);
```
[Answer]
**Learn a large subset of the library functions**.
PHP's library is pretty huge and provides a ton of convenient functions that can greatly shorten various tasks. You could just search every time you try to do something, but beyond wasting time you might not find anything that matches your particular search. The best way is just to get familiar with the library and memorize function names and what they do.
[Answer]
Running functions inside strings.
Try this:
```
$a='strlen';
echo "This text has {$a('15')} chars";
```
Or try this:
```
//only php>=5.3
$if=function($c,$t,$f){return$c?$t:$f;};
echo <<<HEREDOCS
    Heredocs can{$if(true,' be','not be')} used too and can{$if(<<<BE
{$if(true,1,0)}
BE
,'','not')} be nested
HEREDOCS;
//Expected output: Heredocs can be used too and can be nested
```
This only works with strings using `""` and heredocs (DON'T make confusion with nowdocs).
Using nested functions is only possible inside nested heredocs (or you will run into parse errors)!
[Answer]
## by any other name ... function aliases
use ...
* `join` instead of `implode`
* `chop` instead of `rtrim` (`chop` in PERL is different!)
* `die` instead of `exit`
* `fputs` instead of `fwrite`
* `is_int` instead of `is_integer` or `is_long`
* `is_real` instead of `is_float` or `is_double`
* `key_exists` instead of `array_key_exists`
* `mysql` instead of `mysql_db_query`
... to name the most important aliases.
Take a look at <http://php.net/aliases> for more.
[Answer]
**looping through strings**
can be done with 26 bytes or with 24 down to 18:
```
foreach(str_split($s)as$c)  # A) 26 - general
for($p=0;a&$c=$s[$p++];)    # B) 24 - general
for($p=0;$c=$s[$p++];)      # C) 22 - if $s has no `0` character
for(;a&$c=$s[$p++];)        # D) 20 - if $p is already NULL or 0 (does NOT work for false)
for(;$c=$s[$p++];)          # E) 18 - both C and D
for(;$o=ord($s[$p++]);)     # F) 23 - work on ASCII codes, if $s has no NULL byte and D
for(;~$c=$s[$p++];)         # G) 19 - if $s has no chr(207) and D
```
---
`$a&$b` does a bitwise AND on the (ascii codes of) the characters in `$a` and `$b`  
and results in a string that has the same length as the shorter of `$a` and `$b`.
[Answer]
# fun with typecasts
* `!!$foo` will turn any truthy value to `true` (or `1` in output), falsy values (0, empty string, empty array) to `false` (or empty output)  
This will rarely be needed in code golf, for in most cases where you need a boolean, there is an implicit cast anyway.
* `(int)$foo` can be written as `$foo|0` or `foo^0`, but may need parentheses.  
For booleans and strings, `$foo*1` or `+$foo` can be used to cast to int.
* Unlike most other languages, PHP handles strings with numeric values as numbers. So if you have any string that contains a number you have to calculate with, just calculate.
* The other way does *not* work: To multiply any number in a variable with `10`, you could append a zero: `*10` -> `.0`. But in this case, PHP will take the dot as decimal point and complain. (It´s different though if you have a variable amount of zeroes in a string.)
* To turn an array into a string, use `join` instead of `implode`.  
If you don´t need a delimiter, don´t use it: `join($a)` does the same as `join('',$a)`
* Incrementing strings: The most amazing feature imo is that `$s=a;$s++;` produces `$s=b;`. This works with uppercase and lowercase characters. `$s=Z;$s++;` results in `$s=AA;`.  
This also works with mixed case: `aZ` to `bA`, `A1` to `A2`, `A9` to `B0` and `z99Z` to `aa00A`.  
Decrement does *not* work on strings. (And it does not on `NULL`).  
Back in PHP 3, `$n="001";$n++;` produced `$n="002";`. I am a little sad they removed that.
Whatever you golf: **always have the [operator precedence table](http://php.net/manual/language.operators.precedence.php) at hand.**
[Answer]
# Use shorttags
In normal code, it's good practice to use `<?php` and `?>`. However, this is *not* normal code - you are writing a code golf code. Instead of `<?php`, write `<?`. Instead of `<?php echo`, write `<?=`. Don't type `?>` at end - it's completely optional. If you need `?>` for some reason (for example to output text, and it's shorter somehow, or something, don't put a semicolon before it - it's not needed, as `?>` implies semicolon.
Wrong (definitely too long):
```
<?php echo ucfirst(trim(fgets(STDIN)));?>s!
```
Correct:
```
<?=ucfirst(trim(fgets(STDIN)))?>s!
```
[Answer]
# array\_flip vs array\_search
use 
```
array_flip($array)[$value]
```
instead of
```
array_search($value,$array)
```
to save 1 Byte in arrays where the occurence of each value is unique
[Answer]
# Use ternary operators
```
if(a==2){some code;}else{some other code;}
```
can be abbreviated to this:
```
(a==2?some code:some other code);
```
Shorter, huh?
[Answer]
# Combining `for` loops
Suppose you have code of the following form:
```
for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;
```
this can generally be re-rolled in the following form:
```
for($pre1; $cond2 • $post2 || $cond1 • $pre2 • $post1; ) $code;
```
where `•` represents a generic combining operator. This usually results in an byte count reduction, but will likely require some creativity. `$cond2` will need to be written so that it fails the first time through. `$post1` should also fail to execute the first time, although it may be easier to refactor beforehand so that `$post1` is not present.
If you're working with three or more nested loops, you can also combine two first, and then combine that to another, and so on. I find that it has generally been easier to combine from the inside outwards.
---
As an example, consider the following solution to the [H-carpet fractal](https://codegolf.stackexchange.com/q/157664/4098) (*97 bytes*):
```
for(;$i<$n=3**$argn;$i+=print"$s\n")for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
```
This can be reformulated in the following way:
```
for(;($i+=$e&&print"$s\n")<$n=3**$argn;)for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
```
*`$e&&print` prevents `print` on first iteration, and also does not increment `$i`.*
and finally (*93 bytes*):
```
for(;$H>$e*=3or$e=($i+=$e&&print"$s\n")<${$s=H}=3**$argn;)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
```
*`$H>$e*=3` will fail the first time as both variables are undefined.*
[Answer]
**line breaks**  
if the output requires line breaks, use a physical line break (1 byte) instead of `"\n"`  
This also gives you a possible benefit to chose between single and double quotes.
[Answer]
### Associative arrays can be merged with the `+` operator.
Instead of:
```
$merged = array_merge($a, $b);
```
Use:
```
$merged = $a + $b;
```
Note the `+` operator works with indexed arrays as well, but probably doesn't do what you want.
[Answer]
**some interesting facts on [variable variables](http://php.net/variables.variable)**
I just had to share them (even before I [verified](https://codegolf.stackexchange.com/a/105831#105831) that at least one of them helps golfing):
* Use letters: `$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";` prints `1,2`  
but other arithmetic operations do not work with letters.
* As [primo mentioned earlier](https://codegolf.stackexchange.com/a/86394#86394), you can use pure numbers as variable names:  
`$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};` prints `543`.
* You can not only use `[0-9a-zA-Z_]` for variable names, but EVERY string:  
`$x="Hello!";$$x="Goodbye.";echo${"Hello!"};` prints `Goodbye.`.
* But: Everything but `[a-zA-Z_][a-zA-Z_0-9]*` as variable names requires braces for literal use.
* With no variables defined, `$$x=1` sets `${NULL}`, which is the same as `${false}` and `${""}`.
* `$a=1;$$a=5;` does not only set `${1}`, but also `${true}`.
* one more, the weirdest one I´ve found so far: Try `$a=[];$$a=3;echo${[]};`. Yes, it prints `3`!
The reason for most of this: variable names are always evaluated to strings.  
(Thanks @Christoph for pointing out.)  
So, whatever you get when you `print` or `echo` the expression, that´s what you get as variable name.
[Answer]
## PCRE-Related (Regex)
### Functions
If the pattern always matches the subject string (thanks to the comment by @Deadcode), instead of `preg_replace`, you can use `preg_filter` (1 byte shorter).
### Patterns
Sometimes [espace sequences](https://www.php.net/manual/en/regexp.reference.escape.php) are useful, like `\d`, `\w`, `\W`, `\s` or `\S`.
### Examples
Filter non-alphabet characters:
```
preg_replace("/[^a-z]/i", "", $s);
preg_filter("/\W|\d/", "", $s); // 3 bytes shorter
```
[Answer]
**avoid quotes where possible**
PHP implicitly casts unknown words to literal strings.
`$foo=foo;` is the same as `$foo='foo';` (assuming that `foo` is neither a key word or a defined constant): `$foo=echo;` does not work.
BUT: `$p=str_pad;` does; and `$p(ab,3,c)` evaluates to `abc`.
Using string literals without quotes will yield a Notice for `Use of undefined constant`; but that won´t show if you use the default value for `error_reporting` (CLI parameter `-n`). 
[Answer]
# array\_merge vs array\_push
```
array_push($a,...$b); 
```
is one byte shorter than
```
$a=array_merge($a,$b);
```
Does not work the same with Associative arrays
[variable-arg-list PHP >5.6](http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list)
[Answer]
# Use boolean operators instead of `strtoupper()` and `strtolower()`
If you're working exclusively with strings consisting of alphabet characters, you can use boolean operators to change them to uppercase or lowercase with fewer keystrokes than PHP's built-in functions.
### Example:
```
// Convert lowercase to uppercase
$s = "g";
echo strtoupper($s);  // Outputs 'G', uses 20 characters
echo~" "&$s;          // Outputs 'G', uses 12 characters
// Convert uppercase to lowercase
$s = "G";
echo strtolower($s);  // Outputs 'g', uses 20 characters
echo$s^" ";           // Outputs 'g', uses 11 characters
// Switch case of each character
$s = "Gg";
echo$s^"  ";          // Outputs 'gG', uses 12 characters
```
Things are a little trickier for strings of arbitrary length, but the `&` and `^` operators will truncate the result to the length of the shorter input string. So for example, if `$W` is a string of spaces at least as long as any input `$s`, then `~$W&$s` is equivalent to `strtoupper($s)`, and `$s|$W^$s` is equivalent to `strtolower($s)` (whereas `$s|$W` by itself will produce a string with additional spaces unless `$s` and `$W` are of equal length).
[Answer]
# Arrow functions in PHP 7.4
PHP 7.4 is on RC2 version now and hopefully will be released in about 2 months. List of new features are [here](https://www.php.net/manual/en/migration74.new-features.php) (this page can actually be updated when 7.4 is released). In 7.4, finally PHP has got the arrow functions, so not only function answers can be shorter now, but also passing closures to other functions can be a lot shorter too. Here are a few examples:
**Return input + 1:**
Anonymous function (closure) - 25 bytes - 
[Try it online!](https://tio.run/##K8go@G9jX5BRwMWlkmb7P600L7kkMz9PQyVPs7ootaS0KE8lT9vQuva/NRdXanJGvoJKmoaRpvV/AA "PHP – Try It Online")
```
function($n){return$n+1;}
```
Arrow function - 12 bytes - 
[Try it online!](https://tio.run/##K8go@G9jX5BRwMWlkmb7Py1PQyVP09ZOJU/b8L81F1dqcka@gkqahpGm9X8A "PHP – Try It Online")
```
fn($n)=>$n+1
```
**Multiply items of first input (array of ints) by second input (int):**
Anonymous function (closure) - 72 bytes - 
[Try it online!](https://tio.run/##RcqxDoJADADQ/b6CoUNruojAcho/xBhSCBcYrE29G4zh28@RNz9brV7vtloIkG41FZ3z9lYEYVD6@ZKLayPu8h1fYniEicpnwSPBdAKNO4NQ3GsMwXzTPDpCwseZW75wxz0PT25aolj/ "PHP – Try It Online")
```
function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}
```
Arrow function - 38 bytes - 
[Try it online!](https://tio.run/##Fcg7DoAgDADQnVM4dADTRfwsih7EGFIGgoNNQ1w8fdU3PimiyyZFjIEcNLMFQmAXVqqVnniR2D/TN5BaYARyOhsj9eQ7VgvZ7h167HHAEacDG@/crC8 "PHP – Try It Online")
```
fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)
```
Did you notice that `$n` is accessible in the inner function without a `use $n` statement? Yeah that is one of the arrow function features.
---
As a side note, I could not get arrow functions to work recursively (call the same arrow function inside itself), because we cannot give them a name and storing them as a closure in a variable like `$f` doesn't make `$f` accessible withing itself (sad). So this example **doesn't work** and using `$f` in first line causes a fatal error:
```
$f=fn($n)=>$n?$f($n-1):0;
$f(5); // Causes error: "PHP Notice: Undefined variable: f" + "PHP Fatal error: Uncaught Error: Function name must be a string"
```
But calling an arrow function withing a different arrow function works:
```
$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2
```
[Answer]
Regarding file I/O:
Linking to another [related question](https://codegolf.stackexchange.com/q/5713/3862), the answers to which fit here.
[Answer]
### Use negative indexes to reference the end of a string
If you need the last character in a string, you can use the array reference method, and provide a negative index:
```
$lastChar = $string[-1];
```
This also works for functions like `substr()`:
```
$lastFour = substr($string, -4);
```
[Answer]
### Directly dereference arrays returned from functions.
E.g., instead of this:
```
$a = foo();
echo $a[$n];
```
You can do:
```
echo foo()[$n];
```
This works with methods too:
```
echo $obj->foo()[$n];
```
You can also directly dereference array declarations:
```
echo [1, 2, 3, 4, 5][$n];
```
[Answer]
### Use `end()` instead of `array_pop()`
The `end()` function doesn't just move the internal pointer to the end of the array, it also returns the last value. Note of course that it doesn't *remove* that value, so if you don't care what the array contains afterwards, you can use it instead of `array_pop()`.
[Answer]
# double array\_flip vs in\_array vs array\_unique
in this [special case](https://codegolf.stackexchange.com/questions/116786/find-the-translation-table) a double array\_flip saves 10 Bytes 
`($f=array_flip)($k=$f($c)))` remove all double values in the array
and I have dropped this `$c=[],` , `|in_array($o,$c)` and replace `array_keys($c)` with `$k` 
```
for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,($f=array_flip)($k=$f($c)))==$y # boolean replacement string 1 equal to string 2
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases
```
[Online Version](http://sandbox.onlinephpfunctions.com/code/15c1d9bddf3b7132a6998e6563b08e728dff0343)
against
```
for($c=[],[,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o|in_array($o,$c)?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,$c)==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases
```
[Online version](http://sandbox.onlinephpfunctions.com/code/806278a6c8ec65d86984b234f7d3f0bec8017477)
against array\_unique it saves 2 Bytes
```
for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,array_unique($c))==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases
```
[Online Version](http://sandbox.onlinephpfunctions.com/code/3bcf8625977f94b64cdea19bf39fd2c3cabd866a)
After finding a bug in this program and replacement `$x[$i]==$o?:$c[$x[$i]]=$o` to `($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p` the double array\_flip was not necessary longer 
[Answer]
## Return two copies of an expression
If you want to get two copies of the result of an expression, you can use this:
```
$v.$v=expr
```
But it won't be shorter than the more straightforward `($v=expr).$v` if you need to append more things to the result.
For 4 copies:
```
$v.$v.=$v=expr
```
You cannot use it to get 3 copies.
[Answer]
**intersecting strings**
Have you ever used  
`join("DELIMITER",str_split($s))` (31 bytes) or even  
`preg_replace(".","DELIMITER",$s)` (32 bytes)  
?
There´s a builtin for that:
Try `chunk_split($s,1,"DELIMITER")` (29 bytes).
---
If you omit the third parameter, [`chunk_split`](http://php.net/chunk-split) will use `\r\n`; that can save you 7 or 8 bytes.
But beware: `chunk_split` also appends the delimiter to the string,  
so you may not get exactly what you want.
(If you don´t provide the chunk length, it will use 76. Rather unusual for code golf, but who knows.)
[Answer]
# unset() vs INF
In a case search for a minimum in an array you can use instead of 
```
unset($var[$k]);
$var[$k]=INF;
```
to save 3 Bytes
]