1 of 105

Лекция 3: �Введение в разработку на PHP�Требования к коду

intervolga.ru/school/

Ерофеев Анатолий Андреевич

Руководитель отдела разработки

1

2 of 105

2

Устройство ИНТЕРНЕТА,

HTTP, HTML, верстка

Веб-сервер�Лекции 1 и 2�ЛР 1

Работа с данными�PHP, MySQL, веб-формы, фильтрация данных�Лекции 3 и 4�ЛР 2

3 of 105

Язык PHP: история

  • Создан датским программистом Расмусом Лердорфом в 1994-м. (для сравнения Python был выложен в open source в 1991-м)�
  • Расшифровывается как “PHP: Hypertext Preprocessor” (ранее как “Personal Home Page Tools”)�
  • Изначальная цель: вкрапление динамической информации в статичные html-страницы.�
  • Особенность номеров версий: все четные номера - для развития языка, все нечетные - публичные релизы.�Актуальная на сегодня версия 8.x

3

4 of 105

Язык PHP: история

  • 7.x (последняя версия 7.4.33) — поддержка завершена 28 ноября 2022 года
  • 5.x (5.6.40) — 31 декабря 2018 года
  • 4.x (4.4.9) — 7 августа 2008 года
  • 3.x — 20 октября 2000 года

4

5 of 105

Язык PHP: история

  • В развитии языка большую роль сыграла компания Zend (много инвестиций в производительность)
  • 7-я версия PHP в среднем в 2-3 раза быстрее Python 3.7
  • В отличие от других веб-ориентированных языков (Python, NodeJS, Asp.Net) поддерживается подавляющим большинством хостинг-провайдеров

Язык имеет C-подобный синтаксис, динамическую типизацию, сборщик мусора.�Характеризуется низким порогом входа.

5

6 of 105

2 способа запуска

Из консоли

>> php -f /home/user/test.php�Этот способ активно используется при миграциях, установках и любых других долгих операциях.

В том числе для запуска регламентных задач через cron

Из браузера (через веб-сервер)

6

Браузер

Веб-сервер (Apache, Nginx)

PHP

test.php

HTTP-запрос

HTTP-ответ

вызов

html/text

чтение файла

исходный текст

7 of 105

Как выглядит PHP-разработка

  1. Инструменты
  2. Процесс
  3. Артефакты
  4. Результат

7

8 of 105

PHP-разработка. Инструменты

  1. IDE. Рекомендуем PhpStorm, но можно что угодно (Sublime Text, Notepad++, Eclipse PDT, NetBeans…).
    1. Важно для понимания: IDE не запускает php-скрипты, только редактирует их. Запускаются php-скрипты на сервере.
  2. Серверная среда для разработки (в составе готового окружения XAMPP или ручная установка php на ПК или виртуальную машину)
  3. Браузер любой

8

9 of 105

PHP-разработка. Процесс

9

10 of 105

PHP-разработка. Процесс

  1. На своем ПК в IDE разработчик создает и правит .php-файлы
  2. Разработчик загружает .php-файлы на веб-сервер (в вашем случае веб-сервер=локальный ПК, в реальности тут git/sftp и т.п.)
  3. В браузере разработчик открывает новые страницы и узнает, молодец ли он

10

11 of 105

PHP-разработка. Артефакты

  • .php и другие файлы на веб-сервере(.js, .css, картинки, шрифты, документы для скачивания…). Хранятся также в git-репозитории
  • Данные в БД MySQL. В репозитории должны быть:
    1. .sql-файлы, скрипты установки пустых таблиц
    2. .sql-файлы, скрипты создания “эталонных” данных (aka миграции)
    3. Создали таблицу и написали php-код? => не забудьте создать .sql-файл установки и миграции данных

11

12 of 105

PHP-разработка. Результат

  1. Для обычного пользователя:
    1. По ссылке http(s) — в браузере открывается функционирующий сайт
  2. Для разработчика:
    • инструменты для мониторинга (Zabbix, htop, iotop…)
    • конфигурирования (htaccess, .conf-файлы)
    • управления контентом (админка сайта/phpmyadmin)

12

13 of 105

Синтаксис

// Исторический вариант вставки PHP в HTML (содержимое .php-файла)

<html>

<head>

<title>

Тестируем PHP

</title>

</head>

<body>

<?php echo "Привет мир!"; ?>

<?= 'Привет мир!' /* сокращенная форма для вывода данных */?>

</body>

</html>

13

14 of 105

Какой HTML-код попадет в браузер?

// Исторический вариант вставки PHP в HTML (содержимое .php-файла)

<html>

<head>

<title>

Тестируем PHP

</title>

</head>

<body>

Привет мир!

Привет мир!

</body>

</html>

14

15 of 105

Что увидит пользователь в браузере?

// Исторический вариант вставки PHP в HTML (содержимое .php-файла)

Привет мир!Привет мир!

15

16 of 105

Правильно разделять логику (PHP) и представление (html+css+графику)

// Вариант вкрапления PHP с разделением .php-файла на логику работы с данными и собственно вывод)

<?php // логика�$a = 1+5; �$text = "Привет мир, 1+5 =".$a;

?><!-- представление --><html>

<head><title>Тестируем PHP</title></head>

<body>

<?=$text?>

</body>

</html>

16

17 of 105

Следующий шаг – выделение “шаблона” в отдельный документ

// 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

18 of 105

Логика подключает Представление или наоборот

// 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

19 of 105

Синтаксис PHP-вставок

// Полная форма

<?php

echo “Hello world”

?>

// Краткая форма с короткими тегами

<?

echo “Hello world”

  • Краткую форму использовать не рекомендуется, потому что она считается устаревшей и может быть совсем удалена в будущем
  • Закрывать PHP-тег не нужно, если после него ничего не выводится

19

20 of 105

Типы данных

  • целочисленный тип (integer)
  • число с плавающей точкой (float, double, real)
  • логический тип (boolean)
  • строковый тип (string)
  • массив (array)
  • объект (object)
  • внешний ресурс (resource)
  • неопределенное значение (null)

Существует еще несколько "псевдотипов", в рамках курса они нам не понадобятся.

Тип переменной определяется по ее значению (не объявляется).

20

21 of 105

Строки. Виды кавычек

Одинарные и двойные кавычки

В PHP для строк используют как одинарные ', так и двойные " кавычки. В большинстве случаев они работают одинаково, но не всегда. Например, если использовать переменную внутри одинарных кавычек, то выведется её имя. А если внутри двойных, то значение:

$name = 'Думпо';

keks_log('Слона зовут $name'); // Выведет: "Слона зовут $name"

keks_log("Слона зовут $name"); // Выведет: "Слона зовут Думпо"

Двойные кавычки помогают избежать запутанной конкатенации. О том, какие ещё есть различия между кавычками, вы можете узнать в документации.

21

22 of 105

Переменные

Имя переменной всегда начинается с символа $, чувствительно к регистру. Объявлять переменные не нужно.

<?php

$x = 12; $y = 4; echo $x/$y;

Строковые переменные можно объявлять через одинарные или двойные кавычки. Двойные поддерживают подстановку переменных.

<?php

$x = 'world';

$y = 'Hello, $x; // => Hello, $x

$y = "Hello, $x"; // => Hello, world

22

23 of 105

Переменные-массивы

Особый тип переменных. Внутри устроен как словарь с сохранением порядка вставки.

Если ключи массива являются целыми числами без пропусков от 0 до N-1, такой массив называют “индексированным”. Если это условие не выполняется - “ассоциативным”.

<?php

$a = []; // пустой массив

$b = [1, 5, 3]; // индексный

$c = ['a' => 1, 'c' => 5, 'b' => 3]; // ассоциативный

23

24 of 105

Переменные-массивы

Основные операции с массивами:

  • Вставка в конец $x[] = 12
  • Вставка с ключом $x['abc'] = 12;
  • Проверка наличия ключа isset($x['abc'])
  • Удаление по ключу unset($x['abc'])
  • Вычисление длины count($x)
  • Обход массива (помимо обычного for)�foreach($arr as $key => $value) {...}foreach($arr as $value) {...} // сокращенная форма

24

25 of 105

Индексные 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

26 of 105

Примеры на массивы

Вложенные массивы

Массивы могут содержать в себе другие массивы. Такие массивы называются вложенными.

$flowers = [

0 => [

'name' => 'Ромашка',

'cost' => 'free'

],

1 => [

'name' => 'Лилия',

'cost' => 300

]

];

echo $flowers[0][‘name’];

26

27 of 105

Функции работы с массивами

Колбэком называют функцию, которую передают в качестве аргумента другой функции. Колбэки не являются встроенными функциями, их пишут сами разработчики.

uasort

Встроенная функция uasort сортирует массив. Эта функция принимает два аргумента: массив, который нужно отсортировать, и имя функции-колбэка.

uasort($array, 'callback');

Функция-колбэк, которую мы передаём uasort, должна принимать два аргумента и возвращать число: положительное число, если первый аргумент больше, отрицательное число, если больше второй аргумент, и ноль, если аргументы равны.

Во время вызова uasort передаёт в колбэк по двое элементы массива, узнаёт, какой из них больше, и сортирует массив по возрастанию: от меньшего к большему.

array_slice

Функция array_slice принимает массив, копирует его часть и возвращает её в виде нового массива. Массив, который передали функции, при этом не изменяется.

Функция принимает четыре аргумента:

  • исходный массив,
  • порядковый номер элемента, с которого начнётся копирование,
  • количество элементов, которые нужно скопировать,
  • булево значение — нужно ли сохранять ключи исходного массива.

$new_array = array_slice($array, $first_element, $length, $preserve_keys);

27

28 of 105

Функции работы с массивами

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

29 of 105

Функции работы с массивами

shuffle

Встроенная функция shuffle перемешивает массив. Функция принимает массив и выстраивает его элементы в случайном порядке. Будьте осторожны, функция shuffle изменяет переданный ей массив и не сохраняет ключи. С ассоциативными массивами её лучше не использовать.

shuffle($array);

Объединение массивов

В PHP массивы можно объединить с помощью знака плюс:

$big_array = $array_1 + $array_2;

В результате получится один массив, который включает элементы как из первого, так и из второго массива. При этом порядок элементов и их ключи сохранятся.

Если у нескольких элементов окажутся одинаковые ключи, то значение возьмётся из того массива, который идёт раньше. Перед объединением убедитесь, что ключи в массивах не совпадают или что одинаковым ключам соответствуют одинаковые значения.

29

30 of 105

Логические переменные

Константы: TRUE, false (регистр не важен)

При приведении выражения/переменной к логическому типу

  • 0,
  • "" (пустая строка)
  • "0" (ноль в строке),
  • NULL,
  • пустой массив

считаются равными FALSE

Для “защиты от дурака” рекомендуется по умолчанию всегда использовать оператор === вместо ==, он более корректно обрабатывает нетривиальные сравнения.

30

31 of 105

Лайфхак по стилю кодирования

Вы убережете себя от множества сложно отлаживаемых проблем (во многих языках), если будете соблюдать следующие советы:

  1. В условиях всегда ставьте переменную справа, а константы и вызовы функций слева (даже если это пока что условие < >)�if (123 === $x) {...}�if ($x = false) {...} // легко не заметить ошибку�if (some_func() === 0) {...}
  2. Всегда выделяйте выражения в блочные операторы (скобки), даже если выражение единственное (пока что)�if (strpos(...) > 0) { return true; }

31

32 of 105

Глобальные переменные

// Использовать глобальные переменные в целом нехорошо

Но если нужно, то:

  • Сначала объявить с помощью ключевого слова global
  • Затем использовать (читать/писать)

<?php

// a.php

global $x;

$x = 12;

require('b.php');

32

<?php

// b.php

global $x;

echo $x;

33 of 105

Суперглобальные массивы

В PHP существует несколько глобальных переменных, доступных без объявления. Они называются “суперглобальными массивами”:

  • $GLOBALS - для доступа ко всем переменным, объявленным с помощью global
  • $_SERVER - параметры сервера (REQUEST_METHOD, REMOTE_ADDR)
  • $_GET - get-параметры текущего запроса
  • $_POST - post-параметры текущего запроса
  • $_FILES - файлы, присланные с текущим post-запросом
  • $_COOKIE - cookies, присланные с текущим запросом
  • $_SESSION - пользовательская сессия, сопоставленная сервером текущему запросу
  • $_REQUEST - объединенный массив и $_GET и $_POST
  • $_ENV - переменные окружения

33

34 of 105

Операторы

  • Арифметические: +, -, ++, --, *, /, %, **
  • Логические: >, <, >=, <=, ==, ===, !=, !, ||, &&
  • Побитовые: |, &, ~
  • Строковые: . (конкатенация) // $x = 'Hello' . ' ' . 'world';

34

35 of 105

Циклы

Цикл с предусловием (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

36 of 105

Условия

<?php

$x = 9;

if ($x > 10) {

echo 'Число больше 10';

} elseif (10 === $x) {

echo 'Число равно 10';

} else {

echo 'Число меньше 10';

}

36

37 of 105

Условия

<?php

$x = 9;

$result = $x > 10 ? 'Число больше 10' : 'Число не больше 10';

echo $result;

37

38 of 105

Условия

<?php

$x = 1;

switch ($x) {

case 1: echo ‘Число равно 1’; break;

case 2: echo ‘Число равно 2’; break;

default: echo ‘Другое значение’;

}

38

39 of 105

Альтернативный синтаксис для условий

<?php if (condition): ?>

html code to run if condition is true

<?php else: ?>

html code to run if condition is false

<?php endif ?>

39

40 of 105

Примеры

Внедрение условия в шаблон

PHP позволяет использовать условия внутри шаблонов, чтобы менять разметку в зависимости от ситуации.

<?php if (условие): ?>

разметка

<?php endif; ?>

Конкатенация

Операция склеивания нескольких строк в одну.

$product_class = 'item' . ' item-hot';

// Получается строка 'item item-hot', все пробелы сохраняются

40

41 of 105

Примеры: Добавление класса в разметку

Условие в шаблоне

<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

42 of 105

Примеры: Динамический <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

43 of 105

Включение внешних файлов

  • Существует 4 конструкции, формируемые из 2-х пар слов:

include/require + once/[пусто]

  • require выполняется до старта программы, include - во время работы
  • require выдаст ошибку если файл отсутствует, include - нет
  • once - позволяет не подключать 1 файл дважды

Как правило, используется require_once

<?php require_once($_SERVER['DOCUMENT_ROOT'] . '/db.php');

// ...

43

44 of 105

Функции

<?php

function abc($arg1, array $arg2, &$arg3) {

return 12;

}

$y = 'abc';

$x = abc(1, [2,3,4], $y);

?>

44

45 of 105

Классы

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

46 of 105

Отображение ошибок

Настройки, влияющие на отображение ошибок:

  • error_reporting = E_ALL
  • display_errors = On

4 уровня переопределения настроек:

  • Глобальные настройки PHP (php.ini)
  • Глобальные настройки веб-сервера (обычно Apache->site.conf)
  • Локальные настройки папки (обычно Apache->.htaccess)�php_value display_errors 1

php_value error_reporting E_ALL

  • Локальные настройки php-скрипта�ini_set('error_reporting', E_ALL)

для большинства параметров или точечно для error_reporting: error_reporting(E_ALL & ~E_NOTICE);

46

47 of 105

Типовая отладка

<?php

echo '<pre>';

print_r($_GET);

echo '</pre>';

echo '<pre>';

$x = 12; var_dump($x);

var_dump($_GET);

echo '</pre>';

47

48 of 105

Продвинутая отладка

  • Отладка и Профилирование XDebug�Непростая настройка, пошаговое выполнение, запрещено на production-сервере�
  • Профилирование XHProf�Простая настройка, только мониторинг скорости/памяти, допустимо на production-сервере

48

49 of 105

Хорошие практики

  • Выносите код подключения к БД в отдельный файл.�Само подключение делайте доступным (лучше) через singleton или (хуже) через глобальную переменную.
  • Отделяйте код с логикой от шаблона вывода
  • Стройте свои скрипты по принципу “логика - в начале файла”, “вывод данных” - в конце
  • Используйте фреймворки (после окончания базового курса): �Zend, Symphony, Laravel, 1С-Битрикс
  • Не изобретайте велосипед
    • Сформулируйте суть задачи на английском
    • Введите в поиске на github.com
    • Отфильтруйте по языку, отсортируйте по количеству контрибьюторов
  • Используйте пакетный менеджер: composer

49

50 of 105

Хорошие практики

<?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

51 of 105

Хорошие практики

Представьте, что посетитель интернет-магазина долгих 10 минут настраивал фильтр по смартфонам (цена, бренд, диагональ, ЦПУ, срок доставки).

А после нажатия на кнопку “Найти” увидел 0 предложений. Он захочет изменить свой запрос, но вряд ли захочет заново заполнять все поля.

Мораль: после перезагрузки страницы в форме надо “восстанавливать” все значения в полях, чтобы пользователь

  1. Видел и понимал, что форма сработала и его значения учитываются в фильтре
  2. Мог быстро скорректировать свои запросы
  3. Мог поделиться ссылкой на эту страницу (если форма работает по GET-методу)

<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 of 105

Источники

  1. Лекции ИНТУИТ по PHP
  2. Лекции mail.ru по веб-разработке

52

53 of 105

отвлечемся на ЛР 2

54 of 105

Лабораторная работа 2

  • работа с таблицами,
  • веб-формы,
  • get-запросы,
  • чтение данных из БД
  • организация кода
  • немного безопасности

55 of 105

ЛР 2: �таблицы, формы, запросы, чтение из БД

Цель работы:

Познакомиться с работой связки браузер-сервер, get-запросами, обработкой данных и базой данных.

Суть:

  1. Программируем работу с данными на SQL+PHP+HTML, работаем с GET-запросами
  2. Учимся связывать HTML и PHP, обращаться к базе данных.
  3. Демо-вариант ЛР 2 доступен по ссылке https://volgu.ivdev.ru/LR2/drugs.php

Ход работы

  1. В вашем варианте ЛР описана структура таблицы, которую вы будете использовать
  2. Найдите ее и поймите что эта структура означает.
  3. Создайте структуру базы данных из 2 таблиц вроде такой (рекомендуем использовать https://dbdesigner.net ). Далее везде примеры для варианта 61 из списка тем лабораторной работы.

55

56 of 105

Ход работы

Задание 61:

Пример исполнения:

Между сущностями реализована связь один-ко-многим (т.е. на одну запись из таблицы drugs может быть найдена только одна запись из таблицы brands, а для одной записи из brands может быть множество разных записей из drugs).

56

57 of 105

Как все должно выглядеть

Примерно как тут, в вашем варианте: https://volgu.ivdev.ru/LR2/drugs.php

57

58 of 105

58

59 of 105

Ход работы

Рекомендуем установить XAMPP — пакет из программ Apache (веб-сервер), MariaDB (СУБД), PHP (интерпретатор языка программирования)

  • Скачиваем и устанавливаем с официального сайта
  • Запускаем XAMPP Control Panel
  • Запускаем Apache
  • Все файлы сайта размещаются в C:\xampp\htdocs (для Windows) и доступны в браузере по адресу http://localhost

59

60 of 105

Ход работы

Пример исполнения:

Между сущностями реализована связь один-ко-многим (т.е. на одну запись из таблицы drugs может быть найдена только одна запись из таблицы brands, а для одной записи из brands может быть множество разных записей из drugs).

60

61 of 105

Ход работы

Создайте главную таблицу в MYSQL (через консольный доступ или phpmyadmin, он доступен по адресу http://localhost/phpmyadmin/index.php (вместо localhost может потребоваться написать ваш IP-адрес в XAMPP)).

  1. Придумайте название таблицы: лучше всего перевод на английский язык во множественном числе: “страны” = “countries”
  2. Определите тип каждого поля
    1. Ссылку на другую таблицу нужно хранить как номер записи
    2. Картинки нужно хранить как названия файлов в текстовом поле
  3. Создайте Базу данных и Главную таблицу в ней

61

62 of 105

Ход работы

62

63 of 105

Ход работы

Создание БД и таблицы в консоли сервера БД (для общего развития, делать так не не обязательно)

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

64 of 105

Ход работы

Аналогично создаем вспомогательную таблицу brands.

Заполняем обе таблицы данными.

64

65 of 105

Подключение к БД

65

66 of 105

Примеры запросов

Извлекаем все данные �из 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

67 of 105

Примеры запросов

Извлекаем все данные из 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

68 of 105

Примеры запросов

Извлекаем все данные из 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 of 105

Организация файлов проекта

69

70 of 105

Организация файлов проекта

70

71 of 105

Картинки верстки

71

72 of 105

Картинки каталога

72

73 of 105

Программные файлы

73

74 of 105

Как писать код. Логика

74

75 of 105

Логика вывода

75

76 of 105

Как собирать запрос

...

76

77 of 105

Как все должно выглядеть

Примерно как тут, в вашем варианте: https://volgu.ivdev.ru/LR2/drugs.php

77

78 of 105

78

79 of 105

Частые ошибки

  1. Плагиат 🔥
  2. Варианты в <select> фильтра зашиты в код, а не берутся из БД
  3. <select> передает в get-запрос название, а не id
  4. Форма теряет значения после отправки
  5. Кнопка “Очистить фильтр”:
    1. …реализована как type=submit и отправляет форму
    2. …реализована как type=reset и восстанавливает форму к “изначальному” виду
    3. вместо того, чтобы быть ссылкой на текущую страницу без get-параметров
  6. Забыли про безопасность
    • или перепутали htmlspecialchars и PDO
    • или сделали сразу оба варианта

79

80 of 105

Частые ошибки в SQL-запросе

  • При пустом фильтре все равно есть WHERE-часть запрос
  • Не знать разницу между LIKE и точным совпадением
  • Жесткий заранее прописанный SQL-запрос с фильтрами по всем полям
    • …WHERE price > $x AND price < $y…
    • В главный SQL-запрос фильтрации подставляется $y=999999 если пользователь не задал ограничение по максимальному значению, $x=-999999 если не задал минимальное и т.п.
  • Не знать, зачем в WHERE-части написано “AND 1=1” и применять бездумно

Как надо:

  1. Собирать WHERE-кусок запроса по частям
    1. Если задано значение в $_GET по полю
      1. то добавить в WHERE фильтр по этому полю (price > $x)
      2. и добавить AND, если это не последний фильтр (или см. выше 1=1)

80

81 of 105

// вернемся к лекции

82 of 105

Требования к коду бекенд-программиста

83 of 105

Почитать

Об

83

84 of 105

Почитать

84

85 of 105

Почитать

85

86 of 105

Минимальные требования таковы

87 of 105

Требования

  • Защита
  • Оформление кода
  • Эффективность
  • Портируемость
  • Аккуратный фронтенд

87

88 of 105

Защита от SQL-инъекций

Код поиска пользователя по логину:

mysqli_query('select * from users where LOGIN = ' . $_REQUEST['login']);

Если вдруг вместо логина пользователь он подсунет строчку:

Vasya; drop table users;

Нас ждёт удаление всех пользователей из базы данных.

Требуется любым адекватным способом фильтровать входные данных. Нельзя допустить отправку опасного запроса в базу данных или вывода данных с визуальными ошибками.

88

89 of 105

Защита

Использовать

  1. лучше prepared statements , PDO::prepare
  2. или хотя бы real_escape_string , приведение к int для чисел

Большинство программистов не делают ровным счетом ничего для защиты БД. Кто-то использует функции htmlspecialchars , trim , addslashes — настоящей защиты это не даёт. �

Пример хорошего кода:

89

90 of 105

Именование

Искусство выбора подходящих названий играет немалую роль в разработке ПО. Казалось бы, что тут сложного? Правил немного и запомнить их не так сложно:

  1. Единообразие имён. Если одну переменную вы назвали $firstVar то назвать вторую $second_var — отступление от этого правила. Мы не разжигаем холивар и не утверждаем что camelCase лучше чем snake_case (или наоборот) — но если вы выбрали один из этих стилей, то придерживайтесь его всегда.
  2. Использование грамотного английского языка. Если со знанием английского проблемы — начинайте учить, а пока пользуйтесь переводчиком от Google .
  3. Название должно отражать суть содержимого. Ничто так не огорчает опытного техлида, как переменные типа a, b, c. Мы не на уроке математики в 6 классе, код нужно развивать и поддерживать.
  4. Если речь про название переменной или столбца в БД — то должен быть понятен ещё и тип содержимого. Например, в столбце capital хранятся какие-то сведения о столице, но неизвестно какие. Стоит лишь переименовать в capital_name, становится сразу ясно, что речь о названии.

90

91 of 105

Как надо

Мы оцениваем именование по 4 разным направлениям:

  1. БД (таблицы, колонки)
  2. PHP (переменные, классы, функции)
  3. CSS (классы и id)
  4. Файлы

Пример хорошего кода:

91

92 of 105

Оформление кода

Это «критичное» требование. Ваш код не должен быть похож на кашу. Рецепт прост: грамотно и аккуратно расставлять отступы, скобки и комментарии.

Чем хотите, тем и ставьте отступы — но одинаковые по всему коду.

92

93 of 105

Комментарии

Комментариев нет совсем — не молодец

Комментарии есть ко всем смысловым блокам (блоки по 5-10 строк) — молодец

Нет бесполезных комментариев (вроде «добавляем 1 к переменной-счётчику» или «умножаем на 10») и присутствуют комментарии для функций в нотации phpdoc — большой молодец.

Пример хорошего кода:

93

94 of 105

Борьба с дублированием кода

Есть известный принцип программирования — DRY (Don’t repeat yourself) . Есть злой, но справедливый перевод «копипаст – признак тупости». Вот этим явлением мы и боремся.

Если в вашем решении несколько страниц и на каждой у вас есть подключение к БД, вывод DOCTYPE и прочей вёрстки — выносите это, пожалуйста, в отдельный файл и подключайте через include или require.

Пример хорошего кода:

94

95 of 105

Разделение логики и представления�По-простому

95

96 of 105

Разделение логики и представления�По-взрослому

Model View Controller

96

97 of 105

Разделение логики и представления�По-взрослому

Model View Controller

97

View

98 of 105

Разделение логики и представления�По-взрослому

А где же Model? а ее нет. просто все слишком

зато есть функция “рендера” шаблона

98

99 of 105

Подключение к БД

99

100 of 105

Портируемость: пути

Можно ли запустить код потенциального коллеги на windows- и linux-сервере без правки файлов и их имен?

  1. Все в одной папке;
  2. Код не зависит от папки, в которой расположен сайт; имена всех файлов в нижнем регистре.

Невнимание к регистру имен файлов и пути вроде С:/Интерволга/Программирование/Тестовое задание нас огорчают.

Пример хорошего кода:

100

101 of 105

Портируемость: имена

Имена файлов – в нижнем регистре

К сожалению, не все знают, что у разных ОС разная чувствительность к регистру названий файлов. Чтобы код корректно работал в обоих семействах крупнейших ОС (linux и windows) все файлы должны иметь названия в нижнем регистре.

101

102 of 105

Задавайте вопросы.

Ерофеев Анатолий Андреевич�руководитель отдела разработки

e@intervolga.ru

Наши вакансии:

intervolga.ru/vacancy/developer/

вертикальная оцифровка бизнеса

103 of 105

слайды к 6 лекции примерно

104 of 105

Задача для погружения: �авторизация на сайте

Есть сайт, состоящий из N страниц. Часть этих страниц должна быть доступна только авторизованному пользователю.

Требуется: реализовать авторизацию и контроль доступа.

Подсказка: нужно использовать куки и сессии

// Вопрос к аудитории: что это и как связано?

<?

session_start(); // Необходимо, чтобы использовать $_SESSION

104

105 of 105

Задача для погружения: �авторизация на сайте

  • Факт авторизации нужно хранить в безопасном месте - в сессии. Cookies - доступны для редактирования в браузере.
  • Чтобы идентифицировать пользователя недостаточно знать авторизован он или нет. Правильно - хранить ID пользователя.
  • Пароль нужно хранить в хешированном виде.�// Вопрос к аудитории: что такое хеширование и чем отличается от шифрования?

// Вопрос к аудитории: почему нельзя хранить в открытом?

  • Форму авторизации нужно отправлять методом POST.�Общее правило: любые изменения на сервере должны инициироваться методом POST.�Для продвинутого изучения: CSRF-атака

105