2016-12-29 57 views
2

我觉得PHP静态字段在整个请求过程中都是静态的。PHP静态字段是否真实静态?

我有我的控制器类的代码:

static $a = 2; 

public function debug() 
{ 
    var_dump(self::$a++); 
    var_dump(self::$a++); 
} 

无论多少次,我请求debug,它输出:

int 2 
int 3 

从Java中我的static知识有很大不同。

+3

静态并不意味着不变。这意味着它属于类而不是该类的实例化对象。至于“在整个请求中仅仅是静态的”:每个请求都是PHP的一个新实例/线程,如果你想在请求中保存变量,你必须使用会话('__ SESSION')或某种其他存储(数据库,文件,...)。 – ccKep

+1

PHP中的静态属性与Java中的静态属性完全相同。 – Timurib

+1

@Amruthls。我认为这是不同的问题。 ccKep提到的“每个请求都是PHP的新实例/线程”,可能是我的问题的答案。 – bijiDango

回答

1

是的,PHP中的静态是“真实”的静态。

您观察到的是PHP和Java中不同应用程序生命周期的结果。

在Java中,Web应用程序在WebServer(HTTP服务器)内部运行,在初始类加载之后,以下请求重用它已加载的内容。由于这个原因,类(和静态属性)初始化在应用程序生命周期中只发生一次。

在典型的PHP Web应用程序中,它看起来有点不同。

HTTP服务器是一个独立的应用程序,它监听HTTP请求并按需运行PHP(并非所有的HTTP请求都必须传递给PHP)。 PHP作为一个单独的进程运行,请求被传递并且在接收到应答之后,进程被丢弃。每个请求都由完全独立的进程处理。类(和静态属性)每次都从头开始加载和初始化。

下面是简单的(非常)用PHP编写的HTTP服务器,它将模拟Java WebServer的工作方式。

<?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(); 

运行它使用

php server.php HOST PORT 

例如

php server.php 127.0.0.1 8080 

现在打开你的浏览器http://127.0.0.1:8080/statichttp://127.0.0.1:8080/static2,你会得到

Hello from static: 0 
Hello from static: 1 
Hello from static: 2 
... 

数量将只要你不重新启动服务器增加。