понедельник, 15 октября 2012 г.

Основная функция PHP-приложения. Классы Request и Response

Начинающие веб-разработчики (в том числе и я) не понимают основную функцию веб-приложения (не только php). А ведь это очень важно и в то же время очень просто. Основная функция веб-приложения получить запрос от клиента, подготовить ответ (здесь выполняются различные действия получения данных и их обработки), вернуть ответ клиенту.

Очень часто запрос и ответ реализуются в веб-приложениях в виде классов Request и Response. Тогда все что нужно будет приложению это определить путь запроса Request и вернуть соответствующий пути ответ Response. UML-диаграмма классов Request и Response представлена ниже:


Как мы видим в классе Request есть три метода:


  • getPathInfo() - метод получения пути запроса
  • find(key) - поиск параметра запроса по ключу key
  • has(key) - проверка существования параметра в запроса
Класс Response чуть побольше:
  •  Response(content, status_code, headers) - конструктор класса, принимает в качестве параметров один обязательный содержимое ответа и два не обязательных status_code (200 - по умолчанию), headers - массив HTTP-заголовков
  • setStatusCode(status_code) - из названия понятно что этот метод делает
  • setHeader(header) - то же
  • send() - отправка ответа на вывод
Также в классе Response есть три приватных свойства:
  • content - содержимое ответа
  • status_code - код ответа
  • headers - массив, содержащий HTTP-заголовки ответа
Привер реализации этих классов на PHP:

<?php
/**
 * File: Request.class.php
 * Created: 15.10.2012 12:30
 *
 * Класс Request
 */
class Request {
    /**
     * Получить путь запроса без строки запроса и имени выполняемого
     * скрипта
     * 
     * @return string
     */
    public function getPathInfo() {
        // получаем значения:
        // 
        // - URI без имени хоста
        // - строки запроса после ? 
        // - имя выполняемого скрипта
        $request_uri = $_SERVER['REQUEST_URI'];
        $query_string = $_SERVER['QUERY_STRING'];
        $script_name = $_SERVER['SCRIPT_NAME'];
        
        // извлекаем из URI путь запроса,
        $path_info = str_replace(
                '?' . $query_string, 
                '', $request_uri);
        $path_info = str_replace(
                $script_name, 
                '', $path_info);
        $path_info = trim($path_info, '/');
        
        // возвращаем результат
        return empty($path_info) ? '/' : $path_info;
    }
    
    /**
     * Поиск и получение значения параметра зпроса
     * по ключу
     * 
     * @param string $key               искомый ключ параметра запроса
     * @return mixed                    значение параметра 
     *                                  или null если параметр не существует
     */
    public function find($key) {
        if ( key_exists($key, $_REQUEST) )
            return $_REQUEST[$key];
        else
            return null;
    }
    
    /**
     * Проверяет существование параметра в запросе
     * по его ключу
     * 
     * @param string $key               проверяемый ключ
     * @return boolean
     */
    public function has($key)
    {
        return key_exists($key, $_REQUEST);
    }
}
?>

А теперь класс Response:

<?php
/**
 * File: Response.class.php
 * Created: 15.10.2012 13:17
 * 
 * Класс Response.
 */
class Response {
    private $content;
    private $status_code;
    private $headers;
    
    /**
     * Создает ответ сервера
     * 
     * @param string $content                       содержимое ответа
     * @param integer $status_code                  HTTP-статус код ответа
     * @param array $headers                        HTTP-заголовки ответа
     */
    public function __construct($content, $status_code = 200, $headers = array()) {
        // устанавливаем свойства класса
        $this->content      = $content;
        $this->status_code  = $status_code;
        $this->headers      = $headers;
    }
    
    public function setStatusCode($status_code) {
        $this->status_code = $status_code;
    }
    
    public function setHeader($header) {
        $this->headers[] = $header;
    }
    
    public function send() {
        // выслать код статуса HTTP
        header('HTTP/1.1 ' . $this->status_code);
        
        // отправить заголовки HTTP
        foreach ( $this->headers as $header )
            header($header);
        
        // отправить содержимое ответа
        echo $this->content;
    }
}
?>

Пример использования этих классов index.php:

<?php
// подключаем объявления классов
require_once 'class/Request.class.php';
require_once 'class/Response.class.php';

// определяем путь запроса
$request = new Request();
$path_info = $request->getPathInfo();

// создаем ответ в соответствии с путем запроса
if ( $path_info == '/' )
    $response = new Response('Main page');
else if ( $path_info == 'contact')
    $response = new Response('Contact page');
else
    $response = new Response('Not found 404', 404);

// возвращаем ответ клиенту
$response->send();
?>

Эти три файла служат хорошим костяком для веб-приложения.

1 комментарий: