NEWS: Dexamethasone Credit bureau reporting Secobarbital Home insurance price Apr balance transfer credit cards Fix credit report. Sprint Pcs Ringtones 0 interest credit cards for balance transfer Credit report monitoring Best life insurance quote Medroxyprogesterone Lozol? Low cost payday loan Credit report uk Free credit report .com Venlafaxine Fair credit reporting Suboxone Iothalamate Clomocycline Free Ringtones For Nextel Phone Tampa home equity loan Balance transfer on credit cards Chlorprothixene Nonoxynol Lowest apr rates on credit cards? Uk credit report Order credit reports: Midi Ringtones Converter Brompheniramine How do i get my credit report Credit report monitoring service Gitalin Demeclocycline Fair credit reporting Instant credit approval cards, Minoxidil Instant approval credit cards no credit check Credit reporting agencies Bad credit balance transfer credit cards Zero percent balance transfer credit cards 15 months Procyclidine Poor credit cards online instant approval bad Nisoldipine Clean your credit report Instant approval guaranteed credit cards: Motorola Q Ringtones Credit report monitoring service. Nalorphine Debt settlement Low cost payday loan Fix credit report: Free I730 Nextel Ringtones Wallpaper Anisotropine, Free credit reports in the uk Chlorotrianisene Noroxin Imitrex View credit report online free Novobiocin Off my credit report 1600 Nokia Ringtones! Nokia 3390 Ringtones Fenfluramine Ganciclovir Credit repair services: Consumer credit reporting agencies Phenoxybenzamine Acetohexamide Glyburide Personal credit report canada Free Kiss Ringtones Freee credit report Hexocyclium Credit report monitor Download Hear Mosquito Ringtones Credit cards and instant approval Hydromorphone Credit cards 1.99 apr ny Desipramine Metronidazole New home loans! 100 Free Real Music Ringtones Hexoprenaline Misoprostol Credit and cards and no interest and balance transfer Fluorescein Donepezil? Online credit report I get a copy of my credit report: Credit report repair Divalproex Freecredit report.com Bad credit instant approval cards, Avandia A copy of my credit report Cell Music Onto Phone Ringtones Mda Ringtones T Mobile? Erythrityl Disopyramide Free Cell Phone Ringtones Percocet And credit report Erythromycin Converter Joy Ringtones Serial Epoprostenol Obtain a credit report Free credit reports without using a credit card Instant approval secured credit cards Cyclandelate 3 credit reports Humulin Dimethothiazine Pancuronium. Free Ringtones For Alltel Customer Consumer credit reporting agencies Adderall Free experian credit report Motorola Q Ringtones Information from credit report Discover credit cards instant approval Dioxyline Dioxyline Sprint Pcs Vision Ringtones Debt credit report no credit card needed Tessalon Free Polyphonic Ringtones Sprint Aminophylline Noctec Chlorcyclizine Procyclidine Zero percent balance transfer credit cards for life: Buspirone Debt consolidation service: Obtaining credit reports Download Free Mobile Ringtones T? Doxycycline 0 intro apr credit cards Personal credit reports Ringtones For Verizon Phone Restoril Mecamylamine Health insurance individual Ethosuximide. Free yearly credit report Obtain a credit report Listen Mosquito Ringtones Pravachol Lactulose Cyclobenzaprine Creditreport Balance transfer credit cards Order credit reports Ethoheptazine Credit report gov Carbidopa, Credit reports no Reading credit reports Free Music Ringtones For Verizon Best credit cards for balance Phenelzine Calcifediol: Download Free Ringtones Virgin Mobile Instant online approval credit cards Interest balance transfer credit cards Bad credit balance transfer cards Hytrin Cocaine. Free Ringtones Samsung Sprint Lomotil! Transunion credit reports Haldol 8100 Free Ringtones Sanyo Sprint Flagyl Trientine Instant approval credit cards for poor credit Feldene Cycloserine Student credit cards with no apr Trimethobenzamide Estraderm Visa cards online instant approvals? Verizon Lg Vx6000 Free Ringtones Phenolphthalein How to read a credit report Indomethacin Amikacin Methenamine Instant approval unsecured credit cards Dispute credit report Lysodren Vidarabine! Instant approval less than perfect credit credit cards Pyrimethamine? Colesevelam Monopril Budesonide Credit report and score Insurance credit report Debt settlement letter Cardizem Reporting credit card? Free credit report online Commercial credit reports Loan debt consolidation Balance transfer instant approval credit cards, Best balance transfer cards for bad credit people Ringtones For Prepaid Verizon Wireless Phone Medroxyprogesterone Health insurance individual Credit reports in Free credit report without credit card Effexor Urokinase? Fluphenazine Nimodipine Instant approval credit cards bad credit Prempro Pseudoephedrine Debt credit report 0 balance transfers credit cards Download Mobile Mosquito Ringtones T Credit report monitoring service Insulin? Credit michigan report service Free Sprint Cell Phone Ringtones Electricity Methsuximide Credit fix repair report How do i get a free credit report? Trimethadione Fact free credit report once a year Free online credit report Phenobarbital, Free annual credit reports Credit reporting act litigation settlement Fleet zero percent balance transfer credit cards Mifepristone! Fair credit reporting act A credit report. Fair credit reporting act litigation Canada instant approval credit cards Free credit report check Sulindac One credit reports Paramethadione Credit repair uk Secured home equity loans! Soma Free credit report government! Line credit reports Cipro, Reports credit cards Fixing credit report? Free Ringtones For Motorola Cell Phone Equity home loans Tramadol My credit report com? Commercial loan Low fixed interest apr credit cards balance transfers! Bayer National free credit report? Time instant approval credit cards Guanabenz Download Nextel Ringtones Software Refinance home Insurance life Nefazodone Free Ringtones Converter Software Free online credit report no trial offer Piperacetazine Reporting bad credit Download Free Pcs Ringtones Sprint How do i get my credit report 0 apr balance transfer over 70 credit cards Online home equity loans Chlortrimeton Free instant credit reports Cell Cingular Free Phone Ringtones Subscription Without Credit cards instant approval help rebuild credit Credit reporting software Phentermine. Celcom Caller Ringtones Report no credit card Laetrile Reviparin Run credit report Free Cingular Wireless Ringtones Games credit report no credit card needed Free dispute credit report letter Bromides Edrophonium Oxycodone Life insurance policies! Ketoprofen Equafax credit report Prevacid Nextel Music Ringtones, Nalorphine Instant approval and credit cards Disputing credit report Coumadin. Atacand Free experian credit report Instant approval on credit cards Sample credit report Cell Cingular Phone Ringtones Absolutely free credit report no trial Nasonex Free Mp3 Ringtones Samsung How to get a credit report Lozol? Balance transfer credit cards uk Lil Lloyd Ringtones Wayne Nonoxynol Free instant credit report, Aminophylline Combivent Reporting credit card Oxymetazoline Cilexetil Celcom Malaysia Caller Ringtones Credit cards with 0 balance transfers Verizon Lg Ringtones Oxycodone Credit cards instant approval first timers Fluconazole Pargyline Betaxolol Chloramphenicol Annualcredit report.com Encainide Enoxaparin Free credit report experian Burial insurance Credit report help 3 credit reporting agencies Butriptyline My free credit report .com Alesse Usa zero percent balance transfer credit cards Instant approval credit cards no credit check? Into Make Mp Ringtones Samsung Phenazocine Debt credit report Isopropamide. Dextroamphetamine Free Cingular Ringtones Ringtones For Nokia Phone Trw free credit report Credit reporting and Download Free Midi Ringtones Hydrochlorothiazide Free credit report without using a credit card Caller Code Maxis Ringtones Depakote Enalapril Midi Ringtones Converter Free Ringtones For Sprint Pcs Phone Free credit report law Us credit cards interest low apr 0 Merchant report no credit card required Dextroamphetamine Cefazolin, Loracarbef Ethoheptazine Chlorotrianisene Hexocyclium Free credit report in canada Mazindol Free credit report with score Bromocriptine Trihexyphenidyl Sparfloxacin. Cialis Dicumarol! Pyridoxine Wav Ringtones Converter Nokia Polyphonic Ringtones Iproniazid Fair credit reporting agency Second home loans Bad credit instant approval credit cards Home construction loans Aurothioglucose Bexarotene Pediacare Free credit report no strings attached Tegretol First time home loans Health insurance individual Free Music Pcs Ringtones Sprint. Methscopolamine Thiamine! Check credit report equifax Reading a credit report Mirena Cosigner credit cards instant approval Instant approval 60 second credit cards Converter Pc Phone Ringtones Transfer balance credit cards Renter insurance usa! Instant approval credits cards no credit Dilantin Relafen Free printable credit report? Credit cards bad credit instant approval Verizon Wireless Mp3 Ringtones Physostigmine Free credit report with no credit card Fastin Lg Ringtones V111 Verizon Wireless. Canadian credit score reports Methixene Iproniazid Lamictal Free credit report no membership online Gitalin, Thyroid Naprosyn Free credit report services Pravastatin Payday loan onlines Theophylline: Annualfreecreditreport.com Three in one credit report! Low interest balance transfers canada credit cards Penicillamine Bentyl Instant approval credit cards with no fees Dexbrompheniramine Download Free Ringtones For Verizon Wireless Phone Clean up credit report Instant approval credit cards for poor credit Etoposide Olsalazine Epivir Get credit report Zero percent transfer balance credit cards Low interest credit cards with no balance transfer. Trans union credit reports Equifax credit reports, Credit report fraud Credit report information Free consumer credit report Restoril Balance transfer best deals credit cards Pentazocine Guaranteed instant approval credit cards for poor credit Consumer credit reports, Fenfluramine Bureau credit reports Music Ringtones Converter Aminoglutethimide Ethchlorvynol Instant approval credit cards uk! News report no credit card required Online auto insurance? Ethanol Free Samsung Cell Phone Ringtones My credit reports Free instant credit report online no credit card needed. My free credit report Dyazide Aldactone Free online credit report no trial offer Cevimeline Diclofenac Instant approval poor bad credit cards Caller Download Hotlink Maxis Ringtones Aspirin Efavirenz Naltrexone Biaxin Free no obligation credit report Pyrazinamide Secobarbital Griseofulvin Chloroquine Voltaren. Dianabol Credit cards for balance transfers New jersey free credit report Phenelzine No credit instant approval credit cards 3 credit reporting Free Maker Nextel Ringtones Software Robaxin Aztreonam Free Motorola Tracfone Ringtones Free copy of my credit report Phenindione Colistimethate Download Ringtones For All Nokia Phone Dichloralphenazone Metolazone Games report without credit card Prempro Free Boost Real Music Ringtones 100 Free Real Ringtones, Obtain free credit report Free instant credit report online noe credit card needed Reporting credit 3 in one credit report Methocarbamol Free credit report no credit card needed Mechlorethamine Free Ringtones For Sprint Sanyo Phone, Authorization and release credit report Gentamicin! Decamethonium Credit report laws Septra Auto refinance Carbimazole Refinance investments Imipramine Check credit reports Verizon Wireless Lg Vx4500 Ringtones Instant payday loans: Dactinomycin How to read credit report Ergocalciferol Trans union credit report. Credit cards with low apr Credit report dispute forms Credit bureau reporting Explaining credit report scores? Free instant credit report online no credit card needed Instant approval credit cards, Amphetamine Mometasone, Xanax No obligation free credit report online Daunorubicin 3 credit reports! Mda Ringtones T Mobile Brompheniramine. Provigil Instant approval for credit cards with poor credit Debt settlement Selegiline Adapalene Iodipamide Annualcredit report No apr credit cards! Idoxuridine Estraderm Free Ringtones For T Mobile Phone Flunitrazepam Best credit cards to transfer balances 0 balance transfer credit cards Free Music Nextel Phone Ringtones Imipenem Triflupromazine One free credit report per year Free canadian credit reports instantly online Experion credit reporting! C139 Motorola Ringtones Phencyclidine Astemizole Student credit cards with no apr Lamictal Oxprenolol Child life insurance Allstate fair credit reporting act Pindolol Zyrtec Free instant credit report Cell Free Phone Ringtones Wallpaper Instant online credit approval and credit cards Cogentin. American debt consolidation Alprazolam Nokia Ringtones And Logo Macrobid Diltiazem Boost Free Nextel Ringtones Flurazepam Diclofenac, Clomiphene B class instant approval credit cards Fenoprofen Free instant credit report with no credit card Isoxsuprine Seroquel Sprint Pcs Ringtones Download Rofecoxib Free Reggaeton Real Ringtones Thiothixene Free no obligation credit reports Commercial property loan: Business credit card instant approval credit cards Dofetilide American express cards instant approval bad credit Credit reporting bureau? Ramipril Get free credit report. Cefprozil Buying life insurance, Triprolidine 3 bureau credit report 025 interest balance transfer credit cards Health insurance: How do i get my free annual credit report Mosquito Ringtones Silent! Promazine Cortisol? Interferon Apr balance transfer credit cards Bad credit 2b instant approval 2b credit cards Trans union free credit report Free credit report no credit card needed Piroxicam? Free Real Music Ringtones For Alltel Instant approval department stores credit cards Pentobarbital Credit reports 3, Instant approval credit cards for people with high balances Annual credit report free Credit report and scores Robaxin! Oxybutynin Free credit reports without using a credit card Credit reports no credit card Vicodin 025 apr balance transfer credit cards Cell Music Onto Phone Ringtones, Ceftibuten Converter Joy Ringtones Serial Fixed apr business credit cards Afrin Credit report dispute Nialamide, Saccharin Low interest credit cards visa fixed apr Abacavir Absolutely free online credit reports Refinance Credit rating report: Credit repair report service Disputing credit report! Cogentin Instant approval credit cards students Poor credit instant approval cards Debt consolidation Zuclopenthixol 3 bureau credit report: Ciguatoxin Glipizide Lynestrenol Free Real Ringtones Sprint Free Phone Ringtones Sprint Time instant approval credit cards Pheniramine Granisetron Desipramine Search high limit credit cards instant online approval Credit reports com Timolol Free no obligation credit report Hydrochlorothiazide Home insurance price Neomycin? Levoxyl Instant approval credit cards with bad credit Digitalis Streptomycin Download Free Midi Ringtones Atacand? One credit report Converter Joy Ringtones! Risperdal Dimenhydrinate. Debt settlement Transunion credit reporting agency Free credit report com Instant credit approval for credit cards on line Credit report services Afrin Credit cards with 0 on balance transfers Credit cards with balance transfer: Chloroquine Reports credit cards Enoxaparin Instant approval credit cards with bad or no credit, Yearly free credit report 3 credit report agencies Lo apr credit cards Cleaning up credit report Imiquimod Amitriptyline On my credit report Free credit report instantly Dash Mobile Ringtones T Free Alltel Lg Ringtones! Fosinopril Credit report self help repair! Diazoxide Obtain free credit report Chenodiol Refinance homes? Flupenthixol Meperidine Download Free Bollywood Ringtones Balance transfers on credit cards! Unlimited credit reports Podofilox History transunion credit report Repaglinide! Life insurance policies Lipitor. Thioridazine Allstate fair credit reporting act litigation New instant approval credit cards Guanadrel. Business credit cards instant approvals Canadian credit report Copy of credit report Bureau credit reports Reporting credit card Bromodiphenhydramine. Felodipine Instant approval bad credit unsecured credit cards Download Free Midi Ringtones Tinzaparin Digitoxin Nextel I730 Ringtones Business credit report solectron centum Lamotrigine, Buprenorphine Loan debt consolidation, Get a copy of my credit report Major credit reporting agencies Aprobarbital Yasmin Free Kiss Ringtones Loperamide Chantix Senna Instant approval corporate credit cards Valerian? Chromium Download Free Ringtones Sprint Free Pcs Ringtones Sprint Lithium Ringtones For Tmobile Cell Phone Instant online shopping credit cards instant approval: Free instant online credit report Low apr balance transfer credit cards? Zalcitabine Free equifax credit report Tolazoline Botox 0 apr on balance transfer credit cards Isradipine: Terbinafine Payday loan Free credit report no membership online Equifax credit report, Instant approval credit cards in uk Us government free credit report Low interest credit cards with no balance transfer fee Free I730 Motorola Nextel Ringtones Procyclidine Consumer credit reporting reform act: Compare credit cards instant approval Lotrel Report free no credit card required for instant online Duragesic Credit report dispute form Credit cards instant guaranteed approval visa Digi Caller Ringtones Mephentermine? Reports on credit Lactulose! Canadian credit cards instant approval online Reports and credit Theophylline Home equity Refinance houses Ergotamine Are credit reports Imiquimod: Dilantin Credit report mortgage leads

10 PHP Myths Dispelled

January 2nd, 2008 by Jaybill McCarthy

php-med-trans.pngI am a PHP developer. Maybe even a halfway decent one. As such, I often find myself engaged in conversations on the subject of web application development in general and PHP in particular. I am continually flustered by the myths, half-truths and outright falsehoods that technical and non-technical people alike hold about this humble programming language.

I’m far from a zealot about anything software related. I think if you’re excited about software, you’re missing the point. It’s like a carpenter being really excited about hammers instead of building houses. Having said that, I feel I really need to dispel a few of these things before they fester any longer. That and I’m getting tired of being talked down to by Java developers who feel their chosen language is The One True WayTM. So here’s my list.

Myth #1: PHP is not a truly Object-Oriented Language

I hear this one a lot from Java programmers. It’s completely false. PHP has excellent OO language facilities. There’s inheritance, abstract objects, interfaces, properties and methods. Okay, there’s no method overrides, but there are ways around this. Late binding is still a bit immature. I will say that there have been vast improvements in PHP’s OO mechanics with PHP 5, but I’ve written lots of PHP 4 apps that were totally OO. The mere fact that you can write purely procedural PHP code doesn’t mean that PHP isn’t OO capable. Furthermore, the fact that PHP allows you to mix OO and procedural code makes things like bootstrap scripts really simple.

Myth #2: PHP Encourages Sloppy Code

Also false. Is there a lot of sloppy PHP code around? Absolutely. PHP’s low entry barrier means that a lot of people who aren’t formally trained developers get in over their heads. The sloppy code that results is a result of poor training and bad management, not the language itself. Saying PHP encourages sloppy code is like saying hammers encourage bloody thumbs. Sure, you can bang your thumb with hammer, but is that the hammer’s fault or yours for not knowing how to use it correctly?

Myth #3: PHP doesn’t follow MVC

I know this sounds ridiculous, but I can’t tell you how many Rail-tards I’ve had this discussion with. No, PHP does not, in and of itself, provide an MVC framework. Neither does Ruby, or any language for that matter. That’s because Ruby and PHP are languages, not a application frameworks. MVC is a design pattern, not a language facility. There are many great MVC frameworks written for PHP. I like the Zend Framework. Can you make database calls from a script that also renders HTML? Sure you can. Does that mean you should? No.

Myth #4: PHP is slow because it’s interpreted

This one is insidious because it sounds so plausible. In fact, it should be true. In practice, it’s not. The Zend Engine that powers most PHP implementations is ridiculously fast right out of the box. Combine it with an accelerator, (like the free eAccelerator) which pre-complies and caches the code (and re-complies it if it changes on the disk), and it’s one of the best performing application platforms around, even compared to things that are traditionally compiled, like Java and .NET. Short of writing your app in C or C++, compiling it native and hooking directly into the web server or something, you’re not really going to get much faster.

Myth #5: PHP doesn’t have a good IDE or Debugger

This is true. I doesn’t have one. It has several. There are at least two debuggers and many good IDEs. You can get all the goodies you’d expect, like breakpoints, variable watching, mouse-over evaluation, etc. Can you use a text editor and an FTP client? Sure you can. You certainly don’t have to, though.

Myth #6: PHP apps all look the same

I have to say, it took me a long time to figure out what people who made this assertion were getting at. At first I shrugged it off as if the person saying it was crazy. After all, PHP is just a language, you can make the output look like…whatever you want! Surprisingly, I’ve heard this a lot. Eventually I determined that the confusion stems from non-technical people confusing PHP with PHP-Nuke, which is just an application written in PHP. It’s fairly customizable, but deals in columns and boxes that all look kind of the same.

Myth #7: PHP isn’t really for “serious” developers.

This is another one I hear from Java developers (and perhaps more amusingly, .NET developers). Similar to #2, I think this stems from PHP’s low entry barrier. Pretty much anyone can learn the rudiments of hacking a PHP script together in an afternoon. Does this mean it has no place in “serious” development by “serious” developers? Well, PHP, like any development platform, is a tool. How well a tool is used varies greatly based on the skill and training of the person using it. I have written many large scale, robust, high performance applications in PHP and so have lots of other people.

Myth #8: PHP is only good for web applications

That was true once, but these days it’s pretty much general purpose. It has a command line interpreter that can be run completely independent of the web server (for scripts) but can still use your existing PHP code libraries. You can even knock together GUI applications using PHP-GTK. Admittedly, PHP’s lineage and primary purpose is web applications, but that’s far from all you can do with it.

Myth #9: PHP code is a mess of “include” and “require” statements that break easily.

Being a scripting language, PHP is interpreted at run-time. That means any code that gets executed has to get pulled off the disk and the script in question needs to know where that is. The easiest (but by far the worst) way to do this is to place an “include” or “require” statement that loads your external script. If you do this and you move or rename a file, your script breaks unless you change the offending statement. A mess of includes and requires can make your code into spaghetti.

Fortunately, by following sound OO processes, good naming conventions and using __autoload, in-line includes and requires are generally completely unnecessary. __autoload is a callback function that accepts a class name as an argument. If you instantiate a class that the engine doesn’t know about, it calls your __autoload with the name of the class as a string. Assuming you have a reasonable naming convention, (one class per file, class name and filename match) it’s pretty trivial to load the required class when you need it. This has the side benefit of only loading classes that are actually needed for a particular script, as opposed to loading all of them before your script even runs.

Myth #10: PHP Code is rife with in-line SQL statements

Take a look at a lot of PHP applications and you’ll see it. SQL being scraped together with concatenated strings and passed to database (often mysql) specific statements. This makes your code brittle, annoying to debug and maintain and subject to SQL-injection attacks. It’s also completely unnecessary and easily avoided. Simply use a database abstraction layer like Zend_DB or ADOdb instead of directly talking to the database.

So there you have it. Ten common PHP myths utterly…well…busted. This isn’t to say that PHP isn’t without its faults, but I think few other tools get the unwarranted bad rap that PHP gets. Here’s hoping I cleared things up a little!


Posted in list, php, programming, rant | 42 Comments »

Heywire Guild & Gallery

December 11th, 2007 by Jaybill McCarthy

heywire_screenshot.pngI just finished phase one of the biggest projects I’ve ever done in my life. It’s called Heywire Guild & Gallery. While it’s still pretty new (as of this writing it’s four days old) it’s gaining steam rapidly. I wanted to document my experience while it’s all still fresh in my head.

A little over a month ago, my old friend Steve King came to me with a crazy project. Steve gets a lot of crazy projects, but this one was especially crazy. Essentially, the client wanted to build “Facebook meets eBay, but for art.”

Being a guy that builds social networking sites for a living, I usually tune out right around the time someone starts a sentence with “It’s Facebook meets…” This is because most of the time, the person saying it feels they are the only person that ever thought of harnessing the unspeakable power of “social networks” and “the Internet” for whatever their niche interest happens to be. They also usually don’t have any money, or worse, want you to work for questionable equity. (read: free) This is because they are true visionaries. Isn’t the prospect of basking in their utter awesomeness payment enough?

This, however, was different. Steve’s client (who needs to remain nameless) is a smart business man who made a lot of money in several other ventures. He has a lot of good ideas and the resources to make them happen. There were also no shady equity terms. He wanted it built and was prepared to pay for it. All good so far. Then came the kicker: The site needed to launch December 6th. I found out about it on October 19th.

Normally, I avoid projects that I feel are impossible, no matter how much I want to do them or how much I need the money. It’s better to decline work you can’t do than try to do it, fail and not get paid. I very seriously considered passing on this job considering the time constraints. However, I had just come off building a few other large sites that had a lot of similar elements, so I wouldn’t need to start from scratch. In fact, for going on a year now, I’ve slowly been building up a community application based on top of the Zend Framework. Each time I do a new site, I add to and refine the the underlying app. This seemed like a great opportunity to not only reuse earlier work, but further the platform. So I took the gig.

Step One: Tear it Down

So what I had when I started Heywire was the code from three different apps: MashupChallenge, LazyLibrary and BonAbode. I was pretty proud of how these came together, but they were all pretty site specific. MC and BA share a ton of code, but they’re still distinct apps. The first thing I wanted to do with Heywire was make the application utterly generic, so that building a site on top of it would mean writing a series of modules, plug-ins and a theme. This way, I could eventually port BA and MC to it, so I’d be maintaining one core app instead of several. I wanted to make the Wordpress of community sites, in so much as that when you customize Wordpress, you do it via plug-ins and themes, not by hacking the code base.

To me, there’s a pretty small list of things that are core to absolutely every app I build. I needed to get down to these core things and rip out anything site specific.

First, I needed an MVC framework. Zend does a nice job of this. You can easily break your app into modules, each with it’s own controllers and models. I really wanted to use Smarty for my templating solution instead of phtml, as I find the syntax pretty friendly and it has a nice precomiling and precaching system, say nothing of its rad plugin system. By implementing Zend_View_Interface, Smarty can easily and transparently supplant the view system supplied with the framework. That’s just how they roll over at Zend. Zend_DB is a really flexible way to handle the model layer, as you can be talking to a generic database table in about three lines of code. So now we’ve got the controller, view and model stuff taken care of.

A note on the model thing. I use MySQL 5 for two important reasons. Stored procedures and views. Zend_DB_Table can talk to a view as easily as it can talk to a table. (It just can’t insert or update, obviously.) I can tell you right now that there is not a single bit of in-line SQL in this application, and it’s pretty complex. Any time I have a query that makes for an overly complex where clause or needs a join, I make a new view and a new model object to go with it. This saves you the overhead of creating a huge, ridiculous query at run time and makes your code a lot more manageable. It also saves you from a lot of SQL-injection-hacky-type-stuff.

Core app functionality consists of a few important things. There are users, roles and resources. Users (”jimmy” and “pam”) have roles (”user” and “admin”). Roles can access resources. (”post blog entry” and “delete user”) Zend_Auth and Zend_Acl in combination give you user authentication and access control. It was really important to me to keep access control out of the controller logic. That way, changing what each role can do is a configuration change, not a code change.

I decided to control access at the action level. This has so far proved enough for my purposes. If I need something more granular than I can do with one action, I simple make another. To control access to these, I needed to dynamically get a list of what they are for each controller class. First I tried using the introspection API, but that proved annoying as I had to actually load each class to introspect it. I ended up going with a much quicker and dirtier solution. Knowing that Zend_Controller looks for actions based on their function name being “somethingAction”, I just regexed the text of the class files for “function [something]Action”.

I also have my own extended version of Zend_Registry that stores all its values in a db table. Whenever I need a configurable value in the application, I call App_Registry::get(’some_value_you_can_set’,'default value for this’) - this checks the registry for said key, and if it doesn’t find it, it adds it and uses the default value provided. I have a form for editing these values in the application. This is cool, because it means that when you add a new feature that requires a setting, it doesn’t break the app if the db doesn’t have it. The value may not be correct for that instance of the app, but it’s easily set in the db. My bootstrap loads the config from the db and sticks it in the registry. Why not use config files for this? Easy. There is one thing a config file should have in it, in my mind: the location of the database. EVERYTHING ELSE GOES IN THE DATABASE, WARDEN. Seriously. I have two development copies of this thing and three people working on it, I do not need to be copying instance specific config data all over the place. As far as versioning, I do not store config files in subversion. I store a template of a config file, which gets copied to the real version on install. This prevents config values getting overwritten by svn updates.

So now I’ve got my user, role, config and resource model objects and views to create and edit them. I’ve also got actions and views for registration, account editing and basic administration.

Step Two: We Can Rebuild Him

From here, I added things that probably aren’t going to get used in every single app, but would probably be used in most. Things like comments and media. As far as implementation, I made these generic, so they could be attached to users as well as anything else in the system.

At this point, we’ve got the basic elements of a community site. Users, profiles, comments, media and administration. This comprises the core app. We’ve also got a theme, which is a neatly organized set of Smarty templates in a directory tree outside of the application code directory. This way, we can swap themes out as needed without messing the core app up. It It’s also useful when you’re working with a UX person, like I was in this case, because they can make relatively easy subversion commits and updates independent of the core application.

Step Three: Add Modules, Rinse, Repeat

To expand the app from being Generic Social Network to being Heywire Guild & Gallery, I needed to start building out additional modules. I store these next to the default module and maintain them in a completely separate subversion repository for easy separation. (More on that next time.) By assuming a directory structure, I can automatically add new modules to my include path in my bootstrap. This is cool, because it means that in the future, add on modules will be easily integrated and removed.

So in some cases, modules are completely standalone, like the blog. I won’t be managing the content here, so it’s important I have an interface for the client to do it. Wordpress is easy to use and well known. For this reason, the blog is nothing more than a series of XML-RPC calls to a hidden copy of Wordpress, because, frankly, I’d rather do my own work than repeat what Matt Mullenweg did just for the sake of having it all under my own roof. I call this process “sidecarring” and I do it wherever it makes sense. In fact, the whole “CMS” in this thing just uses the pages functionality of Wordpress. I hate duplicating the work of others, especially when said work is such high quality.

In most cases, though, modules need to tie back into the default module. The “usercontent” module (my generic term for what is called “artwork” in heywire) needs to know about users. For example, when I delete a user, all of their content should also get deleted. I could of course hack the user module, but then I’d be violating my “keep it generic” rule. To overcome this, I borrow a concept from Wordpress and many other well-written apps - callback functions. In each of my controllers and model objects, whenever there’s something that could usefully be extended or filtered, I register a “hook” with in my registry. These are all accessible via a plugin object that extension code can instantiate and use. Extensions can register “actions” or “filters”. Both specify a class and a function to be called by a hook. The actions must specify a callback function that accepts an array called “params”. Filters work the same way, except that they must also return an array with the same number of keys. So for our earlier example, the “user” model object has a hook called “post_delete”, which passes passes a param array of user records that were just deleted. Usercontent has a plugin that adds an action to that hook to delete any usercontent objects belonging to that user. Using this method, I can add pretty much anything to the core app and keep it completely distinct from it at the same time.

Things I Have Learned From This

Normally I’m busy learning from my mistakes. This one time, I’m going to learn from my success, and I hope you can too.

First, if you’re rolling your own app from scratch these days, you are dumb. There’s just no other way to say it. There are no shortage of excellent application frameworks these days suited to a wide variety of different sites. What we did here simply would not have been possible without a robust, extensible application framework to do the tedious stuff, like talking to the database and such. I like Zend because it makes sense to me, but this isn’t like…Zend über alles or anything. I looked at CakePHP and Symfony before deciding on the relatively new Zend Framework. All three are very solid. I went with Zend because they have a very take it or leave it approach to everything. If you want to use the framework and nothing but the framework, it’s pretty complete. If you want to skip some stuff and add other stuff in, they make that really easy. It’s a tool, not a way of life.

Second, always build your apps generically. Wherever possible, create plugins and extend existing classes rather than hacking things for the app you’re working on. Yes, it requires more thinking, but once you get into that mindset, it will save you tons of work and headaches.

Lastly, and perhaps most important: specialize and make it easy for other specialists to work with you. Unless you’re explaining what you do to your grandmother, there’s no such thing as “an Internet guy” any more. Since around 1997, there are several different disciplines under the umbrella of web site production. If you purport you can do all of them, you’re good at one and lackluster at the rest. Know what you’re good at and find people whose work you admire to do the parts you’re not good at. I am a developer. A good one, maybe. I am a below-average HTML/CSS guy. If you are a developer, do not be fooled by HTML’s apparent simplicity. Cross-browser compatibility and accessibility issues are enough to break a man. Also, engineering types tend to make the worst interface decisions imaginable. Web interfaces are an area of specialized knowledge these days, if it’s not your core competency, find a ninja. They’re out there. Lucky for me, I know one of the best UX/HTML/CSS guys in the industry, that being Cory Duncan. Cory brings a level of polish to everything he does that makes him indispensable. Hire Cory if you can. Tell him I sent you.

Where I’m Going From Here

You may have noticed that I haven’t shown any code samples from the generic application I’ve been talking about here. There’s a good reason for that. Pretty soon, you’re going to be able to look at the whole thing yourself. That’s right. I’m in the process of turning it into an open source project, under a BSD-style license. It’s going to be called communit.as, and I’ll be setting up a site for it shortly. I’ve benefited so much from the open source software that made the thing possible it seems wrong not to share it. Stay tuned.

If you have any questions about the stuff I’ve talked about here or thoughts on how I’m doing things right/wrong/stupid, feel free to leave a comment or email me.


Posted in Zend_Db_Table, communit.as, databases, heywire, lazylibrary, php, plugin, programming, wordpress, zend, zend framework | 7 Comments »

Using the Zend Framework with Multiple Databases

September 12th, 2007 by Jaybill McCarthy

This article is what I hope will be the first in a series about my favorite way to develop web applications, the Zend Framework. I’m not going to try and sell the framework to you, I’m going to assume you already know all about it and that’s how you got here.

The Zend_Db_Table class provides a powerful and easy-to-use way of abstracting your data model into PHP objects. One problem I recently encountered was that the design of the class assumes you’re only going to use one database, which may not be the case.

Let’s assume you’ve got a Zend application that follows the de facto standard laid out in this tutorial. You’d have something in your application/config.ini file that looked like this:

  1.  
  2. [general]
  3.  
  4. db.adapter = PDO_MYSQL
  5.  
  6. db.config.host = localhost
  7.  
  8. db.config.username = zfuser
  9.  
  10. db.config.password = ninjabunnies
  11.  
  12. db.config.dbname = zftest
  13.  
  14. db.config.port = 3306

Then in your index.php bootstrapper, you’d have something like this:

  1.  
  2. Zend_Loader::loadClass(‘Zend_Controller_Front’);
  3.  
  4. Zend_Loader::loadClass(‘Zend_Registry’);
  5.  
  6. Zend_Loader::loadClass(‘Zend_Config_Ini’);
  7.  
  8. Zend_Loader::loadClass(‘Zend_Db’);
  9.  
  10. Zend_Loader::loadClass(‘Zend_Db_Table’);// load configuration
  11.  
  12. $config = new Zend_Config_Ini(‘./application/config.ini’, ‘general’);
  13.  
  14. Zend_Registry::set(‘config’, $config);
  15.  
  16. // setup database
  17.  
  18. $dbAdapter = Zend_Db::factory($config->db->adapter,
  19.  
  20. $config->db->config->toArray());
  21.  
  22. Zend_Db_Table::setDefaultAdapter($dbAdapter);
  23.  
  24. Zend_Registry::set(‘dbAdapter’, $dbAdapter);

In the above example, we set all the database parameters in the config.ini file. We load these values into dbAdapter and decalre that adapter as the default via the setDefaultAdapter method of Zend_Db_Table. Any classes derived from Zend_Db_Table abstract will use this database parameter. This works fine for one database, but what if we’ve got more than one? We can’t really use the default adapter anymore, at least not in the usual way.

One way to get around this problem is to create an array of adapters and make the key of the array the name of the database. We can then implement an application specific table class that will allow us to easily choose the adapter we want to use. We can then have our application table classes extend that.

For this example, let’s say we’re building a site to sell textbooks, and there’s two databases: library and order_system

Your config.ini would now look something like this:

  1.  
  2. [databases]
  3.  
  4. db.library.adapter = PDO_MYSQL
  5.  
  6. db.library.config.host = localhost
  7.  
  8. db.library.config.username = libraryuser
  9.  
  10. db.library.config.password = bunch0crunch
  11.  
  12. db.library.config.dbname = library
  13.  
  14. db.library.config.port = 3306
  15.  
  16. db.library.default = truedb.order_system.adapter = PDO_MYSQL
  17.  
  18. db.order_system.config.host = localhost
  19.  
  20. db.order_system.config.username = ecommerceuser
  21.  
  22. db.order_system.config.password = showMeThe$$$
  23.  
  24. db.order_system.config.dbname = order_system
  25.  
  26. db.order_system.config.port = 3306

The in your index.php bootstrapper, you would do something more like the following:

  1.  
  2. Zend_Loader::loadClass(‘Zend_Controller_Front’);
  3.  
  4. Zend_Loader::loadClass(‘Zend_Registry’);
  5.  
  6. Zend_Loader::loadClass(‘Zend_Config_Ini’);
  7.  
  8. Zend_Loader::loadClass(‘Zend_Db’);
  9.  
  10. Zend_Loader::loadClass(‘Zend_Db_Table’);// setup databases
  11.  
  12. $databases = new Zend_Config_Ini(‘./application/config.ini’, ‘databases’);
  13.  
  14. $dbAdapters = array();
  15.  
  16. foreach($databases->db as $config_name => $db){
  17.  
  18.  $dbAdapters[$config_name] = Zend_Db::factory($db->adapter,
  19.  
  20.                                         $db->config->toArray());
  21.  
  22.  if((boolean)$db->default){
  23.  
  24.         Zend_Db_Table::setDefaultAdapter($dbAdapters[$config_name]);
  25.  
  26.  }
  27.  
  28. }
  29.  
  30. Zend_Registry::set(‘dbAdapters’, $dbAdapters);

All we’re doing here is creating an array of adapters instead of just one. If we set the parameter “default” on one of them to true, that will become our default database. This will save you a bit of typing later if have one database that you’ll use most often and one or more other ones you use less.

Then we create a new class, called App_Db_Table_Abstract. You can put this in /application/models folder, but I like to create a folder called /application/lib for my abstract classes. Either way, just make sure it ends up in your include path.

  1. abstract class App_Db_Table_Abstract extends Zend_Db_Table
  2.  
  3. {
  4.  
  5.     function App_Db_Table_Abstract($config = null){
  6.  
  7.         if(isset($this->_use_adapter)){
  8.  
  9.                 $dbAdapters = Zend_Registry::get(‘dbAdapters’);
  10.  
  11.                 $config = ($dbAdapters[$this->_use_adapter]);
  12.  
  13.         }
  14.  
  15.         return parent::__construct($config);
  16.  
  17.     }
  18.  
  19. }

All we’re doing here is looking for a class property called “$_use_adapter”. If that’s set (in our derived classes) then we’ll look for that dbAdapter in the registry. If not, we’ll use whatever the default is set to.

Here’s an example of a derived class that would do this. It uses the “orders” table in the “order_system” database.

  1. class Orders extends App_Db_Table_Abstract {
  2.  
  3. protected $_name        = ‘groups’;
  4.  
  5.  protected $_primary    = ‘group_id’;
  6.  
  7.  protected $_use_adapter = ‘order_system’;
  8.  
  9. }

Now this class will use the correct adapater instead of the default. That’s all there is to it!

This method of implementation is nice because you could have one database, two databases or a hundred databases and the only thing you’d need to do would be to add additional sections to the config.ini file.


Posted in Zend_Db_Table, databases, php, programming, tutorial, zend framework | 2 Comments »