├── git-cheat-sheet.txt ├── coding-standart-php.txt ├── git.txt └── symfony.txt /git-cheat-sheet.txt: -------------------------------------------------------------------------------- 1 | moved to: https://gist.github.com/maxim-oleinik/12e743331614592793155b22f07969a6 2 | -------------------------------------------------------------------------------- /coding-standart-php.txt: -------------------------------------------------------------------------------- 1 | Стандарт кодирования PHP 2 | ================================================================================ 3 | 4 | Используем стандарт кодирования Zend: http://framework.zend.com/manual/ru/coding-standard.html 5 | Но будем придерживаться стандарта symfony для именования файлов и классов. 6 | Например: myWidgetFormUploadFile 7 | 8 | Принципиальные требования: 9 | * Кодировка всех файлов в UTF-8 (без BOM) 10 | * Перенос строк - LF 11 | * Отступы - 4 пробела, никаких табов 12 | * Не оставлять в строке замыкающих пробелов 13 | * Правильно расставлять фигурные скобки 14 | -------------------------------------------------------------------------------- /git.txt: -------------------------------------------------------------------------------- 1 | Git: Оформление коммитов и работа с ветками 2 | ================================================================================ 3 | 4 | @see Git-cheat-sheet 5 | https://gist.github.com/maxim-oleinik/12e743331614592793155b22f07969a6 6 | 7 | 1. Коммиты 8 | ---------- 9 | 1.1 Коммиты должны быть атомарными и НЕБОЛЬШИМИ, т.е. одна логическая правка - один коммит. 10 | Все рефакторинги, переименования и пр. параллельные усовершенствования лучше оформлять отдельным коммитом. 11 | Ориентироваться надо на других разработчиков, которые будут просматривать эти коммиты. 12 | 13 | 1.2 Все форматирование кода, приведение к стандарту оформлять ОТДЕЛЬНЫМ коммитом. 14 | 15 | 1.3 Каждую миграцию структуры БД или редактирование миграции оформлять ОТДЕЛЬНЫМ коммитом. 16 | Чтобы иметь возможность объединить несколько коммитов по одной миграции. 17 | 18 | 1.4 Для Git принято соглашение в первой строке сообщения писать краткое описание, 19 | а ЧЕРЕЗ строку - подробное. Т.е. как почтовое сообщение - заголовок и тело. 20 | В заголовок комментария надо обязательно включать номер тикета и тему/компонент, 21 | к которому он относится. 22 | Например: 23 | ---------------------- 24 | t565 Календарь: Ошибка при добавлении периодической операции 25 | 26 | После добавления операции выдаётся ошибка что незаполнена категория, 27 | но при этом не даёт изменить её. Была проблема в формировании ответа 28 | json на сервере. 29 | ---------------------- 30 | 31 | 1.5 Для подготовки коммита НАДО использовать: 32 | git add -p 33 | Чтобы контролировать каждую правку, которая попадет в коммит. 34 | 35 | 1.6 Перед кажым коммитом смотреть дифф будущего коммита: 36 | git diff --cached 37 | 38 | 39 | 2. Ветки 40 | -------- 41 | 2.1 Под каждую задачу создается отдельная ветка и туда отправляются все коммиты по задаче. 42 | 43 | 2.2 В названии ветки указывать тикет и 1-2 слова-описания: t69-profile-email 44 | 45 | 2.3 Если работа над веткой продолжается дольше чем один день. Тогда подтягиваем 46 | ветку каждый день перед началом работы и после окончания, чтобы не накапливать конфликты. 47 | Если коммитов очень много, тогда лучше регулярно мерджить правки из основной ветки. 48 | Но лучше до такого не доводить и дробить задачи или объединять технические коммиты. 49 | 50 | 2.4 Чтобы опубливать ветку для ревью или демонстрации, ее надо подтянуть к родительской: 51 | 52 | # Убедиться, что родительская ветка в актуальном состоянии: 53 | git fetch 54 | git co master 55 | git merge origin/master 56 | 57 | # Подтянуть ветку, если отстала 58 | git co my-branch 59 | git rebase master 60 | 61 | # Отправить в remote 62 | git push origin my-branch 63 | 64 | 2.5 Перед тем как опубликовать ветку - посмореть полный диф всех правок: 65 | git diff НАЧАЛЬНЫЙ_КОММИТ..НАЗВАНИЕ_ВЕТКИ 66 | -------------------------------------------------------------------------------- /symfony.txt: -------------------------------------------------------------------------------- 1 | Требования/соглашения для работы с symfony 2 | ================================================================================ 3 | 4 | 1. Общее 5 | -------- 6 | 1.1 Для собственных классов ставим префикс "my" 7 | Например: mySuperClass или myWidgetFormCustomInput 8 | 9 | 1.2 Генерация html ТОЛЬКО в шаблонах или в хелперах. 10 | 11 | 1.3 Не использовать sfContext::getInstance() 12 | Все внешние зависимости передавать явно через конструктор, сеттеры, опции и пр. 13 | Бывают исключения, когда без контекста не обойтись, но надо четко понимать разницу 14 | между оправданным исключением и хаком. 15 | 16 | 17 | 2. Конфиг 18 | --------- 19 | 2.1 ИСПОЛЬЗОВАТЬ конфиг, а не хардкодить в разных местах 20 | 21 | 2.2 Использовать каскады конфигурации: plugin -> project -> app -> module 22 | 23 | 2.3 Использовать возможности конфигурирования для разных ENV (prod, dev, test) 24 | 25 | 2.4 Всегда включаем защиту от csrf и xss. Отдельные классы, например DateTime, 26 | можно добавить в исключение: 27 | sfOutputEscaper::markClassesAsSafe(array( 28 | 'DateTime', 29 | )); 30 | 31 | 32 | 3. Роутинг 33 | ---------- 34 | 3.1 Не использовать дефолты в правилах для модуля и экшена. 35 | Всегда прописывать явно или указывать перечисление в requirements. 36 | 37 | Так НЕ надо делать: 38 | article: 39 | url: /article/:action 40 | params: { module: article } 41 | 42 | default: 43 | url: /:module/:action/* 44 | 45 | OK: Явно указать ограничение: 46 | article: 47 | url: /article/:action 48 | params: { module: article } 49 | requirements: 50 | action: (?:show|hide) 51 | 52 | 3.2 Если мы используем частичный RouteCollection, тогда явно указываем, что мы используем: 53 | 54 | article: 55 | class: sfDoctrineRouteCollection 56 | options: 57 | module: article 58 | model: Article 59 | actions: [new, create, edit, update, delete] 60 | 61 | 3.3 Используем sfDoctrineRoute и sfDoctrineRouteCollection, чтобы в контроллере 62 | выбирать объект через 63 | $this->getRoute()->getObject() 64 | Фреймворк автоматически выкинет 404 ошибку, если объект не будет найден. 65 | 66 | 3.4 Для контроля за методами запроса используем requirements: 67 | requirements: 68 | sf_method: [get, head] 69 | sf_method: post 70 | sf_method: put 71 | sf_method: delete 72 | Для "get" запросов желательно оставлять возможность "head" запросов. Поисковики все-таки. 73 | 74 | 3.5 Используем requirements, чтобы лимитировать sf_format: 75 | requirements: 76 | sf_format: html 77 | sf_format: (?:html|xml|json) 78 | В противном случае symfony выкинет исключение, если не найдет шаблон для указанного формата, 79 | который мы не поддерживаем. 404 лучше чем 500. 80 | 81 | 82 | 4. Контроллер 83 | ------------- 84 | 4.1 В контроллерах не пришем запросы - по максимуму выносим в таблицы и в фильтры. 85 | 86 | 4.2 Используем всегда, когда это возможно: $this->getRoute()->getObject() 87 | 88 | 4.3 phpdoc для класса и каждого метода. Так наглядно, чисто и удобно. 89 | /** 90 | * Список статей 91 | */ 92 | public function executeIndex(sfRequest $request) 93 | 94 | 4.4 Контроллеры не должны содержать бизнес-логики, вычислений. Все выносить в модели 95 | и отдельные классы. Длинный метод - индикатор перегрузки. 96 | 97 | 98 | 5. Шаблоны 99 | ---------- 100 | 5.1 Шаблоны не должны содержать никакой бизнес логики. 101 | Только логика (if) на уровне отображения. Но и ее следует сремиться минимизировать, 102 | чтобы не загромождать шаблоны. 103 | 104 | 5.2 Использовать партиалы, чтобы: 105 | - не копипастить и повторно использовать фрагменты html-кода 106 | - сделать шаблон чище, короче и понятнее 107 | 108 | 5.3 Использовать хелперы. 109 | Можно сделать себе подсказку: grep 'function' ./lib/vendor/symfony/lib/helper/* 110 | 111 | 5.4 Пишем свои хелперы, чтобы: 112 | - не копипастить 113 | - вынести часть логики отображения из шаблона 114 | - сделать шаблон чище, короче и понятнее 115 | 116 | 5.5 Ссылки и урлы выводим ТОЛЬКО через хелперы и ТОЛЬКО с явным указанием правила маршрутизации: 117 | OK: 118 | url_for('article_edit', $article); 119 | url_for('article_edit', array('id' => $article->getId()); 120 | NO: 121 | url_for('article/edit', $article); 122 | url_for('@article_edit?id='.$article->getId()); 123 | 124 | Бывают случаи, когда стоит использовать именно @article_edit?id=... 125 | Но эти случаи довольно редки и следует стремиться не использовать такую форму записи. 126 | 127 | Routing.yml - единственное место, где фигурируют реальные URL. 128 | В тестах мы используем $this->generateUrl(), см. sfPHPUnitFunctionalTestCase 129 | 130 | 5.6 Используем только альтернативный синтаксис для PHP: 131 | 132 | Никаких фигурных скобок (с учетом оправданных исключений). 133 | 134 | 5.7 В заголовке шаблона указываем phpdoc с описанием и списком ожидаемых переменных: 135 | 142 | 143 | 5.8 Все стили только в css. 144 | 145 | 146 | 6. Модель/Таблицы 147 | ----------------- 148 | 6.1 Желательно, чтобы в таблицах методы возвращали Doctrine_Query, 149 | чтобы контроллер или другой клиент мог самостоятельно выбрать способ гидрации 150 | или уточнить запрос. 151 | 152 | А еще лучше читаем и делаем: 153 | http://prendreuncafe.com/blog/post/Optimize-your-Doctrine-Workflow-with-Specialized-Queries 154 | 155 | 156 | 7. БД/schema.yml 157 | ---------------- 158 | 7.1 Таблицам даем название во множественном числе: 159 | Например: 160 | Tag: 161 | tableName: tags 162 | 163 | Article: 164 | tableName: articles 165 | 166 | ArticleTag: 167 | tableName: article_tags 168 | 169 | 7.2 Именования колонок: 170 | - первичный ключ: "id" 171 | - связь с другой таблицей по первичному ключу: "user_id", "article_id", "tag_id" 172 | - timestamp: "created_at", "updated_at", "deleted_at" 173 | 174 | 7.3 Для первичных ключей используем по смыслу: 175 | type: integer(4), unsigned: false 176 | type: integer(3) 177 | type: integer(2) # +-32767 178 | type: integer(1) # +-127 179 | До бигинта integer(8) редко кто доживает, а кто доживает, тот понимает, что это уже float. 180 | 181 | 7.4 Первичные ключи не объявляем в схеме там, где это возможно. 182 | Доктрина самостоятельно добавит "id" и укажет все необходимые свойства. 183 | Правда укажет тип integer(8), но если мы используем миграции, это не принципиально. 184 | В миграции, мы можем указать свой тип integer(4). 185 | 186 | 187 | 8. Миграции 188 | ----------- 189 | Подробно см. http://habrahabr.ru/blogs/symfony/97940/ 190 | 191 | 8.1 Миграции должны быть атомарными. Одна правка — одна миграция. 192 | ОБЯЗАТЕЛЬНО выносить все правки FK в отдельную миграцию. 193 | 194 | 8.2 Названия 195 | В названии файла и класса миграции указываем номер версии, модель, действие и описание: 196 | 197 | 001_Article_CreateTable.php 198 | 002_Article_AddColumn_AuthorId.php 199 | 003_Article_AddFk_Authors.php 200 | 004_Article_UpdateColumn_Title.php 201 | 005_Article_DropTable.php 202 | 203 | класс: 204 | class Migration_Article_CreateTable 205 | 206 | 8.3 Если есть возможность, используем короткую запись миграций вместе с migrate(). 207 | См. http://www.doctrine-project.org/projects/orm/1.2/docs/manual/migrations/en#writing-migration-classes:up/down-automation 208 | 209 | 8.4 ВСЕГДА делаем возможность откатить миграцию. 210 | 211 | 8.5 Миграции данных пишем ТОЛЬКО в raw sql и не используем модели. 212 | Пишем в pre/post хуках. 213 | 214 | 215 | 216 | TODO 217 | -------------------------------------------------------------------------------- 218 | - расширенный naming convention для классов 219 | - Указывать AppNamе: app/lib/myAdminUser.php 220 | - BaseClass, ArticleQuery (myAdminArticleQuery) 221 | - В первую очередь класть классы в app/lib, а потом выносить в глобальный lib при первой необходимости. 222 | - schema.yml: Всегда указывать relations: autoComplete: false, и включать при первой необходимости. 223 | - i18N 224 | - генерация админки 225 | --------------------------------------------------------------------------------