I feel that the PHP static field is static merely throughout a request.
I have this code in my controller class:
static $a = 2;
public function debug()
{
var_dump(self::$a++);
var_dump(self::$a++);
}
No matter how many times I request debug, it outputs:
int 2
int 3
Very different from my knowledge on static in java.
Yes, static in PHP is "real" static.
What you observe is result of different application life cycle in PHP and Java.
In Java, web application run inside WebServer(HTTP server), which after initial class load, on following requests reuse what it already loaded. For this reason class(and static properties) initialization occurs only once in application life cycle.
In case of typical PHP web application it looks a bit different.
HTTP server is independent application which listens for HTTP requests and runs PHP on demand(not all HTTP requests must be passed to PHP). PHP is run as a separate process, request is passed and after answer is received process is discarded. Every request is handled by completely separate process. Classes(and static properties) are loaded and initialized from scratch every single time.
Below is simple(very) HTTP server written in PHP which will simulate how Java WebServer works.
<?php
class Server {
private $socket;
private $routes = [];
public function __construct($address, $port, $backlog = 5) {
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
throw new Exception("socket_create() failed: reason: " . socket_strerror(socket_last_error($socket)));
}
if (socket_bind($socket, $address, $port) === false) {
throw new Exception("socket_bind() failed: reason: " . socket_strerror(socket_last_error($socket)));
}
if (socket_listen($socket, $backlog) === false) {
throw new Exception("socket_listen() failed: reason: " . socket_strerror(socket_last_error($socket)));
}
$this->socket = $socket;
}
public function listen() {
while( ($requestSocket = socket_accept($this->socket)) !== false ) {
$this->handleRequestSocket($requestSocket);
}
throw new Exception("socket_accept() failed: reason: " . socket_strerror(socket_last_error($this->socket)));
}
public function registerController($url, $controller) {
$this->routes[$url] = $controller;
}
private function handleRequestSocket($socket) {
$buffer = "";
while(false !== ($part = socket_read($socket, 1024, PHP_NORMAL_READ))){
$buffer .= $part;
if(substr($buffer, -4) == "\r\n\r\n") break;
}
$buffer = trim($buffer);
echo "\n======\n$buffer\n======\n";
$response = $this->handleRequest($buffer);
if (null === $response){
socket_write($socket, "HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n");
} else {
socket_write($socket, "HTTP/1.1 200 OK\r\nContent-Length: ".strlen($response)."\r\n\r\n$response");
}
socket_close($socket);
}
private function handleRequest($raw) {
$lines = explode("\r\n", $raw);
$req = explode(" ", $lines[0]);
$method = $req[0];
$url = $req[1];
if(isset($this->routes[$url])) {
return (string) (is_callable($this->routes[$url]) ? $this->routes[$url]($raw) : $this->routes[$url]);
}
return null;
}
}
class ControllerWithStatic {
private static $static = 0;
public function handle() {
return "Hello from static: " . (self::$static++) . "\n";
}
}
$server = new Server($argv[1], $argv[2]);
$c = new ControllerWithStatic();
$server->registerController("/", "Hello world\n");
$server->registerController("/closure", function(){return "Hello world from closure\n";});
$server->registerController("/static", [$c, 'handle']);
$server->registerController("/static2", function(){
return (new ControllerWithStatic())->handle();
});
$server->listen();
Run it using
php server.php HOST PORT
e.g.
php server.php 127.0.0.1 8080
Now open in your browser http://127.0.0.1:8080/static or http://127.0.0.1:8080/static2 and you will get
Hello from static: 0
Hello from static: 1
Hello from static: 2
...
Number will be increasing as long as you don't restart server.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With