Статьи

Обработка HTML на стороне сервера с использованием phpQuery

В наших повседневных задачах веб-разработки нам необходимо работать как с клиентским, так и с серверным кодом. Мы пишем бизнес-логику с использованием PHP и генерируем HTML для отображения в браузерах пользователей. Затем мы используем фреймворки, такие как jQuery или Prototype, для обеспечения интерактивности на стороне клиента.

Теперь подумайте, как вы можете изменить и манипулировать сгенерированным HTML-кодом, используя PHP-код на стороне сервера. phpQuery — это идеальное решение, которое придет вам в голову. Если вы не слышали о phpQuery, вас может заинтересовать эта статья, поскольку я собираюсь дать вам краткое введение в phpQuery и объяснить, как вы можете использовать его в реальных проектах.

Что такое phpQuery

phpQuery — это цепочечный API-интерфейс на основе объектной модели документов (DOM), управляемый селектором на стороне сервера, на основе библиотеки JavaScript jQuery.

Это определение дано на официальной странице проекта phpQuery . Если вы использовали jQuery, у вас будет представление о том, как он может упростить многие задачи, требующие манипулирования DOM. phpQuery предоставляет точно такие же функциональные возможности, которые будут использоваться внутри вашего PHP-кода на стороне сервера. Вы можете попрощаться с генерацией неопрятного HTML-кода, используя операторы echo и аналогичные методы.

У вас будет доступ к большинству функций, предоставляемых jQuery в phpQuery, которые в целом можно разделить на 4 задачи, упомянутые ниже:

  • Создание элементов DOM
  • Выбор и управление элементами
  • Итерация по DOM
  • Распечатка вывода в браузер

Вы можете выполнять задачи, используя функции, предоставляемые phpQuery, который известен как «портированные разделы jQuery». Давайте сначала рассмотрим функции:

  • Селекторы — найти элементы на основе заданного условия.
  • Атрибуты — работа с атрибутами элементов DOM.
  • Traversing — перемещаться по списку выбранных элементов.
  • Манипуляции — добавление и удаление контента на выбранных элементах.
  • Ajax — создание серверных ajax-запросов.
  • События — привязывать события DOM к выбранным элементам.
  • Утилиты — общие функции для поддержки других функций.

Вы можете загрузить библиотеку phpQuery со страницы проекта по адресу code.google.com/p/phpquery . Скопируйте папку на ваш веб-сервер, и вы готовы к работе. Установка очень проста, и вы можете запустить файл demo.php

Как использовать phpQuery

Я собираюсь показать вам, как создать неупорядоченный список из двух столбцов с заголовками и разными цветами строк для нечетных и четных строк, как показано на рисунке ниже:

Во-первых, давайте создадим HTML-документ с использованием phpQuery:

 <?php
require("phpQuery/phpQuery.php");
$doc = phpQuery::newDocument("<div/>");

Приведенный выше код создаст базовый HTML-документ с тегом div Библиотека предоставляет различные методы создания документов; Я использовал самый простой, но вы можете найти другие в demo.php

Теперь нам нужно создать неупорядоченный список и добавить его в наш HTML-документ.

 <?php
...
$doc["div"]->append("<ul><li>Product Name</li><li>Price</li></ul>");
$products = array(
    array("Product 1","$30"),
    array("Product 2","$50"),
    array("Product 3","$20"));

foreach($products as $key=>$product) {
    $doc["div ul"]->append("<li>$product[0]</li><li>$product[1]</li>");
}
print $doc;

Вы можете видеть, что у нас есть неупорядоченный список сейчас. Но все элементы находятся в одном столбце, который используется по умолчанию. Мы должны переместить четные элементы списка во второй столбец.

 <?php
...
$doc["div ul"]->attr("style", "width:420px;");
$doc["div ul"]->find("li:even")->attr("style","width:200px; float:left; padding:5px; list-style:none;");
$doc["div ul"]->find("li:odd")->attr("style","width:200px; float:left; padding:5px; list-style:none;");

Я использую атрибут style, чтобы определить стили CSS, необходимые для нашего примера, но не рекомендуется использовать встроенные стили, если это действительно не нужно. Всегда используйте CSS-классы для добавления стилей.

Теперь давайте выделим заголовок и четные строки, используя методы phpQuery.

 <?php
...
$doc["div ul"]->find("li:nth-child(4n)")->attr("style","background:#EEE; width:200px; float:left; padding:5px; list-style:none;");
$doc["div ul"]->find("li:nth-child(4n-1)")->attr("style","background:#EEE; width:200px; float:left; padding:5px; list-style:none;");
$doc["div ul"]->find("li:lt(1)")->attr("style","background:#CFCFCF; width:200px; float:left; padding:5px; list-style:none;");

Мы завершили наш простой пример, и теперь вы должны иметь представление о том, как phpQuery можно использовать для упрощения генерации HTML на стороне сервера. Все, что мы делали, почти так же, как и в случае с jQuery, за исключением того, что мы выполняли все действия с объектом $doc

Важность phpQuery

Несмотря на то, что я объяснил функциональность phpQuery, вы, должно быть, задаетесь вопросом, зачем нам нужна библиотека, когда у нас есть jQuery на стороне клиента. Я покажу важность phpQuery, используя практический сценарий.

Рассмотрим следующую ситуацию: предположим, у нас есть таблица, подобная следующей, которая содержит всю информацию о веб-разработчиках, которые ходили на интервью.

Теперь вот список требований, которые мы должны разработать в этом сценарии:

  • Претенденты, набравшие более 60 баллов за экзамен, должны быть выделены синим цветом.
  • Кандидаты с опытом работы более 3 лет должны иметь ссылку «Подать заявку на старшего инженера-программиста», а другие кандидаты должны иметь ссылку «Подать заявку на инженера-программиста».
  • Компания имеет структуру заработной платы на основе опыта:
    • 1 год — 5000 долларов
    • 2 года — 10000 долларов
    • 3 года — 20 000 долларов
    • более 3 лет — 50 000 долларов

    Столбец зарплаты должен быть выделен зеленым цветом для кандидатов, которые соответствуют критериям.

Вот как должен выглядеть результат:

Разработчик может предоставить следующее решение для удовлетворения требований с использованием чистого кода PHP.

 <?php
// retrieve applicants from database
//...

echo <<<ENDHTML
<div id="main">
 <div class="row_head">
  <div>Name</div>
  <div>Marks</div>
  <div>Experience</div>
  <div>Position</div>
  <div>Expected Salary</div>
 </div>
ENDHTML;
foreach ($applicants as $applicant) {
    echo '<div class="row">';
    echo "<div>" . $applicant["name"] . "</div>";
    echo '<div class="' . marksClass($applicant["marks"]) . '">' . $applicant["marks"] . "</div>";
    echo "<div>" . $applicant["experience"] . "</div>";
    echo "<div>" . positionLink($applicant["experience"]) . "</div>";
    echo '<div class="' . salaryClass($applicant["experience"], $applicant["salary"]) . '">' . $applicant["salary"] . "</div>";
    echo "</div>";
}
echo "</div>";

function marksClass($info) {
    return ($info > 60) ? "pass" : "fail";
}

function positionLink($experience) {
    return ($experience > 3)
        ? '<a href="#">Apply for Senior Software Engineer</a>'
        : '<a href="#">Apply for Software Engineer</a>';
}

function salaryClass($experience, $salary) {
    switch ($experience) {
        case 1:
            return ($salary < 5000) ? "accept" : "reject";
        case 2:
            return ($salary < 10000) ? "accept" : "reject";
        case 3:
            return ($salary < 20000) ? "accept" : "reject";
        default:
            return ($salary < 50000) ? "accept" : "reject";
    }
}

Теперь давайте сделаем это с помощью phpQuery и сравним код и его преимущества.

 <?php
require("phpQuery/phpQuery.php");
$doc = phpQuery::newDocument('<div id="main"></div>');
phpQuery::selectDocument($doc);

// retrieve applicants from database
//...

$doc["#main"]->append('
<div id="main">
 <div class="row_head">
  <div>Name</div>
  <div>Marks</div>
  <div>Experience</div>
  <div>Position</div>
  <div>Expected Salary</div>
 </div>');

foreach ($applicants as $key => $applicant) {
    $doc["#main"]->append('<div class="row" id="app_' . $key . '"></div>');
    foreach ($applicant as $field => $info) {
        $doc["#main"]->find("#app_" . $key)->append('<div class="_' . $field . '">' . $info . "</div>");
        if ($field == "experience") {
            $doc["#main"]->find("#app_" . $key)->append('<div style="width:400px" class="_position">-</div>');
        }
    }
}

addMarksClass($doc);
addSalaryClass($doc);
addPositionLink($doc);

print $doc;

function addMarksClass(&$doc) {
    $marks = pq("._marks");
    foreach ($marks as $appMark) {
        if (pq($appMark)->html() > 60) {
            pq($appMark)->addClass("pass");
        }
        else {
            pq($appMark)->addClass("fail");
        }
    }
}

function addSalaryClass(&$doc) {
    $marks = pq("._salary");
    foreach ($marks as $appMark) {
        $experience = pq($appMark)->parent()->find("._experience" )->html();
        $salary = pq($appMark)->html();

        switch ($experience) {
            case 1:
                pq($appMark)->addClass(
                    ($salary < 5000) ? "accept" : "reject"
                );
                break;
            case 2:
                pq($appMark)->addClass(
                    ($salary < 10000) ? "accept" : "reject"
                );
                break;
            case 3:
                pq($appMark)->addClass(
                    ($salary < 20000) ? "accept" : "reject"
                );
                break;
            default:
                pq($appMark)->addClass(
                    ($salary < 50000) ? "accept" : "reject"
                );
        }
    }
}

function addPositionLink(&$doc) {
    $experience = pq("._experience");
    foreach ($experiece as $appExp) {
        if (pq($appExp)->html() > 3) {
            pq($appExp)->parent()->find("._position")->html('<a href="#">Apply for Senior Software Engineer</a>');
        }
        else{
            pq($appExp)->parent()->find("._position")->html('<a href="#">Apply for Software Engineer</a>');
        }
    }
}

С phpQuery легко, если у вас уже есть знания по работе с jQuery. Большая часть приведенного выше кода не требует пояснений. Я хочу отметить, что pq() Все остальные являются функциями jQuery.

И хотя оба выглядят одинаково, код, использующий phpQuery, обеспечивает лучшее качество и расширяемость. Подумайте, насколько хрупким может быть оригинальный код, если позже вам придется добавить дополнительные функции. Давайте предположим, что мы хотим добавить дополнительную проверку оценок, основанную на опыте работы. В этом случае вам придется добавить другой метод и назначить возвращаемый результат внутри цикла foreach Это означает, что вы должны изменить уже написанный код, нарушая принцип Open-Closed :

Программные объекты (классы, модули, функции и т. Д.) Должны быть открыты для расширения, но закрыты для модификации.

Во втором примере, использующем phpQuery, код сначала генерируется без какой-либо проверки, а затем мы передаем таблицу в каждую функцию, и изменения помещаются в исходную таблицу. Каждая функция не влияет на другие функции, поэтому мы можем написать новую функцию для любых новых требований и использовать ее вне цикла с другими функциями. Мы не модифицируем уже существующий код, что звучит хорошо, правда? Это называется украшением :

Шаблон декоратора — это шаблон дизайна, который позволяет динамически добавлять поведение к существующему объекту.

Резюме

Мы начали этот урок с представления функций phpQuery и их важности. Узнав, как использовать phpQuery на простом примере, мы перешли к практическому примеру, где он стал гораздо важнее для улучшения качества кода. phpQuery предоставил нам новую перспективу работы с HTML на стороне сервера, и я надеюсь, что вы будете использовать phpQuery по-разному и поделитесь своим личным опытом в комментариях ниже.