Ошибка в коде CakePHP: 6 самых распространенных ошибок, которые допускают разработчики CakePHP

Опубликовано: 2022-03-11

CakePHP — удивительная PHP-инфраструктура, но у нее крутая кривая обучения! Чтобы стать экспертом, требуется много исследований и тренировок.

Мне посчастливилось использовать CakePHP уже более 7 лет, и за это время я имел честь работать со многими членами сообщества CakePHP.

В этом руководстве по CakePHP я хотел бы описать несколько плохих практик, с которыми я сталкивался за многие годы, и предложить правильный подход, чтобы избежать этих ошибок. Это не значит, что мой код идеален, но как программисты мы всегда учимся, поэтому важно следовать лучшим практикам и корректировать их по мере обучения!

Содержание этой статьи вдохновлено сообщением от CakeCoded. Если вы хотите узнать больше о CakePHP, посетите раздел обучения здесь.

Этот учебник по CakePHP для начинающих поможет вам не засорять код CakePHP ошибками и ошибками!

Распространенная ошибка № 1: несоблюдение соглашений о кодировании CakePHP

Соглашения о кодировании CakePHP можно посмотреть здесь. Я выделю несколько вещей, которые я часто замечаю при просмотре кода других программистов.

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

 if ((expr_1) || (expr_2)) { // action_1; } elseif (!(expr_3) && (expr_4)) { // action_2; } else { // default_action; }

Должен быть 1 (один) пробел перед первой скобкой и 1 (один) пробел между последней скобкой и открывающей скобкой. Таким образом, это означает, что следующее неверно:

 if($this->request->data){ }

Обратите внимание на расстояние между if и ( , и между ) и {

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

Так, например, следующее неверно:

 if ($foo) $bar = true

Это должно быть отформатировано следующим образом:

 if ($foo) { $bar = true }

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

Вот несколько некорректных примеров:

 if ($foo) { $bar = true; }

Это неверно, открывающая скобка должна стоять в первой строке:

 if ($foo) { $bar = true; if ($action) { $to = false; } }

Отступ должен быть выровнен правильно.

Я часто слышу, как программисты говорят: «Но я слишком занят, чтобы сделать код аккуратным…». Мой ответ: «Поверьте мне, аккуратный код выдержит испытание временем». Написание кода CakePHP, который не читается, будет кошмаром, если вам нужно будет внести изменения через несколько месяцев.

Распространенная ошибка № 2: неправильное использование вмещаемого поведения и рекурсивных уровней в ORM

Недавно мне посчастливилось провести неформальную беседу с разработчиком базы данных из Facebook. Мы начали говорить о CakePHP, и он сказал мне: «О, это использует ORM, не так ли? Это может быть страшно». Я спросил его, что он имеет в виду, и он заметил, что при объектно-реляционном отображении (ORM) SQL-запросы легко становятся излишне большими.

В чем-то он прав. Часть волшебства CakePHP заключается в использовании ORM и в том, как он группирует вместе различные отношения таблиц базы данных. По умолчанию CakePHP автоматически выбирает любые связанные данные «Принадлежит», «Имеет один» и «Имеет много», и это может привести к очень большим SQL-запросам. Эти запросы могут не вызывать беспокойства при первоначальной разработке приложения, но после шести месяцев сбора оперативных данных вы можете обнаружить, что приложение работает очень медленно и в некоторых случаях дает сбой, если запросы не оптимизированы.

При аудите существующего веб-сайта я обращаю внимание на две вещи. Во-первых, был ли изменен рекурсивный уровень по умолчанию? По умолчанию CakePHP устанавливает уровень рекурсии равным 1, что, на мой взгляд, слишком велико. Я всегда устанавливаю для него значение -1, а затем использую содержащееся поведение для получения любых связанных моделей.

Это приводит ко второму вопросу, который я ищу: использовалось ли поведение Containable? Ко мне часто приходят новые клиенты и говорят, что CakePHP работает медленно. Причина почти всегда в том, что Containable не использовался! Хороший программист CakePHP оптимизирует свои SQL-запросы независимо от того, сколько «автоматической магии» делается за кулисами.

Контейнерное поведение не было добавлено до CakePHP 1.2, но что изменилось?! Убедитесь, что используете containerable как можно чаще, так как это эффективный способ оптимизировать ваш SQL. Для получения дополнительной информации о том, как реализовать и использовать поведение Containable, щелкните здесь.

Распространенная ошибка № 3: Сохранение бизнес-логики в контроллерах, а не в моделях

Хороший код CakePHP будет иметь логику в файлах моделей. К этому нужно немного привыкнуть, но однажды освоив, уже нельзя оглядываться назад! Файл контроллера следует использовать для того, для чего он предназначен в шаблоне MVC — для управления! Поэтому используйте файл контроллера для обработки действий пользователя, а бизнес-логику поместите в файл модели.

Хорошим примером этого может быть простой CRUD — повседневное действие! В качестве примера возьмем функцию добавления сообщений из учебника по блогам. Функция добавления по умолчанию выглядит следующим образом:

 public function add() { if ($this->request->is('post')) { $this->Post->create(); if ($this->Post->save($this->request->data)) { $this->Session->setFlash(__('Your post has been saved.')); return $this->redirect(array('action' => 'index')); } $this->Session->setFlash(__('Unable to add your post.')); } }

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

Вместо этого мы напишем для этого функцию в нашей модели Post.php . Возможно что-то вроде этого:

 public function addPost($data = array(), $emailAdmin = true) { $this->create(); $this->save($data); // update any other tables // send the email to the admin user if ($emailAdmin) { } // if all is successful return true; }

Затем это приведет к небольшому изменению действия контроллера следующим образом:

 public function add() { if ($this->request->is('post')) { if ($this->Post->addPost($this->request->data)) { $this->Session->setFlash(__('Your post has been saved.')); return $this->redirect(array('action' => 'index')); } $this->Session->setFlash(__('Unable to add your post.')); } }

Как видите, новое действие на одну строку меньше, потому что $this->Post->create() перемещено в файл модели.

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

Распространенная ошибка № 4: слишком усложнять код вместо частого и раннего возврата

Это всегда является чем-то вроде постоянных дебатов, но частый возврат и ранний возврат, безусловно, делает код намного чище. Это относится к методам модели в большей степени, чем к чему-либо еще.

Но что именно я имею в виду? Итак, давайте взглянем на метод, который мы добавили в руководстве по CakePHP выше:

 public function addPost($data = array(), $emailAdmin = true) { $this->create(); $this->save($data); // update any other tables // send the email to the admin user if ($emailAdmin) { } // if all is successful return true; }

Возврат часто и ранний возврат означает, что при выполнении нашей функции мы регулярно проверяем, все ли в порядке. Если это не так, то мы возвращаем false или возвращаем ошибку CakePHP.

Проще всего показать это на примере. Существует два способа написания вышеуказанной функции:

 public function addPost($data = array(), $emailAdmin = true) { if ($data) { $this->create(); $result = $this->save($data); if ($result) { // update any other tables // send the email to the admin user if ($emailAdmin) { // send the admin email } } else { // problem saving the data return false; } // if all is successful return true; } else { // no data submitted return false; } }

Видите, как код быстро становится нечитаемым? Повсюду есть if и else , и функция быстро становится одним большим отступом. Не поймите меня неправильно, я люблю чистые отступы, но посмотрите, как выглядит функция, если она часто пишется с возвратом, принцип возврата раньше.

 public function addPost($data = array(), $emailAdmin = true) { if (!$data) { // no data submitted return false; } $this->create(); $result = $this->save($data); if (!$result) { // problem saving the data return false; } // update any other tables // send the email to the admin user if ($emailAdmin) { // send the admin email } // if all is successful return true; }

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

Это позволяет программисту CakePHP писать так же, как мы читаем — читая код слева направо, сверху вниз, а не по разным блокам, что может быстро запутать!

Распространенная ошибка № 5: неиспользование принципа DRY

DRY расшифровывается как Don't Repeat Yourself, и это философия, которой следует придерживаться при программировании на CakePHP. В объектно-ориентированном коде нет оправдания повторению одного и того же блока кода дважды!

Вот несколько советов CakePHP, которые помогут вам не повторяться:

  • Как упоминалось выше, стремитесь поместить логику в файлы модели, чтобы вы могли поделиться логикой.

  • В ваших файлах представлений, если вы повторяете представления, создайте код представления в виде элемента или даже пользовательского помощника.

  • Настройте некоторые параметры конфигурации — файл app/Config/bootstrap.php — отличное место для этого. Это помогает убедиться, что вы не жестко кодируете такие вещи, как имя приложения и основной адрес электронной почты. Последнее, что вы хотите делать, это просматривать сотни файлов только потому, что клиент попросил обновить адрес электронной почты в приложении.

  • Всегда спрашивайте себя: «Если я повторяю код, есть ли лучший способ написать этот код, и помещаю ли я этот код в нужное место?» Скорее всего, если вам нужно повторить код, его можно было бы написать лучше.

Распространенная ошибка № 6: Отсутствие комментариев к коду

Последнее, что я хочу сказать, касается комментариев. Во-первых, блокировка документов. Блок документации — это когда вы документируете метод или действие. Чтобы записать немного о том, что делает функция, требуется всего минута, но это имеет огромное значение с точки зрения удобочитаемости кода.

Блоки документов CakePHP должны располагаться напротив левого края страницы. Итак, простой пример с использованием кода выше.

 /** * Adds & saves a post as well as emails the admin to let them know the post has been added. * Also performs some saving to another table * * @param array $data The post data * @param bool $emailAdmin If set to true, will email the website admin * @return bool Returns true if successful */ public function addPost($data = array(), $emailAdmin = true) {

Как вы увидите, написание блока документации не занимает много времени, но имеет огромное значение с точки зрения долговечности кода. В конечном счете, это означает, что код может жить после вас как разработчика.

Так же и со встроенными комментариями. Не бойтесь объяснять, что делает ваш код и почему! В долгосрочной перспективе это значительно упрощает понимание вашего кода, особенно если его просматривает другой разработчик!

Заворачивать

CakePHP — это обширный полнофункциональный фреймворк. Учитывая, что он следует соглашению по конфигурации, CakePHP более строг, чем другие фреймворки на основе PHP, в том смысле, что пользователь «вынужден» следовать определенному способу компоновки кода. Это может быть спорным, но, по моему опыту, это приводит к тому, что кодовая база становится более последовательной, удобочитаемой и понятной — вместо того, чтобы позволить разработчику «выбирать», как код должен быть написан, команда разработчиков будет писать согласованный код, следуя соглашениям Cake. .

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