8 ms·
PHP Commandments
- Piskvorrr 14y agoAs for #6, I'd go as far as "NEVER use include, period." I've seen about 1 actual use case out of the bazillions out there; almost certainly, require() is the droid you're looking for. I'd also add a #10: Use E_ALL | E_STRICT , and don't ignore it. PHP is trying to tell you of many problems, shutting it up is not the right answer.
- SkippyZA 14y agoCouldn't agree more with E_ALL|E_STRICT. The current legacy system I am maintaining took me 2 weeks to clear up 90% of the NOTICE errors for using undefined variables etc. Dirty code is dirty, and it is because of this that PHP has received so much negative publicity.
- jacquesm 14y agoThe completely brain dead naming conventions for function names (or rather, the lack thereof) is another. PHP has grown organically, just like the web, to fill a very irregular shaped niche and it shows that history in all the gory little details. That said it made me more money than any other programming language combined (including C, but it's a very close second). Probably a lot of people have similar feelings towards Ruby, getting stuff done is what pays the bills.
- lmm 14y agoI haven't seen anywhere near the same level of hate for Ruby - and I can't help thinking it's because PHP is objectively worse. A lot of the problems listed in the article wouldn't arise in a language with a better module system (such as Ruby), for example.
- Luyt 14y agoQuick! Was it ($haystack, $needle) or ($needle, $haystack) ?
- jacquesm 14y agoOr better still... one where it doesn't matter: http://www.php.net/manual/en/function.implode.php http://www.php.net/manual/en/function.implode.php
- kijin 14y agoEven better, set error reporting to -1. This will catch every error, even if PHP devs decide to add a new type of error that isn't included in E_ALL | E_STRICT. (They already made E_STRICT not part of E_ALL, so there's no guarantee they won't do it again.) The reason this works is because -1 is 0xFFFFFFFF.
- hjay 14y agoIf you want to see why you should always use prepared statements in your code, take a look at this [1]. Old and outdated, but still very much applicable. [1]: http://technewsgalore.com/site/04/15/sql-injection-tutorial-by-for3v3rforgott3n http://technewsgalore.com/site/04/15/sql-injection-tutorial-...
- martin_ 14y agoFew comments.. #3 assumes that the variable came from user input, it's not necessarily bad. In some cases (i.e. dynamically switching from ORDER BY ASC/DESC) it's quite acceptable. But PDO + prepared statements for sure. #4 no need to use a library, htmlspecialchars/htmlentities are quite enough. #5 I think many frameworks/libraries can go here - why pick on one? #7 Mailgun, sengrid etc are becoming increasingly popular - worth mentioning. #9 isn't PHP related I agree with Piskvorrr - I favor require (though it isn't a function, no need for parenthesis.)
- astrodust 14y ago#3 should be #1, and further, it should read "If you insist on writing your own database layer, stop. You'll do it wrong in the worst possible way." PHP has institutionalized SQL value injection. mysql_query cannot be removed soon enough.
- martin_ 14y ago#3 should be #3 :) > mysql_query cannot be removed soon enough. I agree. Bring on 5.5
- Piskvorrr 13y agoI don't favor require, I require it (sorry for the pun). The main issue is that include() will just emit a warning and continue if the file doesn't exist, often leading to a confusing fatal error in a completely different part of the code; in other words, On Error Continue Next, PHP version. Even worse, people who use include are even more likely to use @include(). Oh, and require_once(), while we're on the subject: "if you're purposefully trying to require() a file twice, you're doing something Very Wrong."
- alekseyk 14y agoMost of the items on that list are not specific to PHP. Some of the stuff pointed out is up for discussion (I hate when people use the word 'NEVER' when they are writing about their point of view, especially when programming is a topic).
- daniloassis 14y agoI would add the following: General tips: * Understand how HTTP works (sounds trivial for a PHP developer, but at least here in Brazil, a huge portion doesn't do) * ALWAYS keep php.ini with production settings and replicate the same into your development environment (Vagrant is a great option here) * ALWAYS keep Apache or Nginx configs in sync among every environment * NEVER trust $_SERVER['REMOTE_ADDR'] to get client ips when you are behind a Load Balancer (most modern frameworks already treat this, but make sure you are parsing it correctly) * ALWAYS use `realpath` when you are symlinking folders * Be REALLY careful when using `setlocale` for something, specially with numbers * 2 basic things about Cookies: use `HttpOnly` flag whenever possible AND `Secure` flag when behind SSL * Make sure the Database library uses PDO in its core * Every service runs in UTC timezone (PHP, DB, OS etc). Offset calculations just for presentation or input (when explicitly necessary) * Don't use $_POST and $_GET globals directly * Support other methods (DELETE, PATCH, etc) by parsing the Request body properly Personal tips: * Use Composer * Use Twig * Use a nice Request/Response handler (Symfony2's HttpFoundation, for instance) I am sure I forgot many things here, one day I compile a list with everything I've been through. Hope it helps! :)
- ihsw 14y agoAnother nice Request/Response handler is Guzzle[1], which is what Amazon's AWS-API library uses. Guzzle's easy support of parallel HTTP requests is really nice. [1] http://guzzlephp.org/ http://guzzlephp.org/
- EvilTerran 14y agoDon't use $_POST and $_GET globals directly May I ask why not?
- krapp 14y agoIf they aren't sanitized or validated they can generate exceptions or contain malicious data which leads to XSS or SQL injection after they've been reflected back to the user or added to a database. Since the values in these arrays come from the user, they should always be considered actively hostile and treated as such.
- citricsquid 14y ago8. NEVER create a file of useful functions, even if it's called helpers.php This smacks of such a broken thinking process, it makes my teeth itch. If you have commonly-used functions, they should be integrated with the commonly-used parts of your code. Example function used for debugging: function preint_r($arr) { echo '<pre>'; print_r($arr); echo '</pre>'; } Where would something like this fit, if not a general helpers.php type file?
- bru 14y ago>Where would something like this fit, if not a general helpers.php type file? In debugging.php alongside with other debugging helpers?
- grobolom 14y agoMaybe if it's used solely for debugging, but there are cases where simple functions aren't easy to place. Consider implementing the array_column function for pre-5.4 PHP. Or things like method pull, index grouping, or array_select_keys functions. What helper library should a function like the following exist in? function array_select_keys(array $dict, array $keys) { $result = array(); foreach ($keys as $key) { if (array_key_exists($key, $dict)) { $result[$key] = $dict[$key]; } } return $result; }
- rmrfrmrf 14y agoUhh, really? array_intersect_key http://php.net/manual/en/function.array-intersect-key.php http://php.net/manual/en/function.array-intersect-key.php
- grobolom 14y agoarray_intersect_key does not do the same as array_select_keys. You can emulate it using array_intersect_key, but either in a more confusing or slow way. $array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]; array_select_keys($array, ['a', 'b']); array_intersect_key($array, ['a' => '', 'b' => '']); // OR array_intersect_key($array, array_flip(['a', 'b'])); // OR Neither are elegant. In either case, that wasn't the point. This is a basic kind of functionality that doesn't belong to any particular class in most code bases. So in this case, having a class of 'helper' functions like these isn't bad.
- adamors 14y agoAre people still using PHP without frameworks these days?
- Demiurge 14y agoAre people still using PHP these days? Couldn't help myself :(
- obviouslygreen 14y agoThe most painful thing about the years I spent working with PHP was having not even understood that web development frameworks existed. The little slice of the development world I existed in had absolutely no exposure to the concept... after switching to Python and only then discovering the concept, most of those PHP memories, in addition to being painful, became simultaneously embarrassing.
- conradfr 14y agoLet me introduce you to my colleagues. (who were a bit upset when they looked for jobs elsewhere)
- heidar 14y agoThe "cool kids" in PHP are using Laravel 4. It's a well made framework. I'm doing a REST API in it at work and the lack of mind share and docs is probably the worst part about it (it's still in beta to be fair). Most of the time I ended up reading the framework code. PHP leaves a lot to be desired though. It boggles my mind how developers who love what they do have the patience to stick with it. Example: Feature request for the unless control structure: https://bugs.php.net/bug.php?id=40296 https://bugs.php.net/bug.php?id=40296
- ihsw 14y agoI'm curious, why did you choose Laravel over Symfony?
- heidar 14y agoWe used Symfony 2 on projects previously. I find that it makes simple things hard to do and it is too verbose. Laravel 4 uses many of the Symfony 2 components but makes nice facades that you can call as static methods so you never have to worry about namespace importing and it makes things a lot less verbose and easy to use.
- jcampbell1 14y agoIs sending email really that slow? In my experience, it just writes something to a local mail queue if your front ends can send email.
- ineedtosleep 14y agoYes it's slow in that it's a blocking call. Since it takes more than a fraction of a second put a message in the mail queue, it'll _feel_ slow.
- jcampbell1 14y agoI am trying to verify your claim: php -r '$s = microtime(1);mail("jcampbell1@gmail.com","test","text");printf("%d\n ms",(microtime(1)-$s)*1000);' > 20 ms 20 ms doesn't _feel_ slow. You spend far more time fetching the data and rendering the email.
- ineedtosleep 14y agoJust realized I edited out (before I posted) my qualifcation for my statement, but it should've been prefaced as "from what I've noticed with no hard numbers." The reason I assume that it has the feeling of being slow, from the applications I've had to clean up, is because many times there's processing happening right before the mail() function. So while, yes, its relatively fast the the total time is what feels slow. And for comparison I've ran your commandline test as well with two of my cheap-o VPS instances, one of which is a Linode instance: Linode: 50ms, 13ms, 14ms Crappier VPS: 677ms, 149ms, 188ms
- UnoriginalGuy 14y agoIt can be that slow, yes. There is no assurances that will be fast, you're just hoping it will be. Now you could argue "that's true of anything!" but in general you are forced to depend on local IO/CPU/RAM otherwise your site is struggling in general, by adding DNS/SMTP/etc you're just adding more "stuff" that your site relies upon. Plus SMTP servers are "allowed" to go offline for short periods. The client should try to resend the email 2-4 additional times before giving up. Clearly a PHP script cannot do that.
- mikedwebdev 14y agoI have to disagree with your "Never use Ubuntu" way of doing things found here: http://biasedphp.com/windows-linux-distribution http://biasedphp.com/windows-linux-distribution Ubuntu's focus on the newest and latest is primarily on the desktop not the server. Better yet recommend user stick to LTS releases with 5 years of support.
- aarondf 14y agoCan someone help me understand why a "helpers" or "utilities" file of functions is so bad? Asking humbly because I do that and don't yet understand why it's bad / the alternative.
- martin_ 14y agoIt isn't - they should be abstracted to what they help with though. For example I have a \Helpers namespace and my autoloader brings them in as required: http://pastie.org/7743301 http://pastie.org/7743301
- deleted 14y ago[deleted]
- daniloassis 14y agoI don't quite agree with him on that also. PHP is multi-paradigm, if you keep helpers functions in a way it's well structured and feels right in your project, why do not use them? This is a personal preference, not a fact.
- the1 14y agothere's no generic "helpers". probably he meant to be more specific like htmlparsinghelper.
- rmrfrmrf 14y agoHelper files are a pain in the ass because they're usually all jumbled up and hard to maintain. In my experience with them, they come a zillion functions that are all unrelated, from input sanitization to XML processing to database initialization. Then, when you need to figure out what the hell is going on in your code, you have to wade through a forest of garbage just to figure out what the function is doing. God forbid you accidentally make a typo in ANOTHER function while editing the one you wanted -- now you've just introduced another bug without even realizing it. Furthermore, in PHP, we devs are almost always using the same boilerplate over and over again (getting user input, etc.), so why would we use a "helpers.php" file when we instead could break out our code into more semantic, reusable chunks? Instead, you should be creating classes (or at the very least, creating files that all have related functions, not just throwing all of your "helpers" into one file, so instead of helpers.php, you have inputSanitizer.php, htmlParser.php, et cetera). For example, I see a lot of this kind of thing in "helper.php" files: function sanitizeInput($input) { $input = htmlentities($input); ... return $input } What I personally love to do because I'm OO obsessed is use a home-grown InputSanitizer class, so now when I have a new project, I don't have to copy over my "helpers.php" file and then strip out everything unrelated to my project; I just copy over InputSanitizer.php to the new project and do something like this: $username = InputSanitizer::getPostData('username'); MUCH cleaner and easier to maintain. Even better: if you're using classes and auto-loading, you'll never have to worry about includes again, you simply just call the class methods or instantiate. There's a clean, wonderful side to PHP that I think a lot of people aren't taking advantage of.
- rmrfrmrf 14y agoThese are the "PHP Commandments"? How about we set the bar a little higher? Anyone who has had longer than 1 day's worth of training with PHP should know these things.
- Piskvorrr 13y agoShould is the operative word. I keep being amazed at what people ought to know, yet don't.
- Jleagle 14y agoWow, this guy really hates CakePHP. If you know what you're doing and don't just presume Cake has done it for you, none of those problems should exist.
- TheCapn 14y agoI find that to be very true. Seems a lot of amateur programmers pick up CakePHP for one reason or another without actually knowing PHP and try to drive every screw with the one hammer they have. When everything's suddenly broken they blame the hammer. EDIT: Although I suppose the author's point of view is from the outside-in where he's tasked with cleaning up the mess that amateurs leave behind and has a bias against it.
- Schlaefer 14y agoIf you know what you're doing you will not pass around huge arrays (in PHP) by value. Or pass them around (in CakePHP) at all, it's maybe a MVC warning flag that you do something in a place you shouldn't. Related note: CakePHP 3.0 (current is 2.x) will use objects [1]. [1] https://groups.google.com/d/msg/cake-php/-TLn6RpHt4U/EAP0lt2yjsAJ https://groups.google.com/d/msg/cake-php/-TLn6RpHt4U/EAP0lt2...
- smacktoward 14y agoI have no brief for or against Cake (never used it myself), but input filtering seems like exactly the sort of tedious-but-necessary infrastructure code that a good framework is supposed to let you avoid having to write from scratch for each new project. If Cake doesn't do that, I don't think it's unreasonable to count that as a strike against it.
- pieterp 14y ago#6 re: autoloading. PSR-0?
- deleted 14y ago[deleted]
- chrisguitarguy 14y agoI would recommend Doctrine DBAL[0] over Meekro. 0. http://www.doctrine-project.org/projects/dbal.html http://www.doctrine-project.org/projects/dbal.html
- UnoriginalGuy 14y ago> NEVER hash passwords with MD5/SHA-1/Hash-of-the-day > PHPass will make life easy for yourself and keep your users' passwords secure. MD5/3DES/SHA-1 are relatively broken. But saying "use this magical library" is really far from a solution. Who's to say that that library won't be broken tomorrow and then someone else won't write an article next week saying "don't use PHPass!" Programmers just need to stay up-to-date with the latest trends and adjust their approaches accordingly. > MD5/SHA-1/Hash-of-the-day is not, was not, and never will be acceptable. MD5 was very much acceptable for the longest time. Back when everyone was using 3DES, MD5 was seen as the Bcrypt of the time. So saying that it "never was acceptable" is simply nonsense. It was even what was implemented by the standard libraries and APIs of the time.
- chacham15 14y agoNo. >MD5 was very much acceptable for the longest time. MD5 was never a good password hash. Neither is SHA1,256,etc. The reason is that they are crypto hashes optimized for speed. This is bad for passwords. What you should be using is the opposite: an expensive hash to compute. This is bcrypt which has been in use since 1999 (and what the PHPass is based on). This is a clear example of "Dont do your own crypto" because you dont know all the details. >It was even what was implemented by the standard libraries and APIs of the time. Yes, and this was a mistake. But to be fair DES used to take a full second to compute and bcrypt wasnt invented until 1999. This is why current password hashes use variable rounds so that we can increase the cost as computers get faster. When the algorithm is DESIGNED to be computed quickly it is fundamentally broken for passwords. This is the reason that LinkedIn's passwords were vulnerable[1]. [1]http://www.itworld.com/security/280813/expert-calls-linkedins-new-salted-hashes-useless http://www.itworld.com/security/280813/expert-calls-linkedin...
- UnoriginalGuy 14y ago> MD5 was never a good password hash. Neither is SHA1,256,etc. The reason is that they are crypto hashes optimized for speed. That's strange to hear you say that, because I remember people having huge arguments in the 1990s about how they couldn't use MD5 because it was /so/ slow and how 3DES was the only way to go! I swear people love to re-write history. > This is a clear example of "Dont do your own crypto" because you dont know all the details. That doesn't even make any sense. MD5 is a standard cryptographic function. If someone had used it they wouldn't be making their own crypto. Hell, many of the standard libraries implemented MD5 when you asked them to protect a password by default. That's so far from rolling your own it isn't even logical to try and make the argument you're making. Your entire post reads like someone who knows nothing about the history and is just spouting "OMG USE bcrypt IT IS THE BESTEST AND WILL BE SECURE FOREVER!" bcrypt too will fall from grace and then you'll have someone making a post like yours saying "how could anyone use bcrypt, it is SOOO fast!"
- nikic 14y ago> PHP version 5.5 (not yet released) will support Bcrypt natively via its password_hash() function. Use it. This makes it sound like PHP didn't support bcrypt before 5.5. It did. PHP always has bcrypt support in 5.3 and 5.4. In older versions it also has bcrypt support if the operating system supports it. PHP 5.5 only added a wrapper around the low-level crypt() API, which makes password hashes more convenient to use and less prone to error.
- jcampbell1 14y agoThe php 5.5 functions are really nice. Fortunately they can be shimmed into versions 5.3.7+. See: https://github.com/ircmaxell/password_compat https://github.com/ircmaxell/password_compat
- jtreminio 14y agoThis whole thing could be replaced with the far better http://www.phptherightway.com/ http://www.phptherightway.com/
- pilif 14y ago> 7. NEVER send emails directly from web page code Sending emails is slow. Incredibly slow. Don't tie up a precious web front-end process with doing so. Use a message queue instead. Well. MTAs are message queues. Why use a third party software speaking a third-party protocol, adding more complexity only to eventually be talking SMTP anyways. As such, my message queue is a locally installed MTA listening on port 587, talking SMTP. This is as fast or faster than any message queuing system you can come up with, but as it's managed by the OS, it's bound to work much better than third-party solutions. I also get a lot for free in exchange. Stuff like automatic resending, queueing, queue management and so on. As such, I would not strictly agree with point 7 in the article. Sure - don't send mail by talking to a remote MTA, but if it's running inside of your local network, using any other queuing system provides nothing but overhead. Furthermore: >How do you set up Nginx so that it won't die or kill your server when you receive a big burst of traffic? You install it. No. You are shifting the burden of correct app server configuration from apache to php-fpm or whatever other process manager you're using. In the end it doesn't matter much whether you're down completely (misconfigured apache) or still somewhat capable of serving static files while unable to serve any dynamic pages (misconfigured php-fpm).
- martin_ 14y agoThe comments pretty much sum up how useful this blog post is... The upvotes merely show how educated a lot of the PHP community isn't
- ihsw 14y ago"The PHP Community" comprises massive swaths of developers, from people who have a hard time caring about things like "namespaces" and "encapsulation" to people who think and breath those concepts on a daily basis. It would be disingenuous to make such broad-sweeping and baseless statements about the entirety of a group of people. Please don't get confused and paint everybody so broadly, it damages us all. There are many people working hard to improve the language and create a more modern environment around PHP.
- krapp 14y agoRight, which is why the Ruby and Python threads just tend to get ignored -- because everyone in those communities already knows everything about everything... (especially PHP)
- alan_cx 14y agoOr just up front and honest. Which leads to open discussion. Which improves things. Maybe...
- krapp 14y ago#1 oh, god yes. Variable variables and extract. I hate extract. Although i've only actually seen it in production in wordpress... Though i'd edit this to always do the simplest thing that will work properly. After all, the simplest way to do a SQL query in php that works is to just dump POST vars into a mysql function... #2 I've actually gotten into an argument with someone who insists md5 is perfectly fine for password hashing if you salt it. Better, in fact, because it's faster. So yeah. #3 Unfortunately we're also stuck with a ton of legacy code that does this, and would be all but impossible to refactor, and i'm still pointing out to people who post code like this to at the very least sanitize their stuff. Seriously, if it's even possible, someone come up with an easy way to convert old-style linear SQL statements to parameterized queries or something in PHP. #4 HTMLPurifier is good, but can be incredibly slow. htmlspecialchars is probably good where you don't need to sanitize data but still provide markup. I personally use htmlpurifier after a markup generator like Markdown, so I can enforce a whitelist against it. Still, YMMV but do SOMETHING. #5 Might as well say don't use Wordpress either. I have yet to find a framework that makes me as angry as it does. Though granted, I haven't actually used cakePHP yet and I hear Zend Framework is a bit gnarly. Though "Use a framework when you can" is probably a good rule. Though eventually that ends up being "don't reinvent the wheel" #6 WHO EVEN DOES THIS?! #7 I don't know. Depending on how many you're sending, it's probably fine for low volume. It's probably right though. #8 Don't really agree with this at all. In a global file, the body of helpful_function() is in one place, so if I want to change it or upgrade it, it's right there. If I integrate it into the rest of my code, I have to go look for it or else deal with multiple definitions in different files. Though I will agree that if you're only using a helper function once in your code, then clearly it needs to be integrated somewhere else. My definition for a helper function is that it gets used multiple times in no particular place. #9 Most php developers work with whatever server their host is using, so this is of limited utility.
- mattacular 14y agoI agree with most of these except the one about helper functions but I think it was just written poorly (like the whole article). Definitely sort your functions into the files where they are most applicable, but sometimes (a lot of the time) you will have toolkit/helper functions which are globally applicable to the entire app. Where should those go? A helper or toolkit PHP file IMHO.
- acabal 14y agoFor anyone interested in taking the next step for some of these suggestions (i.e., "OK, never put variables in SQL, what do I do instead then?"): I maintain https://phpbestpractices.org https://phpbestpractices.org, which is an attempt to document the "best" solutions to common low-level tasks, like DB access, which have lots of possible dangerous approaches. (Note I only talk about the version of PHP that ships with Ubuntu 12.04 LTS, so brand-spanking-new stuff like password_hash() isn't in there.)
- shousper 14y agoThe more of these posts I read, the more I believe most PHP programmers (as a majority) really aren't "clean coders" or have any intention of writing organised, maintainable. More likely they are just coders who write what they have to, whatever works and takes the least amount of time to get the job done. A sweatshop language? Haha, no I take that back, it's not like that..
- krapp 14y agoYes, and Ruby on Rails users are just hipster kids who consider installing modules to be 'coding'. Herp, and if I might be so bold, derp as well.
- shousper 14y agoThe more of these posts I read, the more I believe most PHP programmers (as a majority) really aren't "clean coders" or have any intention of writing organised, maintainable. More likely they are just coders who write what they have to, whatever works and takes the least amount of time to get the job done. A sweatshop language? Haha, no I take that back, it's not like that..