---

name: Логические операторы
theory: |

  Логические выражения могут объединяться друг с другом, создавая всё более хитрые проверки. Хороший пример: проверка пароля. Как вы знаете, некоторые сайты при регистрации хотят пароль от 8 до 20 символов в длину. Честно говоря, это странное ограничение, но что поделать. В математике мы бы написали `8 < x < 20` (где `x` это длина конкретного пароля), но в PHP такой трюк не пройдет. Нам придётся сделать два отдельных логических выражения и соединить их специальным оператором «И»:

  ```
  Пароль длиннее 8 символов **И** пароль короче 20 символов.
  ```

  Вот функция, которая принимает пароль и говорит, соответствует ли он условиям, или не соответствует:

  ```php
  <?php

  function isCorrectPassword($password)
  {
      $length = strlen($password);
      return $length > 8 && $length < 20;
  }

  isCorrectPassword('qwerty'); // false
  isCorrectPassword('qwerty1234'); // true
  isCorrectPassword('zxcvbnmasdfghjkqwertyui'); // false
  ```

  `&&` - означает «И» (в математической логике это называют конъюнкцией). Всё выражение считается истинным только в том случае, когда истинен каждый операнд — каждое из составных выражений. Иными словами, `&&` означает «и то, и другое». Приоритет этого оператора ниже, чем приоритет операторов сравнения, поэтому выражение отрабатывает правильно без скобок. Кроме `&&`, часто используется оператор `||` — «ИЛИ» (дизъюнкция). Он означает «или то, или другое, или оба». Операторы можно комбинировать в любом количестве и любой последовательности, но когда одновременно встречаются `&&` и `||`, то приоритет лучше задавать скобками.

  Ниже пример расширенной функции определения корректности пароля:

  ```php
  <?php

  function hasSpecialChars($str)
  {
      // проверяет содержание специальных символов в строке
  }

  function isStrongPassword($password)
  {
      $length = strlen($password);
      // Скобки задают приоритет. Понятно что к чему относится.
      return ($length > 8 && $length < 20) && hasSpecialChars($password);
  }
  ```

  Другой пример. Мы хотим купить квартиру, которая удовлетворяет условиям: площадь от 100 кв. метров и больше на любой улице **ИЛИ** площадь от 80 кв. метров и больше, но на центральной улице `Main Street`.

  Напишем функцию, проверяющую квартиру. Она принимает два аргумента: площадь (число) и название улицы (строку):

  ```php
  <?php

  function isGoodApartment($area, $street)
  {
      return $area >= 100 || ($area >= 80 && $street === 'Main Street');
  }

  var_dump(isGoodApartment(91, 'Queens Street'));  // => false
  var_dump(isGoodApartment(78, 'Queens Street'));  // => false
  var_dump(isGoodApartment(70, 'Main Street'));    // => false

  var_dump(isGoodApartment(120, 'Queens Street')); // => true
  var_dump(isGoodApartment(120, 'Main Street'));   // => true
  var_dump(isGoodApartment(80, 'Main Street'));    // => true
  ```

  Область математики, в которой изучаются логические операторы, называется булевой алгеброй. Ниже показаны «таблицы истинности» — по ним можно определить, каким будет результат применения оператора:

  ## И `&&`

  | A     | B     | A `&&` B |
  | ----- | ----- | -------- |
  | TRUE  | TRUE  | **TRUE** |
  | TRUE  | FALSE | FALSE    |
  | FALSE | TRUE  | FALSE    |
  | FALSE | FALSE | FALSE    |

  Пара примеров:

  ```php
  <?php

  // true && true;
  3 > 2 && str_starts_with('wow', 'w'); // true

  // true && false;
  'start' === 'start' && 8 < 3; // false
  ```

  ## ИЛИ `||`

  | A     | B     | A `‖` B  |
  | ----- | ----- | -------- |
  | TRUE  | TRUE  | **TRUE** |
  | TRUE  | FALSE | **TRUE** |
  | FALSE | TRUE  | **TRUE** |
  | FALSE | FALSE | FALSE    |

  Пара примеров:

  ```php
  <?php

  // true || true;
  3 > 2 || str_starts_with('wow', 'w'); // true

  // false || false;
  'start' === 'Start' || 3 < 3; // false
  ```

instructions: |

  Реализуйте функцию `isLeapYear()`, которая определяет, является ли год високосным или нет. Год будет високосным, если он кратен (то есть делится без остатка) 400 или он одновременно кратен 4 и не кратен 100. Как видите, в определении уже заложена вся необходимая логика, осталось только переложить её на код:

  ```php
  <?php

  isLeapYear(2018); // false
  isLeapYear(2017); // false
  isLeapYear(2016); // true
  ```

  Кратность можно проверять так:

  ```php
  <?php

  // % - возвращает остаток от деления левого операнда на правый
  // Проверяем что number кратен 10
  $number % 10 === 0
  // Проверяем что number не кратен 10
  $number % 10 !== 0
  ```

tips:
  - |
    [Булева алгебра](https://ru.wikipedia.org/wiki/Булева_алгебра)
  - |
    [Конъюнкция](https://ru.wikipedia.org/wiki/Конъюнкция)
  - |
    [Дизъюнкция](https://ru.wikipedia.org/wiki/Дизъюнкция)

definitions:
  - name: "Логические операторы"
    description: "операторы «И» (&&), ИЛИ (||), позволяющие создавать составные логические условия."
