|
|
@@ -105,14 +105,14 @@ Content-Language: ru
|
|
|
|
|
|
* **PHP** - скриптовый язык общего назначения, интенсивно применяемый для разработки веб-приложений. В настоящее время поддерживается подавляющим большинством хостинг-провайдеров и является одним из лидеров среди языков, применяющихся для создания динамических веб-сайтов. В своем составе имеет библиотеки для работы с базами данных, поэтому его мы в дальнейшем и будем изучать.
|
|
|
* **Java** - строго типизированный объектно-ориентированный язык программирования общего назначения.
|
|
|
-* **Node или Node.js** - программная платформа, основанная на движке V8 (транслирующем JavaScript в машинный код), превращающая JavaScript из узкоспециализированного языка в язык общего назначения. Node.js добавляет возможность JavaScript взаимодействовать с устройствами ввода-вывода через свой API, написанный на C++, подключать другие внешние библиотеки, написанные на разных языках, обеспечивая вызовы к ним из JavaScript-кода. Node.js применяется преимущественно на сервере, выполняя роль веб-сервера.
|
|
|
+* **Node или Node.js** - программная платформа, основанная на движке V8 (транслирующем JavaScript в машинный код), превращающая JavaScript из узкоспециализированного языка в язык общего назначения. Node.js добавляет возможность JavaScript взаимодействовать с устройствами ввода-вывода через свой API, написанный на C++, подключать другие внешние библиотеки, написанные на разных языках, обеспечивая вызовы к ним из JavaScript-кода. Node.js применяется преимущественно на сервере, выполняя роль веб-сервера. Сервер для проекта `cinema.kolei.ru` написан на этом языке и код, если интересно, можно [посмотреть](../cinema/index.js) в этом репозитории в каталоге `cinema`.
|
|
|
* **Python** - (в русском языке встречаются названия пито́н или па́йтон) — высокоуровневый язык программирования общего назначения с динамической строгой типизацией.
|
|
|
|
|
|
## Синтаксис PHP
|
|
|
|
|
|
Пробежимся по верхушкам:
|
|
|
|
|
|
-**Переменные** - зяык динамически типизируемый, поэтому типы при объявлении переменных можно не использовать. Переменной одного типа в любой момент может быть присвоено значение другого типа. Ключевых слов для объявления переменных тоже нет - переменная создается в момент присваивания ей значения (но если попытаться считать переменную до её объявления, то получим исключение). Первым символом в названии переменной должен быть знак "$"
|
|
|
+**Переменные** - язык динамически типизируемый, поэтому типы при объявлении переменных можно не использовать. Переменной одного типа в любой момент может быть присвоено значение другого типа. Ключевых слов для объявления переменных тоже нет - переменная создается в момент присваивания ей значения (но если попытаться считать переменную до её объявления, то получим исключение). Первым символом в названии переменной должен быть знак `$` (доллар)
|
|
|
|
|
|
```php
|
|
|
$myVariable = 0;
|
|
|
@@ -150,6 +150,7 @@ function someFunction($firstParam, $secondParam)
|
|
|
{
|
|
|
return $firstParam.$secondParam;
|
|
|
}
|
|
|
+
|
|
|
$concat = someFunction('раз', 'два');
|
|
|
```
|
|
|
|
|
|
@@ -157,6 +158,10 @@ $concat = someFunction('раз', 'два');
|
|
|
|
|
|
**Классы**
|
|
|
|
|
|
+Объявление класса начинается с ключевого слова **class**, если класс является наследником какого-то класса, то родительский класс указывается после ключевого слова **extends**
|
|
|
+
|
|
|
+Конструктором класса является функция с именем **__construct**
|
|
|
+
|
|
|
```php
|
|
|
class ApiServer extends ParentClass
|
|
|
{
|
|
|
@@ -168,6 +173,7 @@ class ApiServer extends ParentClass
|
|
|
// ЛОКАЛЬНАЯ переменная
|
|
|
$var = 0;
|
|
|
|
|
|
+ // свойство класса
|
|
|
$this->var = 1;
|
|
|
}
|
|
|
}
|
|
|
@@ -177,7 +183,7 @@ class ApiServer extends ParentClass
|
|
|
|
|
|
## Разработка API-сервера на PHP
|
|
|
|
|
|
-API будем писать похожее на то, что использовалось для проекта "база" (то апи написано на **Node.js**, в конце я приведу исходный код). Отличия обусловлены тем, что сервер на PHP является **stateless** (не хранящим состояние). Поэтому без использования дополнительных механизмов (**Redis**, **Mongo**) нам негде хранить токен и будем использовать "базовую" авторизацию.
|
|
|
+API будем писать похожее на то, что использовалось для проекта "база". Отличия обусловлены тем, что сервер на PHP является **stateless** (не хранящим состояние). Поэтому без использования дополнительных механизмов (база данных, **Redis**, **Mongo**) нам негде хранить токен и будем использовать "базовую" авторизацию.
|
|
|
|
|
|
Таким образом, запросы *login* и *logout* нам не понадобятся, сразу реализуем методы получения данных (примеры запросов в формате плагина **REST Client** редактора VSCode).
|
|
|
|
|
|
@@ -206,12 +212,15 @@ Authorization: Basic ZXNtaXJub3Y6MTExMTAz
|
|
|
Описываем класс сервера и создаём его (при этом вызовется конструктор)
|
|
|
|
|
|
```php
|
|
|
+// декларация класса
|
|
|
class ApiServer
|
|
|
{
|
|
|
public function __construct(){
|
|
|
print_r($_SERVER);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// создание экземпляра
|
|
|
new ApiServer();
|
|
|
```
|
|
|
|
|
|
@@ -219,7 +228,7 @@ new ApiServer();
|
|
|
|
|
|
Переменная *$_SERVER* внутренняя глобальная переменная языка **PHP**, она содержит параметры запроса и возвращает примерно такое:
|
|
|
|
|
|
-```
|
|
|
+```txt
|
|
|
Array
|
|
|
(
|
|
|
[DOCUMENT_ROOT] => /home/kei/[ЙОТК]/API_PHP
|
|
|
@@ -259,9 +268,6 @@ Array
|
|
|
```php
|
|
|
class ApiServer
|
|
|
{
|
|
|
- // шаблон ответа
|
|
|
- private $response = ['notice'=>[]];
|
|
|
-
|
|
|
private $db = null;
|
|
|
|
|
|
public function __construct(){
|
|
|
@@ -280,11 +286,11 @@ class ApiServer
|
|
|
// break;
|
|
|
}
|
|
|
} catch (\Throwable $th) {
|
|
|
- $this->response['notice']['answer'] = $th->getMessage();
|
|
|
+ header("HTTP/1.1 500 Server error");
|
|
|
+ $response['error'] = $th->getMessage();
|
|
|
+ // выводим в stdout JSON-строку
|
|
|
+ echo json_encode($response, JSON_UNESCAPED_UNICODE);
|
|
|
}
|
|
|
-
|
|
|
- // выводим в stdout JSON-строку
|
|
|
- echo json_encode($this->response, JSON_UNESCAPED_UNICODE);
|
|
|
}
|
|
|
|
|
|
private function processGet($path)
|
|
|
@@ -295,9 +301,10 @@ class ApiServer
|
|
|
$this->auth();
|
|
|
|
|
|
// получаем данные
|
|
|
- $this->response['notice']['data'] = $this->db
|
|
|
+ $response = $this->db
|
|
|
->query("SELECT * FROM Product")
|
|
|
->fetchAll(PDO::FETCH_ASSOC);
|
|
|
+ echo json_encode($response, JSON_UNESCAPED_UNICODE);
|
|
|
break;
|
|
|
default:
|
|
|
header("HTTP/1.1 404 Not Found");
|
|
|
@@ -318,15 +325,37 @@ class ApiServer
|
|
|
}
|
|
|
```
|
|
|
|
|
|
+* `private $db = null` - ссылка на базу данных, получается после успешной авторизации
|
|
|
+* `header` - встроенный метод PHP, добавляет строку в заголовок ответа
|
|
|
+* `echo` - встроенная команда PHP, выводит данные в *stdout* (всё, что попадёт в выходной поток, станет телом ответа)
|
|
|
+* `json_encode($response, JSON_UNESCAPED_UNICODE)` - встроенный метод PHP, преобразует данные в JSON-строку
|
|
|
+* `isset` - встроенный метод PHP, проверяет существует ли указанная переменная
|
|
|
+* запрос данных из бд
|
|
|
+
|
|
|
+ ```php
|
|
|
+ $response = $this->db
|
|
|
+ ->query("SELECT * FROM Product")
|
|
|
+ ->fetchAll(PDO::FETCH_ASSOC);
|
|
|
+ ```
|
|
|
+
|
|
|
+* подключение к БД mysql
|
|
|
+
|
|
|
+ ```php
|
|
|
+ $this->db = new PDO(
|
|
|
+ "mysql:host=kolei.ru;port=3306;dbname={$_SERVER['PHP_AUTH_USER']};charset=UTF8",
|
|
|
+ $_SERVER['PHP_AUTH_USER'],
|
|
|
+ $_SERVER['PHP_AUTH_PW']);
|
|
|
+ ```
|
|
|
+
|
|
|
Запустить локальный сервер для отладки можно из командной строки в каталоге проекта
|
|
|
|
|
|
-```
|
|
|
+```txt
|
|
|
php -S 127.0.0.1:8080
|
|
|
```
|
|
|
|
|
|
Либо, если нам нужен доступ к этому АПИ с другого устройства (а эмулятор андроида это другое устройство)
|
|
|
|
|
|
-```
|
|
|
+```txt
|
|
|
php -S 0.0.0.0:8080
|
|
|
```
|
|
|
|
|
|
@@ -334,7 +363,7 @@ php -S 0.0.0.0:8080
|
|
|
|
|
|
### Параметры GET-запроса
|
|
|
|
|
|
-Параметры GET-запроса передаются прямо в URL. Отделяются от пути знаком вопроса. Между собой разделяются знаком &. Представляют собой пары `ключ=значение`. Например, так может выглядеть запрос материала по нужному продукту:
|
|
|
+Параметры GET-запроса передаются прямо в URL. Отделяются от пути знаком вопроса. Между собой разделяются знаком `&`. Представляют собой пары `ключ=значение`. Например, так может выглядеть запрос материала по нужному продукту:
|
|
|
|
|
|
```
|
|
|
GET {{url}}/Material?product_id=1
|
|
|
@@ -361,7 +390,7 @@ POST-запросы отличаются тем, что содержат дан
|
|
|
$json = json_decode($rawData);
|
|
|
```
|
|
|
|
|
|
- В переменной $json будет JSON-**объект**. Данные из него извлекаются как из класса -> стрелочным синтаксисом.
|
|
|
+ В переменной $json будет JSON-**объект**. Данные из него извлекаются как из класса `->` стрелочным синтаксисом.
|
|
|
|
|
|
Если кому-то удобнее работать с ассоциативными массивами, то можно в функции **json_decode** добавить второй параметр *true*
|
|
|
|
|
|
@@ -369,46 +398,3 @@ POST-запросы отличаются тем, что содержат дан
|
|
|
$json = json_decode($rawData, true);
|
|
|
```
|
|
|
|
|
|
-## Docker
|
|
|
-
|
|
|
-Рассказать про докер...
|
|
|
-
|
|
|
-В каталоге `data` этого репозитория лежит архив `DockerPhp.zip`, в нём настроены контейнеры PHP и NGINX.
|
|
|
-
|
|
|
-PHP проект складывать в подкаталог `www/yotc.kei` - он будет доступен на локальной машине по адресу `http://localhost:8080`. Если вам нужно более одного проекта, то нужно добавить в NGINX конфиг для нового проекта:
|
|
|
-
|
|
|
-* в каталоге `hosts` скопировать файл настроек `yotc_kei.conf` в, например, `myproject.conf` и исправить в нём 2 строки (я их специально вынес в начало конфига)
|
|
|
-
|
|
|
- ```
|
|
|
- server {
|
|
|
- listen 8081;
|
|
|
- root /var/www/html/myproject;
|
|
|
- ```
|
|
|
-
|
|
|
- - **listen 8081;** - порты до 1024 считаются зарезервированными, поэтому используйте 8081 и т.д. (общепринятая практика)
|
|
|
- - **root /var/www/html/myproject;** - путь к вашему проекту в каталоге `www` (**/var/www/html/** - на этот путь каталог монтируется в контейнере)
|
|
|
-
|
|
|
-* в файле **docker-compose.yml** в секцию **nginx -> ports** добавьте порт вашего нового проекта
|
|
|
-
|
|
|
- ```yml
|
|
|
- services:
|
|
|
- nginx:
|
|
|
- # используем последний стабильный образ nginx
|
|
|
- image: nginx:latest
|
|
|
- # маршрутизируем порты
|
|
|
- ports:
|
|
|
- - "8080:80"
|
|
|
- - "8081:8081"
|
|
|
- ```
|
|
|
-
|
|
|
-Как запустить/остановить контейнеры написано в **read.me** (находится в архиве)
|
|
|
-
|
|
|
-<!--
|
|
|
-
|
|
|
-работу с датой добавить в шпаргалки
|
|
|
-
|
|
|
-нижнее меню
|
|
|
-
|
|
|
-горизонтальный список карт, смена свайпом
|
|
|
-
|
|
|
--->
|