#TIL : Never autostart XDebug in cli environment

TLDR;

Never ever enable xdebug.remote_autostart in cli

Xdebug is handy extension helps you debug your PHP code. But it slows the performance in cli mode, especially run PHP cli tool like composer or phpunit.

So please disable Xdebug in cli mode or set xdebug.remote_autostart=0 in INI file.

#TIL : try, catch and finally in PHP

We have to deal with exceptions every moment we touch PHP web development, and so please be carefully with running order of exception catching.

Here is an example

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

function a() {
try {
throw new Exception('dsads');
} catch (Exception $e) {
return 'b';
} finally {
echo 'c';
}
}

echo a();

Then the output is

1
cb

Than mean even return 'b'; runs, the finally code must be runned before function result passes out.

#TIL : realpath function

If you pass a non-exists path to function realpath, it returns empty string. So please don’t do something like :

1
2
3
function storage_path($folder) {
return realpath(__DIR__.'/storage/'.$folder);
}

if you expect it return full path of new folder !

#TIL : Persistent connection to MySQL

When a PHP process connects to MySQL server, the connection can be persistent if your PHP config has mysql.allow_persistent or mysqli.allow_persistent. (PDO has the attribute ATTR_PERSISTENT)

1
$dbh = new PDO('DSN', 'KhanhDepZai', 'QuenMatKhauCMNR', [PDO::ATTR_PERSISTENT => TRUE]);

Object destruction

PHP destruct an object automatically when an object lost all its references.

Example code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php

$x = null;

function klog($x) {
echo $x . ' => ';
}

class A {
private $k;
function __construct($k) {
$this->k = $k;
}

function b() {
klog('[b]');
}

function __destruct() {
klog("[{$this->k} has been killed]");
}
}

function c($k) {
return new A($k);
}

function d() {
c('d')->b();
}

function e() {
global $x;
$x = c('e');
$x->b();
klog('[e]');
}

function f() {
klog('[f]');
}

d();
e();
f();

Result:

1
[b] => [d has been killed] => [b] => [e] => [f] => [e has been killed] =>

Reducing PDO persistent connections in PHP long-run process (connect to multiples databases)

Instead of using a service object, we should use a factory design pattern for each job (each connection). PHP will close MySQL connection because it destructs object PDO. Then we can reduce the number of connections to MySQL at a same time.

I learned this case when implement a web-consumer (long-run process) to run database migration for multiples databases.

Before fixing this, our MySQL server had been crashed because of a huge opened connections.

Now, everything works like a charm !

Bring it on

#TIL : Using VarDumper in PHPUnit

The trick is writing the output to STDERR stream, I wrote a helper function below

1
2
3
4
5
6
7
function phpunit_dump() {
$cloner = new \Symfony\Component\VarDumper\Cloner\VarCloner();
$dumper = new \Symfony\Component\VarDumper\Dumper\CliDumper(STDERR);
foreach (func_get_args() as $var) {
$dumper->dump($cloner->cloneVar($var));
}
}

How to use it ?

1
2
3
4
5
// Something magic here :D

phpunit_dump($magic_var1, $magic_var2, $magic_of_magic);

// So much magic below, can't understand anymore

Magic

#TIL : F-cking stupid limit of input vars

Today, I tried to debug many hours to find out why my POST request missing some data (specify _token hidden field). :disappointed:

I tried to config NGINX and PHPFPM max_post_size, client_max_body_size but they still gone. After 2-3 hours searching on Google, I found the link from PHP.net,
it has a config value about limiting max input vars (default = 1000), so it causes the problem about missing data.

So I changed max_input_vars = 9999 in my php.ini and everything works like a charm. :smiley:

At least, I had a luck cos it doesn’t run my POST request when missing the CSRF token :grin: My data is save !!!

#TIL : Run built-in server via Docker

Docker is the fast and clean way to run Linux programs.

We can run a PHP project via PHP built-in server and Docker.

1
docker run -it -p 8080:8080 -v `pwd`:/code php:7 php -S 0.0.0.0:8080 -t /code/web /code/web/server.php

With server.php content is

1
2
3
4
5
6
7
8
9
10
11
<?php

$filename = __DIR__.preg_replace('#(\?.*)$#', '', $_SERVER['REQUEST_URI']);
if (php_sapi_name() === 'cli-server' && is_file($filename)) {
return false;

}

// Run application below
$app = new Application();
$app->run();