Лекция 3: �Введение в разработку на PHP�Требования к коду
intervolga.ru/school/
Ерофеев Анатолий Андреевич
Руководитель отдела разработки
1
2
Устройство ИНТЕРНЕТА,
HTTP, HTML, верстка
Веб-сервер�Лекции 1 и 2�ЛР 1
Работа с данными�PHP, MySQL, веб-формы, фильтрация данных�Лекции 3 и 4�ЛР 2
Язык PHP: история
3
Язык PHP: история
4
Язык PHP: история
Язык имеет C-подобный синтаксис, динамическую типизацию, сборщик мусора.�Характеризуется низким порогом входа.
5
2 способа запуска
Из консоли
>> php -f /home/user/test.php�Этот способ активно используется при миграциях, установках и любых других долгих операциях.
В том числе для запуска регламентных задач через cron
Из браузера (через веб-сервер)
6
Браузер
Веб-сервер (Apache, Nginx)
PHP
test.php
HTTP-запрос
HTTP-ответ
вызов
html/text
чтение файла
исходный текст
Как выглядит PHP-разработка
7
PHP-разработка. Инструменты
8
PHP-разработка. Процесс
9
PHP-разработка. Процесс
10
PHP-разработка. Артефакты
11
PHP-разработка. Результат
12
Синтаксис
// Исторический вариант вставки PHP в HTML (содержимое .php-файла)
<html>
<head>
<title>
Тестируем PHP
</title>
</head>
<body>
<?php echo "Привет мир!"; ?>
<?= 'Привет мир!' /* сокращенная форма для вывода данных */?>
</body>
</html>
13
Какой HTML-код попадет в браузер?
// Исторический вариант вставки PHP в HTML (содержимое .php-файла)
<html>
<head>
<title>
Тестируем PHP
</title>
</head>
<body>
Привет мир!
Привет мир!
</body>
</html>
14
Что увидит пользователь в браузере?
// Исторический вариант вставки PHP в HTML (содержимое .php-файла)
Привет мир!Привет мир!
15
Правильно разделять логику (PHP) и представление (html+css+графику)
// Вариант вкрапления PHP с разделением .php-файла на логику работы с данными и собственно вывод)
<?php // логика�$a = 1+5; �$text = "Привет мир, 1+5 =".$a;
?><!-- представление -->�<html>
<head><title>Тестируем PHP</title></head>
<body>
<?=$text?>
</body>
</html>
16
Следующий шаг – выделение “шаблона” в отдельный документ
// logic.php
<?php�$a = 1+5; �$text = "Привет мир, 1+5 =".$a;
include(“view.php”);
?>
// view.php
<html>
<head><title>Тестируем PHP</title></head>
<body>
<?=$text?>
</body>
</html>
17
Логика подключает Представление или наоборот
// logic.php
<?php �$a = 1+5; �$text = "Привет мир, 1+5 =".$a;
?>
// view.php
<? include(“logic.php”); ?>
<html>
<head><title>Тестируем PHP</title></head>
<body>
<?=$text?>
</body>
</html>
18
Синтаксис PHP-вставок
// Полная форма
<?php
echo “Hello world”
?>
// Краткая форма с короткими тегами
<?
echo “Hello world”
19
Типы данных
Существует еще несколько "псевдотипов", в рамках курса они нам не понадобятся.
Тип переменной определяется по ее значению (не объявляется).
20
Строки. Виды кавычек
Одинарные и двойные кавычки
В PHP для строк используют как одинарные ', так и двойные " кавычки. В большинстве случаев они работают одинаково, но не всегда. Например, если использовать переменную внутри одинарных кавычек, то выведется её имя. А если внутри двойных, то значение:
$name = 'Думпо';
keks_log('Слона зовут $name'); // Выведет: "Слона зовут $name"
keks_log("Слона зовут $name"); // Выведет: "Слона зовут Думпо"
Двойные кавычки помогают избежать запутанной конкатенации. О том, какие ещё есть различия между кавычками, вы можете узнать в документации.
21
Переменные
Имя переменной всегда начинается с символа $, чувствительно к регистру. Объявлять переменные не нужно.
<?php
$x = 12; $y = 4; echo $x/$y;
Строковые переменные можно объявлять через одинарные или двойные кавычки. Двойные поддерживают подстановку переменных.
<?php
$x = 'world';
$y = 'Hello, $x; // => Hello, $x
$y = "Hello, $x"; // => Hello, world
22
Переменные-массивы
Особый тип переменных. Внутри устроен как словарь с сохранением порядка вставки.
Если ключи массива являются целыми числами без пропусков от 0 до N-1, такой массив называют “индексированным”. Если это условие не выполняется - “ассоциативным”.
<?php
$a = []; // пустой массив
$b = [1, 5, 3]; // индексный
$c = ['a' => 1, 'c' => 5, 'b' => 3]; // ассоциативный
23
Переменные-массивы
Основные операции с массивами:
24
Индексные vs Ассоциативные
Индексные
Ключи не указаны или 0,1,2,3…
Индексы позволяют не только получать элементы, но и записывать в массив новые данные.
Добавим в массив $favorite_food новый элемент:
$favorite_food = ['пюре', 'котлеты', 'борщ'];
$favorite_food[] = 'пельмени';
print_r($favorite_food[3]); // Выведет: "пельмени"
Изменим элемент:
$favorite_food = ['пюре', 'котлеты', 'борщ'];
print_r($favorite_food[1]); // Выведет: "котлеты"
$favorite_food[1] = 'блины';
print_r($favorite_food[1]); // Выведет: "блины"
Ассоциативные
Ключи указаны и это не 0,1,2,3…
Вместо числовых индексов в ассоциативных массивах к элементам можно обращаться по ключу
$food = ['пюре' => 100, 'котлеты' => 150];
$food['борщ'] = 250;
print_r($food['котлеты']); // 150
print_r($food['борщ']); // 250
25
Примеры на массивы
Вложенные массивы
Массивы могут содержать в себе другие массивы. Такие массивы называются вложенными.
$flowers = [
0 => [
'name' => 'Ромашка',
'cost' => 'free'
],
1 => [
'name' => 'Лилия',
'cost' => 300
]
];
echo $flowers[0][‘name’];
26
Функции работы с массивами
Колбэком называют функцию, которую передают в качестве аргумента другой функции. Колбэки не являются встроенными функциями, их пишут сами разработчики.
uasort
Встроенная функция uasort сортирует массив. Эта функция принимает два аргумента: массив, который нужно отсортировать, и имя функции-колбэка.
uasort($array, 'callback');
Функция-колбэк, которую мы передаём uasort, должна принимать два аргумента и возвращать число: положительное число, если первый аргумент больше, отрицательное число, если больше второй аргумент, и ноль, если аргументы равны.
Во время вызова uasort передаёт в колбэк по двое элементы массива, узнаёт, какой из них больше, и сортирует массив по возрастанию: от меньшего к большему.
array_slice
Функция array_slice принимает массив, копирует его часть и возвращает её в виде нового массива. Массив, который передали функции, при этом не изменяется.
Функция принимает четыре аргумента:
$new_array = array_slice($array, $first_element, $length, $preserve_keys);
27
Функции работы с массивами
array_filter
В PHP есть встроенная функция фильтрации — array_filter. Она принимает два аргумента: исходный массив и функцию-колбэк — и возвращает новый массив. Исходный массив при этом не изменяется.
$filtered_array = array_filter($array, 'callback');
Согласно документации, колбэк должен принимать элемент исходного массива и возвращать булево значение: true, если этот элемент нужно включить в новый массив, и false, если не нужно.
array_rand
Для получения случайных элементов из массива, используем функцию array_rand. Она принимает исходный массив и количество случайных элементов, которые мы хотим получить.
$random = array_rand($array, $number_of_elements);
Если второй аргумент — единица, функция вернёт один случайный ключ. Если второй аргумент больше единицы, функция вернёт массив со случайными ключами.
Функция array_rand выбирает случайные элементы, но возвращает их в том порядке, в каком они идут в исходном массиве.
28
Функции работы с массивами
shuffle
Встроенная функция shuffle перемешивает массив. Функция принимает массив и выстраивает его элементы в случайном порядке. Будьте осторожны, функция shuffle изменяет переданный ей массив и не сохраняет ключи. С ассоциативными массивами её лучше не использовать.
shuffle($array);
Объединение массивов
В PHP массивы можно объединить с помощью знака плюс:
$big_array = $array_1 + $array_2;
В результате получится один массив, который включает элементы как из первого, так и из второго массива. При этом порядок элементов и их ключи сохранятся.
Если у нескольких элементов окажутся одинаковые ключи, то значение возьмётся из того массива, который идёт раньше. Перед объединением убедитесь, что ключи в массивах не совпадают или что одинаковым ключам соответствуют одинаковые значения.
29
Логические переменные
Константы: TRUE, false (регистр не важен)
При приведении выражения/переменной к логическому типу
считаются равными FALSE
Для “защиты от дурака” рекомендуется по умолчанию всегда использовать оператор === вместо ==, он более корректно обрабатывает нетривиальные сравнения.
30
Лайфхак по стилю кодирования
Вы убережете себя от множества сложно отлаживаемых проблем (во многих языках), если будете соблюдать следующие советы:
31
Глобальные переменные
// Использовать глобальные переменные в целом нехорошо
Но если нужно, то:
<?php
// a.php
global $x;
$x = 12;
require('b.php');
32
<?php
// b.php
global $x;
echo $x;
Суперглобальные массивы
В PHP существует несколько глобальных переменных, доступных без объявления. Они называются “суперглобальными массивами”:
33
Операторы
34
Циклы
Цикл с предусловием (while);
<?php $i=0; while ($i++<10) { echo $i; } ?>
Цикл с постусловием (do-while);
<?php $i=0; do { echo $i; } while ($i++<10); ?>
Цикл со счетчиком (for);
<?php for ($i=0; $i<10; $i++) { echo $i; } ?>
Специальный цикл перебора массивов (foreach).
$arr = array(1, 2, 3, 4);
foreach ($arr as $value)
echo $value * 2;
// Будет выведено�2468
35
Условия
<?php
$x = 9;
if ($x > 10) {
echo 'Число больше 10';
} elseif (10 === $x) {
echo 'Число равно 10';
} else {
echo 'Число меньше 10';
}
36
Условия
<?php
$x = 9;
$result = $x > 10 ? 'Число больше 10' : 'Число не больше 10';
echo $result;
37
Условия
<?php
$x = 1;
switch ($x) {
case 1: echo ‘Число равно 1’; break;
case 2: echo ‘Число равно 2’; break;
default: echo ‘Другое значение’;
}
38
Альтернативный синтаксис для условий
<?php if (condition): ?>
html code to run if condition is true
<?php else: ?>
html code to run if condition is false
<?php endif ?>
39
Примеры
Внедрение условия в шаблон
PHP позволяет использовать условия внутри шаблонов, чтобы менять разметку в зависимости от ситуации.
<?php if (условие): ?>
разметка
<?php endif; ?>
Конкатенация
Операция склеивания нескольких строк в одну.
$product_class = 'item' . ' item-hot';
// Получается строка 'item item-hot', все пробелы сохраняются
40
Примеры: Добавление класса в разметку
Условие в шаблоне
<section class="item
<?php if ($is_new): ?>
item-new
<?php endif; ?>
">
Класс item-new в теле условия не оборачивается в кавычки. Перед item-new надо поставить пробельный символ, чтобы два класса не слиплись в одно слово.
Условие в сценарии
Ещё один вариант внедрения класса — добавить в разметку переменную, которая будет содержать конечный результат — строку с необходимыми классами. А само условие написать в сценарии. Тогда код в шаблоне получается не таким громоздким и его удобней читать.
В разметке:
<section class="<?= $product_class ?>">
В сценарии:
$product_class = 'item';
if ($discount > 1400 || $is_last) {
$product_class = $product_class . ' item-hot';
// Слово 'item' склеится со словом 'item-hot' в одну строку
};
41
Примеры: Динамический <select>
Логика
// Получим записи из БД
$fruits = Fruits::getRecords();
// Записи возвращаются в виде массива
// $fruits = [
// 10 => “Apple”,
// 11 => “Banana”,
// 20 => “Lemon”
// ];
Представление
<label for="fruit-select">Выберите фрукт:</label>
<select name="fruits" id="fruit-select">
<?php foreach ($fruits as $id => $fruit): ?>
<option value="<?=$id?>"><?=$fruit?></option>
<?php endforeach;?>
</select>
С помощью цикла перебираем массив и динамически генерируем элементы списка
42
Включение внешних файлов
include/require + once/[пусто]
Как правило, используется require_once
<?php require_once($_SERVER['DOCUMENT_ROOT'] . '/db.php');
// ...
43
Функции
<?php
function abc($arg1, array $arg2, &$arg3) {
return 12;
}
$y = 'abc';
$x = abc(1, [2,3,4], $y);
?>
44
Классы
class A {
protected $prop = 12;
protected $statProp = 13;
function __construct($x) { $this->prop = $x; }
public static function Stat1() { echo self::$statProp; }
public static function work() { echo $this->prop; }
}
class B extends A {
private $statProp2 = 14;
public static function Stat2() { echo static::$statProp2; }
}
echo B::Stat2();
echo B::Stat1();
$y = new B(5);
echo $y->work();
45
Отображение ошибок
Настройки, влияющие на отображение ошибок:
4 уровня переопределения настроек:
php_value error_reporting E_ALL
для большинства параметров или точечно для error_reporting: error_reporting(E_ALL & ~E_NOTICE);
46
Типовая отладка
<?php
echo '<pre>';
print_r($_GET);
echo '</pre>';
echo '<pre>';
$x = 12; var_dump($x);
var_dump($_GET);
echo '</pre>';
47
Продвинутая отладка
48
Хорошие практики
49
Хорошие практики
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/db.php');
require_once($_SERVER['DOCUMENT_ROOT'] . '/lib.php');
$data = [
'x' => 1,
'y' => 2,
];
if (..) { $data['z'] = 3; }
?>
<html>
<head><title>Тестируем PHP</title></head>
<body><?= $data['z'] ?></body>
</html>
50
Хорошие практики
Представьте, что посетитель интернет-магазина долгих 10 минут настраивал фильтр по смартфонам (цена, бренд, диагональ, ЦПУ, срок доставки).
А после нажатия на кнопку “Найти” увидел 0 предложений. Он захочет изменить свой запрос, но вряд ли захочет заново заполнять все поля.
Мораль: после перезагрузки страницы в форме надо “восстанавливать” все значения в полях, чтобы пользователь
<form>
<label for="fname">Название:</label>
<input type="text" id="fname" name="fname" value="<?=htmlspecialchars($_GET['fname'])?>">
<label for="lname">Бренд:</label>
<input type="text" id="lname" name="lname" value="<?=htmlspecialchars($_GET['lname'])?>">
</form>
51
Источники
52
отвлечемся на ЛР 2
Лабораторная работа 2
ЛР 2: �таблицы, формы, запросы, чтение из БД
Цель работы:
Познакомиться с работой связки браузер-сервер, get-запросами, обработкой данных и базой данных.
Суть:
Ход работы
55
Ход работы
Задание 61:
Пример исполнения:
Между сущностями реализована связь один-ко-многим (т.е. на одну запись из таблицы drugs может быть найдена только одна запись из таблицы brands, а для одной записи из brands может быть множество разных записей из drugs).
56
Как все должно выглядеть
Примерно как тут, в вашем варианте: https://volgu.ivdev.ru/LR2/drugs.php
57
58
Ход работы
Рекомендуем установить XAMPP — пакет из программ Apache (веб-сервер), MariaDB (СУБД), PHP (интерпретатор языка программирования)
59
Ход работы
Пример исполнения:
Между сущностями реализована связь один-ко-многим (т.е. на одну запись из таблицы drugs может быть найдена только одна запись из таблицы brands, а для одной записи из brands может быть множество разных записей из drugs).
60
Ход работы
Создайте главную таблицу в MYSQL (через консольный доступ или phpmyadmin, он доступен по адресу http://localhost/phpmyadmin/index.php (вместо localhost может потребоваться написать ваш IP-адрес в XAMPP)).
61
Ход работы
62
Ход работы
Создание БД и таблицы в консоли сервера БД (для общего развития, делать так не не обязательно)
create database sporting_meal; #создаем БД
use sporting_meal; #начинаем использовать БД
create table drugs ( #начало создания таблицы
id int(11) not null � auto_increment primary key, #ключевое поле с автоприращением
name varchar(45), #название
img_path varchar(45), #поле имени файла картинки
id_brand int(11), #номер бренда (ИМЯ не храним)
description text, #описание, текст большой длины
cost int(11) #стоимость
); #заканчиваем создавать таблицу
63
Ход работы
Аналогично создаем вспомогательную таблицу brands.
Заполняем обе таблицы данными.
64
Подключение к БД
65
Примеры запросов
Извлекаем все данные �из 1 таблицы
select *
from drugs
Извлекаем все данные из 2 таблиц, соблюдая логику связей
� select drugs.name, brands.name, img_path, description, cost� from drugs � inner join brands on drugs.id_brand=brands.id�
66
Примеры запросов
Извлекаем все данные из 2 таблиц, соблюдая логику связей
С фильтрацией по имени (вхождение “at” и стоимости (=1000))
� select drugs.name, brands.name, img_path, description, cost� from drugs � inner join brands on drugs.id_brand=brands.id
where drugs.name like “%at%”
and cost=1000�
67
Примеры запросов
Извлекаем все данные из 2 таблиц, соблюдая логику связей
С фильтрацией по бренду Myprotein и слову “best” в описании
� select drugs.name, brands.name, img_path, description, cost� from drugs � inner join brands on drugs.id_brand=brands.id
where id_brand=2
and description like “%best%”�
68
Организация файлов проекта
69
Организация файлов проекта
70
Картинки верстки
71
Картинки каталога
72
Программные файлы
73
Как писать код. Логика
74
Логика вывода
75
Как собирать запрос
...
76
Как все должно выглядеть
Примерно как тут, в вашем варианте: https://volgu.ivdev.ru/LR2/drugs.php
77
78
Частые ошибки
79
Частые ошибки в SQL-запросе
Как надо:
80
// вернемся к лекции
Требования к коду бекенд-программиста
Почитать
Об
83
Почитать
84
Почитать
85
Минимальные требования таковы
Требования
87
Защита от SQL-инъекций
Код поиска пользователя по логину:
mysqli_query('select * from users where LOGIN = ' . $_REQUEST['login']);
Если вдруг вместо логина пользователь он подсунет строчку:
Vasya; drop table users;
Нас ждёт удаление всех пользователей из базы данных.
Требуется любым адекватным способом фильтровать входные данных. Нельзя допустить отправку опасного запроса в базу данных или вывода данных с визуальными ошибками.
88
Защита
Использовать
Большинство программистов не делают ровным счетом ничего для защиты БД. Кто-то использует функции htmlspecialchars , trim , addslashes — настоящей защиты это не даёт. �
Пример хорошего кода:
89
Именование
Искусство выбора подходящих названий играет немалую роль в разработке ПО. Казалось бы, что тут сложного? Правил немного и запомнить их не так сложно:
90
Как надо
Мы оцениваем именование по 4 разным направлениям:
Пример хорошего кода:
91
Оформление кода
Это «критичное» требование. Ваш код не должен быть похож на кашу. Рецепт прост: грамотно и аккуратно расставлять отступы, скобки и комментарии.
Чем хотите, тем и ставьте отступы — но одинаковые по всему коду.
92
Комментарии
Комментариев нет совсем — не молодец
Комментарии есть ко всем смысловым блокам (блоки по 5-10 строк) — молодец
Нет бесполезных комментариев (вроде «добавляем 1 к переменной-счётчику» или «умножаем на 10») и присутствуют комментарии для функций в нотации phpdoc — большой молодец.
Пример хорошего кода:
93
Борьба с дублированием кода
Есть известный принцип программирования — DRY (Don’t repeat yourself) . Есть злой, но справедливый перевод «копипаст – признак тупости». Вот этим явлением мы и боремся.
Если в вашем решении несколько страниц и на каждой у вас есть подключение к БД, вывод DOCTYPE и прочей вёрстки — выносите это, пожалуйста, в отдельный файл и подключайте через include или require.
Пример хорошего кода:
94
Разделение логики и представления�По-простому
95
Разделение логики и представления�По-взрослому
Model View Controller
96
Разделение логики и представления�По-взрослому
Model View Controller
97
View
Разделение логики и представления�По-взрослому
А где же Model? а ее нет. просто все слишком
зато есть функция “рендера” шаблона
98
Подключение к БД
99
Портируемость: пути
Можно ли запустить код потенциального коллеги на windows- и linux-сервере без правки файлов и их имен?
Невнимание к регистру имен файлов и пути вроде С:/Интерволга/Программирование/Тестовое задание нас огорчают.
Пример хорошего кода:
100
Портируемость: имена
Имена файлов – в нижнем регистре
К сожалению, не все знают, что у разных ОС разная чувствительность к регистру названий файлов. Чтобы код корректно работал в обоих семействах крупнейших ОС (linux и windows) все файлы должны иметь названия в нижнем регистре.
101
Задавайте вопросы.
Ерофеев Анатолий Андреевич�руководитель отдела разработки
вертикальная оцифровка бизнеса
слайды к 6 лекции примерно
Задача для погружения: �авторизация на сайте
Есть сайт, состоящий из N страниц. Часть этих страниц должна быть доступна только авторизованному пользователю.
Требуется: реализовать авторизацию и контроль доступа.
Подсказка: нужно использовать куки и сессии
// Вопрос к аудитории: что это и как связано?
<?
session_start(); // Необходимо, чтобы использовать $_SESSION
104
Задача для погружения: �авторизация на сайте
// Вопрос к аудитории: почему нельзя хранить в открытом?
105