1 | Strangecode coding standards |
---|
2 | 29 Aug 2005 20:12:49 |
---|
3 | |
---|
4 | |
---|
5 | ====================================================================== |
---|
6 | Preamble |
---|
7 | ====================================================================== |
---|
8 | |
---|
9 | Our standards follow closely the PEAR coding standards. |
---|
10 | |
---|
11 | Essential reading: |
---|
12 | http://pear.php.net/manual/en/standards.php |
---|
13 | |
---|
14 | |
---|
15 | ====================================================================== |
---|
16 | File naming conventions |
---|
17 | ====================================================================== |
---|
18 | |
---|
19 | script.php Public accessible scripts. |
---|
20 | |
---|
21 | Auth_SQL.inc.php One PHP Class to be included. The filename is the |
---|
22 | type of class, underscore, name. Or if in subdirs, |
---|
23 | this could be /Auth/SQL.inc.php while the class name |
---|
24 | remains "Auth_SQL" |
---|
25 | |
---|
26 | some_file.inc.html HTML file, which may or may not have some PHP, |
---|
27 | but will be included by some other PHP file. Never |
---|
28 | includes sensitive code as these files may be accessed |
---|
29 | directly in the web root. |
---|
30 | |
---|
31 | script.cli.php A command-line executable script, possibly executed |
---|
32 | with CRON. Outputs TEXT if any instead of HTML. |
---|
33 | |
---|
34 | schema.mysql Database schema file that goes with the application. |
---|
35 | |
---|
36 | main.screen.css CSS file with media: screen/print/all |
---|
37 | main.print.css |
---|
38 | |
---|
39 | |
---|
40 | ====================================================================== |
---|
41 | Indenting and wrap |
---|
42 | ====================================================================== |
---|
43 | |
---|
44 | Use an indent of 4 spaces, with no tabs. Code and especially comments should |
---|
45 | be wrapped <= 80 characters. Exceptions are made in the case where code |
---|
46 | readability is significantly improved with longer lines. |
---|
47 | |
---|
48 | |
---|
49 | ====================================================================== |
---|
50 | Control Structures |
---|
51 | ====================================================================== |
---|
52 | |
---|
53 | These include if, for, while, switch, etc. Here is an example if statement, |
---|
54 | since it is the most complicated of them: |
---|
55 | |
---|
56 | if ((condition1) || (condition2)) { |
---|
57 | action1; |
---|
58 | } else if ((condition3) && (condition4)) { |
---|
59 | action2; |
---|
60 | } else { |
---|
61 | defaultaction; |
---|
62 | } |
---|
63 | |
---|
64 | Control statements should have one space between the control keyword |
---|
65 | and opening parenthesis, to distinguish them from function calls. |
---|
66 | |
---|
67 | Even in the case of an if with no else clauses, and only a 1 line action, |
---|
68 | the curly braces should still be used: |
---|
69 | |
---|
70 | if (condition) { |
---|
71 | action; |
---|
72 | } |
---|
73 | |
---|
74 | This improves readability and allows easy extension of the clause. |
---|
75 | |
---|
76 | For switch statements: |
---|
77 | |
---|
78 | switch (condition) { |
---|
79 | case 1: |
---|
80 | action1; |
---|
81 | break; |
---|
82 | |
---|
83 | case 2: |
---|
84 | action2; |
---|
85 | break; |
---|
86 | |
---|
87 | default: |
---|
88 | defaultaction; |
---|
89 | break; |
---|
90 | |
---|
91 | } |
---|
92 | |
---|
93 | |
---|
94 | ====================================================================== |
---|
95 | Function Calls |
---|
96 | ====================================================================== |
---|
97 | |
---|
98 | Functions should be called with no spaces between the function name, |
---|
99 | the opening parenthesis, and the first parameter; spaces between commas |
---|
100 | and each parameter, and no space between the last parameter, the |
---|
101 | closing parenthesis, and the semicolon. Here's an example: |
---|
102 | |
---|
103 | $var = foo($bar, $baz, $quux); |
---|
104 | |
---|
105 | As displayed above, there should be one space on either side of an |
---|
106 | equals sign used to assign the return value of a function to a |
---|
107 | variable. In the case of a block of related assignments, more space |
---|
108 | may be inserted to promote readability: |
---|
109 | |
---|
110 | $short = foo($bar); |
---|
111 | $long_variable = foo($baz); |
---|
112 | |
---|
113 | |
---|
114 | ====================================================================== |
---|
115 | Function Definitions |
---|
116 | ====================================================================== |
---|
117 | |
---|
118 | Function declaractions follow the "one true brace" convention: |
---|
119 | |
---|
120 | function fooFunction($arg1, $arg2 = '') |
---|
121 | { |
---|
122 | if (condition) { |
---|
123 | statement; |
---|
124 | } |
---|
125 | return $val; |
---|
126 | } |
---|
127 | |
---|
128 | Arguments with default values go at the end of the argument list. Always |
---|
129 | attempt to return a meaningful value from a function if one is appropriate. |
---|
130 | |
---|
131 | Recommend using studlyCaps for function names, to distinguish from php |
---|
132 | internal functions which standard on under_score_space() style names. |
---|
133 | |
---|
134 | |
---|
135 | ====================================================================== |
---|
136 | Return values |
---|
137 | ====================================================================== |
---|
138 | |
---|
139 | When functions return boolean values, use 'return false;' or 'return true;' |
---|
140 | as opposed to 'return 0;' or 'return 1;' or 'return(-1);'. |
---|
141 | |
---|
142 | |
---|
143 | ====================================================================== |
---|
144 | String concatenation |
---|
145 | ====================================================================== |
---|
146 | |
---|
147 | Always include a space before and after the concatenation operator '.' which |
---|
148 | improves readability and improves search-and-replace of adjacent elements. |
---|
149 | |
---|
150 | $something = $blah . funky() . ".\".=" . $blab; |
---|
151 | |
---|
152 | is better than: |
---|
153 | |
---|
154 | $something = $blah.funky().".\".=".$blab; |
---|
155 | |
---|
156 | |
---|
157 | ====================================================================== |
---|
158 | Quote marks |
---|
159 | ====================================================================== |
---|
160 | |
---|
161 | Use the single quote marks ' to enclose simple strings whenever possible. |
---|
162 | Double quote marks " require extra parsing and thus slow things down, but |
---|
163 | are necessary if entities there must be swapped-out such as variables or |
---|
164 | control characters. |
---|
165 | |
---|
166 | $var['singlequote'] = 'singlequote'; |
---|
167 | $var["doublequote-$i"] = "$vars and \n funny \t %s things need doublequotes"; |
---|
168 | $var['doublequote-' . $i] = $var . 'you can do this' . "\t %s" . $var2 . |
---|
169 | 'but it isn\'t any better'; |
---|
170 | |
---|
171 | |
---|
172 | ====================================================================== |
---|
173 | Printing html |
---|
174 | ====================================================================== |
---|
175 | |
---|
176 | For large or complex blocks of HTML, using the following method is much faster |
---|
177 | and safer than echo because the php processor is bypassed and content goes |
---|
178 | directly to output: |
---|
179 | |
---|
180 | <?php |
---|
181 | if (something) { |
---|
182 | // Here comes the HTML... |
---|
183 | ?> |
---|
184 | <div class="sc-tiny"> |
---|
185 | <a href="<?php echo $app->ohref('/contact.php') ?>">Contact us</a> |
---|
186 | </div> |
---|
187 | <?php |
---|
188 | } else if (somethingelse) { |
---|
189 | ?><h1>Just a little html</h1><?php |
---|
190 | } |
---|
191 | ?> |
---|
192 | |
---|
193 | |
---|
194 | ====================================================================== |
---|
195 | Comments |
---|
196 | ====================================================================== |
---|
197 | |
---|
198 | Function comments should follow the Javadoc standard, with detailed |
---|
199 | function comments and one-line pointers along the way: |
---|
200 | http://java.sun.com/products/jdk/javadoc/writingdoccomments/index.html |
---|
201 | |
---|
202 | Here is an example of the codebase method Email::validEmail(): |
---|
203 | |
---|
204 | <?php |
---|
205 | /** |
---|
206 | * Validates an email address based on the recommendations in RFC 3696. |
---|
207 | * Is more loose than restrictive, to allow the many valid variants of |
---|
208 | * email addresses while catching the most common mistakes. Checks an array too. |
---|
209 | * http://www.faqs.org/rfcs/rfc822.html |
---|
210 | * http://www.faqs.org/rfcs/rfc2822.html |
---|
211 | * http://www.faqs.org/rfcs/rfc3696.html |
---|
212 | * http://www.faqs.org/rfcs/rfc1035.html |
---|
213 | * |
---|
214 | * @access public |
---|
215 | * @param mixed $email Address to check, string or array. |
---|
216 | * @return bool Validity of address. |
---|
217 | * @author Quinn Comendant <quinn@strangecode.com> |
---|
218 | * @since 30 Nov 2005 22:00:50 |
---|
219 | */ |
---|
220 | function validEmail($email) |
---|
221 | { |
---|
222 | $app =& App::getInstance(); |
---|
223 | |
---|
224 | // If an array, check values recursively. |
---|
225 | if (is_array($email)) { |
---|
226 | foreach ($email as $e) { |
---|
227 | if (!$this->validEmail($e)) { |
---|
228 | return false; |
---|
229 | } |
---|
230 | } |
---|
231 | return true; |
---|
232 | } else { |
---|
233 | // To be valid email address must match regex and fit within the lenth constraints. |
---|
234 | if (preg_match($this->getParam('regex'), $email, $e_parts) && strlen($e_parts[2]) < 64 && strlen($e_parts[3]) < 255) { |
---|
235 | return true; |
---|
236 | } else { |
---|
237 | $app->logMsg(sprintf('Invalid email: %s', $email), LOG_INFO, __FILE__, __LINE__); |
---|
238 | return false; |
---|
239 | } |
---|
240 | } |
---|
241 | } |
---|
242 | ?> |
---|
243 | |
---|
244 | Single line comments should be of the double-slash variety, and be on the line above the |
---|
245 | code being commented upon: |
---|
246 | |
---|
247 | <?php |
---|
248 | // If the last word in $var is peanuts, set $need_peanuts to TRUE. |
---|
249 | $need_peanuts = preg_match('/peanuts$/i', $var); |
---|
250 | ?> |
---|
251 | |
---|
252 | |
---|
253 | ====================================================================== |
---|
254 | Including Code |
---|
255 | ====================================================================== |
---|
256 | |
---|
257 | If you are including a class, function library, or anything else which would |
---|
258 | cause a parse error if included twice, always use include_once. This will |
---|
259 | ensure that no matter how many factory methods we use or how much dynamic |
---|
260 | inclusion we do, the library will only be included once. |
---|
261 | |
---|
262 | If you are including a static filename, such as a conf file or a template |
---|
263 | that is _always_ used, use require. |
---|
264 | |
---|
265 | If you are dynamically including a filename, or want the code to only be |
---|
266 | used conditionally (an optional template), use include. |
---|
267 | |
---|
268 | |
---|
269 | ====================================================================== |
---|
270 | PHP Code Tags |
---|
271 | ====================================================================== |
---|
272 | |
---|
273 | ALWAYS use <?php ?> to delimit PHP code, not the <?php ?> shorthand. Even |
---|
274 | use <?php echo $name ?> instead of <?php echo $name; ?>. |
---|
275 | |
---|
276 | |
---|
277 | ====================================================================== |
---|
278 | php.ini settings |
---|
279 | ====================================================================== |
---|
280 | |
---|
281 | All code should work with register_globals = Off. This means using |
---|
282 | $_GET, $_POST, $_COOKIE, $_SESSION, |
---|
283 | $_SERVER, and $_ENV to access all get, post, cookie, |
---|
284 | session, server, and environment data, respectively. |
---|
285 | |
---|
286 | All code should work with error_reporting = E_ALL. Failure to do so would |
---|
287 | result in ugly output, error logs getting filled with lots of warning messages, |
---|
288 | or even downright broken scripts. |
---|
289 | |
---|
290 | All code should work regardless of the setting of magic_quotes_gpc. |
---|
291 | Form data should be passed through stripslashes if necessary. |
---|
292 | |
---|
293 | No code should assume that '.' is in the include path. Always |
---|
294 | specify './' in front of a filename when you are including a file in |
---|
295 | the same directory. |
---|
296 | |
---|
297 | |
---|
298 | ====================================================================== |
---|
299 | XHTML 1.0 Compliance |
---|
300 | ====================================================================== |
---|
301 | |
---|
302 | All HTML should be valid XHTML 1.0 verfied with the |
---|
303 | W3C Markup Validation Service: http://validator.w3.org/ |
---|
304 | |
---|
305 | All tag names and parameters must be lower case including javascript |
---|
306 | event handlers: |
---|
307 | |
---|
308 | <div class="mofogo">...</div> |
---|
309 | <a href="http://www.example.com/" onmouseover="status=''" onmouseout="status=''">...</a> |
---|
310 | |
---|
311 | All tag parameters must be of a valid parameter="value" form (numeric |
---|
312 | values must also be surrounded by quotes). For parameters that had no |
---|
313 | value in HTML, the parameter name is the value. For example: |
---|
314 | |
---|
315 | <input type="checkbox" checked="checked" /> |
---|
316 | <select name="example"> |
---|
317 | <option selected="selected" value="1">Example</option> |
---|
318 | </select> |
---|
319 | <td nowrap="nowrap">Example</td> |
---|
320 | |
---|
321 | All tags must be properly closed. Tags without a closing part must follow the |
---|
322 | XHTML convention and end with a space and a slash: |
---|
323 | |
---|
324 | <br /> |
---|
325 | <hr /> |
---|
326 | <img src="example.gif" alt="Example" /> |
---|
327 | <input type="submit" value="Example" /> |
---|
328 | |
---|
329 | All form definitions must be on their own line and either fully defined within |
---|
330 | a <td></td> pair or be outside table tags. Forms must also always have an action |
---|
331 | parameter: |
---|
332 | |
---|
333 | <form method="post" action="http://example.com/example.cgi"> |
---|
334 | <table> |
---|
335 | <tr><td>example</td></tr> |
---|
336 | </table> |
---|
337 | </from> |
---|
338 | |
---|
339 | <table> |
---|
340 | <tr><td> |
---|
341 | <form action="javascript:void(0)" onsubmit="return false;"> |
---|
342 | </form> |
---|
343 | </td></tr> |
---|
344 | </table> |
---|
345 | |
---|
346 | All JavaScript tags must have a valid language and type parameters: |
---|
347 | |
---|
348 | <script language="JavaScript" type="text/javascript"> |
---|
349 | <!-- |
---|
350 | ... |
---|
351 | // --> |
---|
352 | </script> |
---|
353 | |
---|
354 | Nothing may appear after </html>, therefore include any common footers after |
---|
355 | all other output. |
---|
356 | |
---|
357 | All images must have an alt parameter: |
---|
358 | |
---|
359 | <img src="example.gif" alt="<?php echo _("Example"); ?>" /> |
---|
360 | |
---|
361 | Input field of type "image" does not allow the border parameter, and may render |
---|
362 | with a border on some browsers. Use the following instead: |
---|
363 | |
---|
364 | <a href="" onclick="document.formname.submit(); return false;"><img src="example.gif" alt="<?php echo _("Example"); ?>" /></a> |
---|
365 | |
---|
366 | |
---|
367 | ====================================================================== |
---|
368 | Database Naming Conventions |
---|
369 | ====================================================================== |
---|
370 | |
---|
371 | All database tables need to make sure that their table and field names work in all |
---|
372 | databases. Many databases reserve words like 'uid', 'user', etc. for |
---|
373 | internal use, and forbid words that are SQL keywords (select, where, |
---|
374 | etc.). Adding '_tbl' to the end of the table name is a good idea for this reason |
---|
375 | and also improves searching for the table names in the code. |
---|
376 | |
---|
377 | A good way to do this for field names is to make the field name |
---|
378 | table_name_field_name. |
---|
379 | |
---|
380 | When building queries referencing two-or-more tables always preface columns |
---|
381 | with the table containing the column (admin_tbl.username, location_tbl.location_address). |
---|
382 | This method is much preferred over using aliases of table names (a.username, l.location_address). |
---|
383 | |
---|
384 | Table names should be singular (user_tbl instead of users_tbl). |
---|