Что мы получим в результате обработки интерпретатором файла index php
Но прежде чем говорить о том, как это всё работает, давайте разберём один простой пример. Представим, что у нас есть новый язык программирования (придумайте любое название). Язык довольно прост:
- каждая строка представляет собой выражение,
- каждое выражение состоит из команды (оператора)
- и любого количества значений (операндов), которыми оперирует команда.
set a 1
set b 2
add a b c
print c
Это простой язык, так что мы можем без опаски предположить, что этот код всего лишь выводит на экран 3. Оператор set берёт переменную и присваивает ей число (совсем как $a=1 в PHP). Оператор add берёт две переменные для добавления и сохраняет результат в третьей. Оператор print выводит её на экран.
Теперь давайте напишем программу, которая считывает каждое «выражение», находит оператор и операнды, а затем что-то с ними делает, в зависимости от конкретного оператора. Это довольно просто реализовать на PHP, как вы можете видеть на примере листинга 1.
Это очень простая программа, и вам не придётся писать своё следующее веб-приложение на вашем новом языке. Но данный пример помогает понять, как легко можно создать новый язык и получить программу, которая способна считывать и выполнять этот язык. В нашем случае она построчно считывает исходный файл и выполняет код в зависимости от текущего оператора. Для запуска приложения нам не нужно преобразовывать его в ассемблер или двоичный код, оно и так прекрасно работает. Этот метод выполнения программ называется интерпретированием. Например, таким образом часто выполняются программы на Basic: каждое выражение считывается и сразу же выполняется в высокоуровневом режиме.
Но тут есть ряд проблем. Одна из них заключается в том, что написать подобный языковой процессор довольно легко, а вот выполняться новый язык будет очень медленно. Ведь нам придётся обрабатывать каждую строку и проверять:
- Какой оператор нужно выполнить?
- Это правильный оператор?
- Есть ли у него нужное количество операндов?
Но, несмотря на неторопливость, у интерпретирования есть преимущества: мы можем сразу запускать программу после каждого внесённого изменения. Для внимательных: когда я что-то меняю в PHP-скрипте, я сразу могу его выполнить и увидеть изменения; означает ли это, что PHP — интерпретируемый язык? На данный момент будем считать, что да. PHP-скрипт интерпретируется подобно нашему гипотетическому простому языку. Но в следующих разделах мы ещё к этому вернёмся!
Как можно заставить нашу программу «работать быстро»? Это можно сделать разными способами. Один из них, разработанный в Facebook, называется HipHop (я имею в виду «старую» систему HipHop, а не используемую сегодня HHVM). HipHop преобразовывал один язык (PHP) в другой (С++). Результат преобразования можно было с помощью компилятора С++ превратить в двоичный код. Его компьютер способен понять и выполнить без дополнительной нагрузки в виде интерпретатора. В результате экономится ОГРОМНОЕ количество вычислительных ресурсов и приложение работает гораздо быстрее.
Этот метод называется source-to-source компилированием, или транскомпилированием, или даже транспилированием (transpiling). На самом деле происходит не компилирование в двоичный код, а преобразование в то, что может быть скомпилировано в машинный код существующими компиляторами.
Транскомпилирование позволяет напрямую выполнять двоичный код, что повышает производительность. Однако у этого метода есть и обратная сторона: прежде чем выполнить код, нам сначала нужно провести транскомпилирование, а затем настоящее компилирование. Но это нужно делать только тогда, когда в приложение вносятся изменения, т. е. только во время разработки.
Транскомпилирование также используется для того, чтобы сделать «жёсткие» языки более простыми и динамичными. Например, браузеры не понимают код, написанный на LESS, SASS и SCSS. Но зато его можно транспилировать в CSS, который браузеры понимают. Поддерживать CSS проще, но приходится дополнительно транскомпилировать.
Чтобы всё работало ещё быстрее, нужно избавиться от стадии транскомпилирования. То есть компилировать наш язык сразу в двоичный код, который мог бы тут же выполняться, без дополнительной нагрузки в виде интерпретирования или транскомпилирования.
К сожалению, написание компилятора — одна из труднейших задач в информатике. Например, при компилировании в двоичный код нужно учитывать, на каком компьютере он будет выполняться: на 32-битной Linux, или 64-битной Windows, или вообще на OS X. Зато интерпретируемый скрипт может легко выполняться где угодно. Как и в PHP, нам не нужно переживать о том, где выполняется наш скрипт. Хотя может встречаться и код, предназначенный для конкретной ОС, что сделает невозможным выполнение скрипта на других системах, но это не вина интерпретатора.
Но даже если мы избавимся от стадии транскомпилирования, нам никуда не деться от компилирования. Например, большие программы, написанные на С (компилируемый язык), могут компилироваться чуть ли не час. Представьте, что вы написали приложение на PHP и вам нужно ждать ещё десять минут, прежде чем увидеть, работают ли внесённые изменения.
Если интерпретирование подразумевает медленное выполнение, а компилирование сложно в реализации и требует больше времени при разработке, то как работают языки вроде PHP, Python или Ruby? Они довольно быстрые!
Это потому, что они используют и интерпретирование, и компилирование. Давайте посмотрим, как это получается.
Что, если бы мы могли преобразовывать наш выдуманный язык не напрямую в двоичный код, а в нечто, очень на него похожее (это называется «байт-код»)? И если бы этот байт-код был так близок к тому, как работает компьютер, что его интерпретирование выполнялось бы очень быстро (например, миллионы байт-кодов в секунду)? Это сделало бы наше приложение почти таким же быстрым, как и компилируемое, при этом сохранились бы все преимущества интерпретируемых языков. Самое главное, нам не пришлось бы компилировать скрипты при каждом изменении.
Выглядит очень заманчиво. По сути, подобным образом работают многие языки — PHP, Ruby, Python и даже Java. Вместо считывания и поочерёдного интерпретирования строк исходного кода, в этих языках используется другой подход:
- Шаг 1. Считать скрипт (PHP) целиком в память.
- Шаг 2. Целиком преобразовать/компилировать скрипт в байт-код.
- Шаг 3. Выполнить байт-код посредством интерпретатора (PHP).
Процесс можно легко оптимизировать: предположим, что мы запустили веб-сервер и каждый запрос выполняет скрипт index.php . Зачем каждый раз грузить его в память? Лучше закешировать файл, чтобы можно было быстро преобразовывать его при каждом запросе.
Ещё одна оптимизация: после генерирования байт-кода мы можем использовать его при всех последующих запросах. Так что можно закешировать и его (главное, убедитесь, что при изменении исходного файла байт-код будет перекомпилироваться). Именно это делают кеши кода операций (opcode caches), вроде расширения OPCache в PHP: кешируют скомпилированные скрипты, чтобы их можно было быстро выполнить при последующих запросах без избыточных загрузок и компилирования в байт-код.
Наконец, последний шаг к высокой скорости — выполнение байт-кода нашим PHP-интерпретатором. В следующей части мы сравним это с обычными интерпретаторами. Во избежание путаницы: подобный интерпретатор байт-кода часто называется «виртуальной машиной», потому что в определённой степени он копирует работу машины (компьютера). Не надо путать это с виртуальными машинами, запускаемыми на компьютерах, вроде VirtualBox или VMware. Речь идёт о таких вещах, как JVM (Java Virtual Machine) в мире Java и HHVM (HipHop Virtual Machine) в мире PHP. Свои виртуальные машины есть у Python и Ruby. В некотором роде все они являются высокоспециализированными и производительными интерпретаторами байт-кода.
Каждая ВМ выполняет собственный байт-код, генерируемый конкретным языком, и они несовместимы между собой. Вы не можете выполнять байт-код PHP на ВМ Python, и наоборот. Однако теоретически возможно создать программу, компилирующую PHP-скрипты в байт-код, который будет понятен ВМ Python. Так что в теории вы можете запускать PHP-скрипты в Python (серьёзный вызов!).
Как выглядит и работает байт-код? Рассмотрим два примера. Возьмём PHP-код:
Теперь возьмём аналогичный пример на Python:
Python может напрямую сгенерировать коды операций ©python:
У нас есть два простых скрипта и их байт-коды. Обратите внимание, что байт-коды похожи на язык, который мы «создали» в начале статьи: каждая строка представляет собой оператор с любым количеством операндов. В байт-коде PHP к переменным добавляется префикс !, поэтому !0 означает переменную 0. Байт-коду не важно, что вы используете переменную $a: в ходе компилирования имена переменных теряют значение и преобразуются в числа. Это облегчает и ускоряет их обработку виртуальной машиной. Большинство необходимых «проверок» выполняются на стадии компилирования, что также снимает нагрузку с виртуальной машины и увеличивает скорость её работы.
Поскольку байт-код состоит из простых инструкций, интерпретирование проходит очень быстро. Вместо тысяч двоичных инструкций, которые нужно обработать для каждого выражения интерпретируемого языка, в байт-коде на каждое выражение приходится по несколько сотен инструкций (иногда и того меньше). Поэтому виртуальные машины работают гораздо быстрее интерпретируемых языков.
Иными словами, виртуалки взяли всё лучшее от двух миров. Хотя нам по-прежнему нужно компилировать из исходного кода в байт-код, этот процесс становится быстрым и прозрачным. А после получения байт-кода виртуальная машина быстро и эффективно интерпретирует его без излишних накладных расходов. И в результате мы имеем высокопроизводительное приложение.
Теперь, когда мы умеем эффективно выполнять сгенерированный байт-код, остаётся задача компилирования исходного кода в этот байт-код.
Рассмотрим следующие PHP-выражения:
Все они одинаково верны и должны быть преобразованы в одинаковые байт-коды. Но как мы их считываем? Ведь в нашем собственном интерпретаторе мы парсим команды, разделяя их пробелами. Это означает, что программист должен писать код в одном стиле, в отличие от PHP, где вы можете в одной строке использовать отступления или пробелы, скобки в одной строке или переносить на вторую строку и т. д. В первую очередь компилятор попытается преобразовать ваш исходный код в токены. Этот процесс называется лексингом (lexing) или токенизацией.
Токенизация (лексинг) заключается в преобразовании исходного PHP-кода — без понимания его значения — в длинный список токенов. Это сложный процесс, но в PHP вы можете довольно легко сделать нечто подобное. Представленный в листинге 2 код выдаёт следующий результат:
Строковое значение преобразуется в токены:
- <?php преобразован в токен T_OPEN_TAG,
- $a преобразован в токен T_VARIABLE, который содержит значение $a.
При парсинге токенов мы должны следовать некоторым «правилам», составляющим наш язык. Например, может быть правило: первый обнаруженный токен в программе должен быть T_OPEN_TAG (соответствует <?php).
Ещё одно возможное правило: присваивание может состоять из любого T_VARIABLE, после которого идёт символ =, а затем T_LNUMBER, T_VARIABLE или T_CONSTANT_ENCAPSED_STRING. Иными словами, мы разрешаем $a = 1, или $a = $b, или $a = 'foobar', но не 1 = $a. Если парсер обнаруживает серию токенов, не удовлетворяющих какому-то из правил, автоматически будет выдана ошибка синтаксиса. В общем, парсинг — это процесс, определяющий язык и позволяющий нам создавать синтаксические правила.
Посмотреть список правил, используемых в PHP, можно по адресу. Если ваш PHP-скрипт удовлетворяет синтаксическим правилам, то проводятся дополнительные проверки, чтобы подтвердить, что синтаксис не только правильный, но и осмысленный: определение public abstract final final private class foo() <> может быть корректным, но не имеет смысла с точки зрения PHP. Токенизация и парсинг — хитрые процессы, и зачастую для их выполнения берут сторонние приложения. Нередко используются инструменты вроде flex и bison (в PHP тоже). Их можно рассматривать и в качестве транскомпиляторов: они преобразуют ваши правила в С-код, который будет автоматически компилироваться, когда вы компилируете PHP.
Парсеры и токенизаторы полезны и в других сферах. Например, они используются для парсинга SQL-выражений в базах данных, и на PHP также написано немало парсеров и токенизаторов. У объектно-реляционного маппера Doctrine есть свой парсер для DQL-выражений, а также «транскомпилятор» для преобразования DQL в SQL. Многие движки шаблонов, в том числе Twig, используют собственные токенизаторы и парсеры для «компилирования» файлов шаблонов обратно в PHP-скрипты. По сути, эти движки тоже транскомпиляторы!
После токенизации и парсинга нашего языка мы можем генерировать байт-код. Вплоть до PHP 5.6 он генерировался во время парсинга. Но привычнее было бы добавить в процесс отдельную стадию: пусть парсер генерирует не байт-код, а так называемое абстрактное синтаксическое дерево (Abstract Syntax Tree, AST). Это древовидная структура, в которой абстрактно представлена вся программа. AST не только упрощает генерирование байт-кода, но и позволяет нам вносить изменения в дерево, прежде чем оно будет преобразовано. Дерево всегда генерируется особым образом. Узел дерева, представляющий собой выражение if, обязательно имеет под собой три элемента:
- первый содержит условие (вроде $a == true );
- второй содержит выражения, которые должны быть выполнены, если соблюдается условие true ;
- третий содержит выражения, которые должны быть выполнены, если соблюдается условие false (выражение else ).
В результате мы можем «переписать» программу до того, как она будет преобразована в байт-код. Иногда это используется для оптимизации кода. Если мы обнаружим, что разработчик раз за разом перевычислял переменную внутри цикла, и мы знаем, что переменная всегда имеет одно и то же значение, то оптимизатор может переписать AST так, чтобы создать временную переменную, которую не нужно каждый раз вычислять заново. Дерево можно использовать для небольшой реорганизации кода, чтобы он работал быстрее: удалить ненужные переменные и т. п. Это не всегда возможно, но когда у нас есть дерево всей программы, то такие проверки и оптимизации выполнять куда легче. Внутри AST можно посмотреть, объявляются ли переменные до их использования или используется ли присваивание в условном блоке ( if ($a = 1) <> ). И при обнаружении потенциально ошибочных структур выдать предупреждение. С помощью дерева можно даже анализировать код с точки зрения информационной безопасности и предупреждать пользователей во время выполнения скрипта.
Всё это называется статическим анализом — он позволяет создавать новые возможности, оптимизации и системы валидации, помогающие разработчикам писать гармоничный, безопасный и быстрый код.
В PHP 7.0 появился новый движок парсинга (Zend 3.0), который тоже генерирует AST во время парсинга. Поскольку он достаточно свежий, с его помощью можно сделать не так много. Но сам факт его наличия означает, что мы можем ожидать появления в ближайшем будущем самых разных возможностей. Функция token_get_all() уже принимает новую, недокументированную константу TOKEN_PARSE, которая в будущем может использоваться для возвращения не только токенов, но и отпарсенного AST. Сторонние расширения вроде php-ast позволяют просматривать и редактировать дерево прямо в PHP. Полная переработка движка Zend и реализации AST откроет PHP для самых разных новых задач.
Помимо виртуальных машин, выполняющих высокооптимизированный байт-код, сгенерированный из AST, есть и другая методика повышения скорости. Но это одна из самых сложных в реализации вещей.
Как выполняется приложение? Много времени тратится на его настройку: например, нужно запустить фреймворк, отпарсить маршруты, обработать переменные среды и т. д. По завершении всех этих процедур программа обычно всё ещё не запущена. По сути, куча времени потрачена лишь на функционирование какой-то части вашего приложения. А что, если мы выявим те части, которые могут часто запускаться и способны преобразовывать маленькие куски кода (допустим, всего несколько методов) в двоичный код? Конечно, на это компилирование может уходить относительно много времени, но всё равно метод компилируется куда быстрее, чем всё приложение. Возможно, при первом вызове функции вы столкнётесь с маленькой задержкой, но все последующие вызовы будут выполняться молниеносно, минуя виртуальную машину, и сразу в виде двоичного кода.
Мы получаем скорость компилируемого кода и наслаждаемся преимуществами кода интерпретируемого. Подобные системы могут работать быстрее обычного интерпретируемого байт-кода, иногда гораздо быстрее. Речь идёт о JIT-компиляторах (just-in-time, точно в срок). Название подходит как нельзя лучше. Система обнаруживает, какие части байт-кода могут быть хорошими кандидатами на компилирование в двоичный код, и делает это в тот момент, когда нужно выполнять эти самые части. То есть — точно в срок. Программа может стартовать немедленно, не нужно ждать завершения компилирования. В двоичный код преобразуются только самые эффективные части кода, так что процесс компилирования автоматизируется и ускоряется.
Хотя не все JIT-компиляторы работают таким образом. Некоторые компилируют все методы на лету; другие пытаются только определить, какие функции нужно скомпилировать на ранней стадии; третьи будут компилировать функции, если они вызываются два и больше раза. Но все JIT’ы используют один принцип: компилировать маленькие куски кода, когда они действительно нужны.
Ещё одно преимущество JIT’ов по сравнению с обычным компилированием заключается в том, что они способны лучше прогнозировать и оптимизировать на основании текущего состояния приложения. JIT’ы могут динамически анализировать код во время runtime и делать предположения, на которые неспособны обычные компиляторы. Ведь во время компиляции у нас нет информации о текущем состоянии программы, а JIT’ы компилируют на стадии выполнения.
Если вам доводилось работать с HHVM, то вы уже использовали JIT-компилятор: PHP-код (и надмножественный язык Hack) преобразуется в байт-код, запускаемый на виртуальной машине HHVM. Машина обнаруживает блоки, которые могут быть безопасно преобразованы в двоичный код; если это ещё не было сделано, она это делает и запускает их. По окончании запуска ВМ переходит к следующим байт-кодам, которые могут быть преобразованы в двоичный код.
PHP 7 не выполняется на JIT-компиляторе, но зато его новая система превосходит все предыдущие релизы. Сейчас во всех его компонентах проводятся эксперименты со статическим анализом, динамической оптимизацией, и даже есть простые JIT-системы. Так что не исключено, что однажды даже PHP 7 окажется позади!
Какой оператор обозначает равенство значений в языке PHP?
Как можно задать массив в языке PHP?
- $arr[«a»,»b»,»c»] = «q»;
- $arr («0″=> «a»);
- (Правильный ответ) $arr = array(«a»,»b»,»c»);
- (Правильный ответ) $arr[0] = «a»;
Какие из утверждений относительно оператора require верны?
- require выполняет код указанного в нем файла только один раз
- (Правильный ответ) require используется для включения в программу содержимого другого файла
- при использовании внутри условных блоков require не нужно заключать в фигурные скобки
Каким будет результат выполнения следующей программы
- +-!
- ошибка синтаксиса
- бесконечный цикл
- (Правильный ответ) -+!
Дана команда: if(!$var) echo «Hello»; В каком случае на экран будет выведено слово «Hello»?
- если $var == true
- (Правильный ответ) если $var = 0
- (Правильный ответ) если $var преобразуется к логическому false
Какие из операторов switch записаны правильно с точки зрения синтаксиса?
Что мы получим в результате обработки интерпретатором файла index.php ?
В каком случае выполняется блок действий цикла
- (Правильный ответ) если второе выражение (expr2) вычисляется как true
- если третье выражение (expr3) вычисляется как true
- если первое выражение (expr1) вычисляется как true
Какое из утверждений относительно оператора include верно?
- файл, включаемый с помощью include , должен быть правильным HTML-файлом
- (Правильный ответ) include используется для включения в программу содержимого другого файла
- файл, включаемый с помощью include , может быть любым файлом
Как можно узнать виртуальный путь до выполняющегося в данный момент скрипта?
- (Правильный ответ) getenv(‘SCRIPT_NAME’)
- (Правильный ответ) $_SERVER[‘SCRIPT_NAME’]
- (Правильный ответ) $_SERVER[‘PHP_SELF’]
- с помощью константы SCRIPT_NAME
Чем отличается клиент от сервера?
- (Правильный ответ) клиент посылает запросы, а сервер обрабатывает их
- (Правильный ответ) клиент отображает данные на экране компьютера пользователя, а сервер предоставляет данные
- (Правильный ответ) сервер выполняет запросы клиента, специализируясь на эффективном решении задач определенного класса
- сервер есть часть компьютерной архитектуры сервер-сервер, а клиент – архитектуры клиент-клиент
- сервер создает соединение, а клиент, пользуясь им, передает свой запрос
Как можно получить адрес страницы, с которой был послан запрос?
В чем состоят функции сервера?
- (Правильный ответ) обрабатывать запросы клиента
- (Правильный ответ) запускать процессы, запрошенные клиентом, и возвращать клиенту результаты
- отображать данные на экране компьютера пользователя
- инициировать соединение с клиентом
Дана следующая html форма:
Как можно получить переданные клиентом значения из этой формы?
- $f1 и $f2 , если register_globals=off
- $_POST[«f1»] и $_POST[«f2»]
- (Правильный ответ) $_GET[«f1»] и $_GET[«f2»]
- $POST[«f1»] и $POST[«f2»]
- (Правильный ответ) $_REQUEST[«f1»] и $_REQUEST[«f2»]
Создать класс A , расширяющий класс B с помощью метода add() и переменной $a .
Как можно получить и вывести на экран список всех методов класса, представителем которого является объект?
- get_methods(get_class(объект));
- (Правильный ответ) get_class_methods(get_class(объект));
- get_class_methods(get_class -> объект);
Класс MyClass задан следующим образом:
Создать представителя класса MyClass . Получить и вывести значения всех свойств этого класса. Вызвать методы данного класса.
Имеется объект ($obj) какого-то класса. Требуется получить список всех свойств класса, которому принадлежит объект.
- $get_class_vars(get_class->$obj);
- get_class_var(get_class($obj));
- (Правильный ответ) $vars = get_class_vars(get_class($obj));
Как можно программно узнать имя класса, представителем которого является объект?
- $(get_class->объект);
- (Правильный ответ) get_class(объект);
- class(объект);
Имеется следующая форма:
Изменить значения переданных элементов, увеличив их в 10 раз. Использовать функцию array_walk() . Вывести значения элементов до и после применения array_walk
Дана строка «<h2>Наука – <font color=red>двигатель</font> прогресса!</h2>» . Как можно вывести ее в браузер именно в таком виде, без форматирования согласно стандарту HTML?
Дана строка текста: «PHP – очень простой язык. Я знаю PHP. ». Заменить в ней все вхождения слова «PHP» на слово «Perl».
Что делает функция move_uploaded_file (временное имя файла, место назначения) ?
- удаляет загруженный файл
- (Правильный ответ) проверяет, загружен ли файл, и если да, то перемещает его из временной директории в указанную директорию для хранения
- перемещает файл из временной директории в указанную директорию для хранения
Имеется следующая html-форма
Как узнать размер файла, который клиент хочет загрузить на сервер с помощью этой формы.
- (Правильный ответ) filesize($_FILES[‘my’][‘tmp_name’])
- filesize($_FILES[‘my’][‘name’])
- $_FILES[‘size’]
- filesize($_FILES[‘name’][‘my’])
С помощью какой функции можно проверить, существует ли файл?
- (Правильный ответ) file_exists()
- is_writable()
- is_readable()
Какие из перечисленных функций считывают данные из файла, ссылка на который установлена функцией fopen ?
- (Правильный ответ) fgetc()
- (Правильный ответ) fgetss()
- fileread()
- (Правильный ответ) fread()
Имеется следующая html-форма
Как узнать, что файл, загружаемый на сервер с помощью этой формы, был загружен успешно?
- if (isset($_FILES[‘my’])) echo «файл загружен успешно»;
- (Правильный ответ) if ($_FILES[‘my’][‘error’] == 0) echo «файл загружен успешно»;
- if ($_FILES[‘my’][‘error’] == 1) echo «файл загружен успешно»;
Каков синтаксис оператора удаления таблицы?
- REMOVE TABLE [IF EXISTS] имя_таблицы [, имя_таблицы,…] [RESTRICT | CASCADE]
- (Правильный ответ) DROP TABLE [IF EXISTS] имя_таблицы [, имя_таблицы,…] [RESTRICT | CASCADE]
- DELETE TABLE [IF EXISTS] имя_таблицы [, имя_таблицы,…] [RESTRICT | CASCADE]
Составить запрос к таблице Articles на получение всех значений таких ее полей, как название статьи (title) , автор (author) и краткое содержание (abstract) . Упорядочить результат запроса по имени автора.
Оператор update предназначен для обновления значений существующих столбцов таблицы в соответствии с введенными значениями. Каков синтаксис этого оператора?
Составить запрос к таблице описаний статей (Articles) : изменить название статьи (title) , автор (author) которой «Петров» на название «Второе название».
Составить запрос к таблице Articles на добавление описания статьи с названием (title) «Новая статья» и автором (author) «Сидоров С. С.».
Получить имена всех полей таблицы persons базы данных book
Функция mysql_connect , устанавливающая соединение с базой данных MySQL, имеет следующий синтаксис:
mysql_connect ( server, username, password, new_link, client_flags)
Какие значения будут установлены для параметров server , username , password , если они не были заданы при вызове функции mysql_connect ?
Каковы синтаксис и семантика функции explode ?
- массив explode (строка string) . Эта функция разбивает строку string на части с помощью разделителя » » и возвращает массив полученных строк
- эта функция без параметров. Ее семантика неизвестна
- (Правильный ответ) массив explode(строка separator, строка string [, int limit]) . Эта функция разбивает строку string на части с помощью разделителя separator и возвращает массив полученных строк
Уничтожить текущую сессию целиком можно командой session_destroy(); К чему приведет уничтожение сессии?
- после уничтожения сессии очищается массив $_SESSION и больше ничего не происходит
- (Правильный ответ) после уничтожения сессии уничтожается ее идентификатор, мы больше не можем ни регистрировать переменные, ни вообще производить какие-либо действия с сессией
- после уничтожения сессии массив $_SESSION заполняется нулями
С помощью какой функции можно получить идентификатор сессии?
- id_session
- session_identificator
- (Правильный ответ) session_id
В одном из скриптов программы имеется переменная $user_name = «Иван Петров» . Как сделать так, чтобы эта переменная была доступна во всех скриптах программы.
Какова структура регулярного выражения?
- (Правильный ответ) общая структура регулярного выражения: шаблон, выделенный с помощью специального символа разделителя, модификатор, влияющий на способ обработки регулярного выражения
- общая структура регулярного выражения: шаблон, заключенный в круглые скобки, и функция для его обработки
- общая структура регулярного выражения: шаблон, выделенный с помощью специального символа разделителя
Назначение метасимвола «-« ?
- вычисляет символьный класс
- отрицание класса, но только если это первый символ
- (Правильный ответ) задает диапазон символов
Выделить из URL адреса ресурса имя хоста
Что делает следующая функция?
Для того, чтобы понять эту статью, вам уже нужно быть знакомым с PHP хотя бы на самом базовом уровне, быть чуть-чуть знакомым с консолью и очень желательно уже уметь запускать простые программы на PHP. Но я попытаюсь всё это объяснить еще раз.
Что такое файл index.php?
Давайте разберемся, что такое файл index.php. Если говорить формальное - это стартовая точка запуска программы на PHP. Это очень важно, хотя и звучит не очень понятно. Чтобы разобраться, что такое index.php, сначала нужно коротко понять как работает сам PHP.
Возможно, вы уже знаете, что PHP - это язык программирования. Любой язык программирования работает не сам по себе, а выполняет инструкции, написанные программистом, которые обычно называются "исходными кодами" (source code). Исходный код, по сути - это и есть программа. Так вот, исходный код программы не обязал содержаться в одном файле. Он может находиться в разных файлах. И у этих файлов могут быть любые имена.
Файл index.php
Тогда почему есть файл, который обязан называться index.php? Это уже относится только к PHP. Дело в том, что PHP должен знать, как именно запустить вашу программу. Ему нужно указать, откуда она начинается. Здесь в дело вступает файл index.php: его название указывает на то, что его нужно запустить первым. Тут не надо думать, надо просто запомнить: если в каталоге есть 1000 файлов с PHP-кодом и один файл index.php, то вся программа начнется с него, он запустится первым.
Может ли не быть файла index.php?
Таким образом, когда пользователь в браузере откроет ссылку http://yourawesomewebsite.ru/ (домен только для примера!) - на самом деле запрос придет к вашему серверу, запустится ваш веб-сервер (nginx или apache) и уже он обратится в каталог /var/www/yourawesomewebsite.ru/public_html/, найдет там файл index.php, "прогонит" код через PHP и выдаст результат обратно пользователю. Эта тема требует несколько углубленного изучения, но основные идеи я вам рассказал. Пишите вопросы в комментариях.
Как создать файл index.php?
Как и все остальные файлы исходных кодов - файл index.php является простым текстовым файлом. Чтобы создать файл index.php, потребуется всего лишь создать обычный текстовый файл. Вы можете использовать для этого любой текстовый редактор, который вам нравится (и который сохраняет в результате plain text, конечно). Например "Блокнот" в Windows, Sumlime Text (который я рекомендую), командную строку сервера и так далее.
Давайте создадим index.php, который в результате своей работы посчитает сумму двух чисел? Для этого откройте текстовый редактор, о котором мы говорили. Напишите туда следующий код:
Закрывающий тег PHP ?> ставить не обязательно. Когда возможно (если весь файл состоит из PHP-кода, например) — лучше его не ставить, это удобно.
Теперь сохраните этот файл с названием index.php. Далее давайте запустим его через интерпретатор PHP. Для этого в консоли выполните команду:
Обратите внимание, что у вас должен быть настроен PHP соответствующим образом, чтобы делать такой запуск. Путь до файла php.exe (или php в linux) должен быть прописан в PATH для вашего окружения. Иначе напишите полный путь до интерпретатора PHP.
Если вы начинающий программист, я рекомендую вам разобраться и установить Linux на свой компьютер (удалять Windows при этом не обязательно). Дело в том, что все сервера работают на linux и вам придется столкнуться с ним рано или поздно. Лучше - рано, еще и потому, что работать в linux (когда вы с ним разберетесь) банально удобнее, он лучше приспособлен для программирования. А какой-нибудь nginx в Windows, например, вообще установить невозможно (придется сильно помучиться).
Файл index.php и веб-сервер
Настройка веб-сервера выходит за рамки данной статьи. Тем более, что веб-серверов много и все они разные. Поэтому просто укажу на некоторые важные вещи.
Как я уже сказал, в настройках конкретного сайта для веб-сервер всегда должно быть указано, в каком каталоге располагается сайт. Именно в нем веб-сервер начнет искать файл index.php. Но если такой файл отсутствует, то веб-сервер попробует найти файл index.html или index.htm (всё это, конечно, настраивается). Поэтому название файла index.php - это прямая калька с файла index.html, который является "стартовым" для сайта, написанного на чистом HTML (представляете, такие были).
Во-вторых, даже если вы всё настроили правильно, вы должны быть уверены, что веб-сервер имеет соответствующие права, чтобы открыть ваш файл index.php. Почитайте что-нибудь про "Права и доступы в Linux", ничего конкретного порекомендовать я тут не могу.
Если вы добавите HTML в пример с подсчетом чисел (см. выше), то при открытии через интерпретатор (то есть через консоль) вы не увидите HTML-страницу. HTML обрабатывается только браузером, поэтому в этой статье я приводить такой пример не стал.
Умоляю, не пишите говно-код на PHP. Выучите язык хорошо перед тем, как начинать работать. Я так устал рефакторить говно, написанное идиотами. :) Это тема заслуживает отдельной статьи, пожалуй.
Отличие веб-приложения от обычной программы
Начиная писать программы для веба, многие начинающие программисты сталкиваются с такой ошибкой. Они рассматривают систему браузер-сервер, как обычное приложение. Интерактивное. Нажал кнопку - система среагировала. Провел мышкой - среагировала. Вся информация, которая доступна клиенту - доступна и программе, программа все время находится в памяти.
Так вот, в веб-программировании это не так!.
В момент, когда пользователь видит перед собой страницу и начинает совершать какие-то действия с ней, PHP уже завершил работу! И пользователь взаимодействует не с PHP скриптом, а со своей страницей HTML, которую он получил в браузер. Результатом работы скрипта на PHP в большинстве случаев является обычный текст. Текст HTML страницы. Которая отдается браузеру и показывается им, как обычный HTML. Вы сами можете в этом убедиться, написав в скрипте
<? echo "Привет, <b>Вася!</b>"; ?>;
А потом просмотрев в браузере исходный текст полученной страницы. Никаких тегов PHP там нет! Только
Привет, <b>Вася!</b>
Потому, что PHP исполняется на сервере!
Сервер и браузер общаются, посылая друг другу запросы по особому протоколу - HTTP. Соединение может инициировать только браузер. Он посылает серверу запрос - показать такой-то файл. Сервер клиенту файл посылает.
Только так и происходит. Клиент запросил - сервер отдал. И забыл сразу о клиенте. Отсюда становится понятным ответ на вопрос, можно ли точно узнать, сколько юзеров сечас на сайте. Нельзя. потому, что "на сайте" нету ни одного. Они соединяются, запрашивают страницу, и отсоединяются. Не имеют постоянного cоединения с сервером, как, например, игроки в Кваку. Узнать можно только примерно, записывая время каждого соединения и выбирая записи за определенный промежуток времени.
Пример общения браузера с сервером:
Пользователь нажимает на ссылку, браузер посылает запрос серверу и ждет ответа:
Браузер -> PHP
PHP выполняет скрипт, отдает результат в браузер и завершает работу:
PHP -> браузер
Браузер отображает страницу, "просматривая" её на предмет ссылок, которые надо запросить у сервера (теги <img src>, <script src> и так далее) и посылает соответствующие запросы. Их можно увидеть, просматривая обмен заголовками, о чем речь будет чуть ниже:
Браузер -> сервер, Браузер -> сервер, Браузер -> сервер.
Пользователь заполняет форму и нажимает на кнопку:
Браузер -> PHP
PHP обрабатывает форму, записывает данные в базу и посылает браузеру заголовок
Location:
PHP -> браузер
Браузер, получив этот заголовок, запрашивает указанную страницу
Браузер -> PHP
PHP выполняет ее. и так далее.
Как передать переменную из PHP в JavaScript и обратно?
Начнем с того, что никакую переменную передать, конечно же, невозможно. Поскольку переменная - это часть программы. И из одной в другую передать её нельзя. Передать можно только значение переменной. Т.е. текст. То есть, различия между "передачей переменной в яваскрипт" и формированием html таблицы НЕТ НИКАКОГО!
Отсюда вывод - "Передать переменную" в Javascript очень легко. Особенно, повторюсь, если учесть, что никакой "передачи" не происходит. PHP просто напросто генерирует яваскрипт точно так же, как и всю остальную страницу, вместе со всеми переменными.
Точно так же, как вы выводите в браузер строку "Hello World, это Вася Пупкин!", выводится и любой яваскрипт, со всеми своими переменными.
Единственное условие - вы должны представлять себе тот яваскрипт, который хотите получить.
К примеру в PHP есть переменная $name="Вася" , значение которой надо передать в яваскрипт, чтобы получить
<script>name="Вася";</script>
Мы просто пишем
<?
$name="Вася";
?>
<script>name="<? echo $name; ?>"</script>
То есть, фактически, мы просто сформировали нашим PHP скриптом некий текст, который выглядит, как нужный нам код на яваскрипте. Или, с другой стороны, мы писали свой яваскрипт, в нужных местах вставляя вывод переменных из PHP.
Чтобы не сойти с ума от разнообразных кавычек, настоятельно рекомендуется яваскрипт выводить не весь с помощью echo, а именно так, как написано здесь - закрыв тег PHP и открывая их только там, где нужно вывести переменную.
Как передать переменную из яваскрипта в PHP?
Точно так же, как и любые другие данные - послав запрос на сервер.
Но надо четко понимать, что во время выполнения php скрипта получить что-либо из яваскрипта, разумеется, невозможно. Передать можно будет только при следующем запросе. И обрабатывать его будет уже другой PHP скрипт.
Если надо по событию onClick обратиться к базе данных, то следует помнить, что она находится на сервере. То есть, надо запрашивать сервер, который запустит PHP скрипт, который обратится к базе, получит от неё ответ и передаст его в браузер.
Все вышеизложенное не противоречит, разумеется, модной технологии асинхронного общения браузера с сервером. Все методы остались те же, просто общение с сервером выполняет не сам браузер, а программа на яваскрипте.
Подробнее можно почитать на ресурсах, посвященных яваскрипту. С точки зрения PHP запросы по технологии AJAX ничем не отличаются от обычных.
Самое главное, что надо помнить: сервер по своей инициативе обратиться к клиенту не может. Мы можем только по факту запроса выдать что-то браузеру - либо страницу, либо команду запросить другой ресурс.
ОЧЕНЬ ВАЖНОЕ ЗАМЕЧАНИЕ
Из того факта, что PHP исполняется на сервере, и посылает результат своей работы браузеру, следует один простой, но очень важный вывод. Что PHP в принципе НЕ МОЖЕТ отобразить в браузере ничего такого, что невозможно было бы сделать средствами html.
ПРЕЖДЕ, чем что-то писать на PHP - попробуйте это сделать чистым HTML.
"Нажатие на Энтер" не переводит строку? А в html вы не пробовали таким образом строки переводить? Не получилось? Какая досада. Прочитайте, как в html сделать перевод строки и приходите снова.
Браузер не умеет показывать файлы, в которые напихан одновременно и html картинки. Браузер умеет показывать только известные ему типы данных. В частности, это ИЛИ html ИЛИ картинка. Но не вместе. Если картинка - то ОДНА. Несколько картинок подряд браузер показывать не умеет. Браузер умеет показывать HTML, в котором прописаны ССЫЛКИ на несколько картинок.
Пожалуйста, прежде, чем изучать PHP - изучите хотя бы основы HTML! Прежде, чем что-то требовать от PHP - попробуйте сделать это на html.
Читайте также: