JANUARY 2003 - Volume II - Issue 1 php|architect The Magazine For PHP Professionals Writing Secure PHP Code Make your applications safer
IonCube PHP Accelerator 1.3.3 Reviewed for you: CodeCharge Studio 1.0
Exclusive ZEND
Interview Plus: Using the .NET Assembly with PHP Writing A Web-based PDF Viewer Taming Full-Text Search with MySQL This copy is registered to: Jakob Breivik Grimstveit Accessing the Windows API and Other DLLs [email protected] Implementing Database Persistence Layers The designers of PHP offerfer youyou thethe fullfull spectrumspectrum ofof PHPPHP solutionssolutions
Serve More. With Less. Zend Performance Suite Reliable Performance Management for PHP
Visit www.zend.com for evaluation version and ROI calculator
Technologies Ltd. January 2003 IN D E X T ABLE 4 5 Departments 73 71 6 68 58 php| | | | | | | | OF · PHP Architect CONTENTS exit(0); BOOK REVIEWS TIPS & REVIEWS EDIT NEW STUFF PHP-WIN Language Let’ by JohnHolmes ionCube PHPAccelerator CodeCharge Studio1.0 s CallittheUnknown ORIAL TRICKS · www RANTS .phparch.com ar chitect Features 30 62 19 10 37 42 50 | | | | | | | T W Accessing theWindows Implementing Dat Using The W by Mar V by DavidJorm other DynamicLinkLibraries by TheoSpears by LeonV MySQL by ShawnBedard Persistence LayersinPHP by Mar Heaven Programming: SmallBusiness The ZendofComputer by JayeshJain through COMinPHP aming Full-T iewer riting aW riting SecurePHP co T co T ismer abini abini .NET eb-based PDF ext Searchwith Assembly abase
Code E
API and X
3 C
L
U
S
I
V E January 2003 E D IT O R IA L R A N T S EDITORIAL er forever the pagesofmagazine easi- should make"flipping" through the tableofcontents. This tom ofeachpagelink back to words "php|ar to eachofthearticles,while contents onpage3isfullylinked read iton-screen.Thetableof magazine, forthosewholiketo ed internallinksthroughoutthe First ofall,wehavenowinclud- number ofchangesinthisissue. next month. range ofissuestofixbeforethe than brilliantand,therefore,a ance onwherewehadbeenless was ver critiques sentourway Still, wehadafewconstructive expecting atenpagefanzine. tained inphp|a,ashewas amount ofinformationcon- they weresurprisedbythe where someonehadwrittenthat a notefoundinwebforum, detail; mypersonalfavoritewas ed intermsofcontentand was betterthanyouhadexpect- to letusknowthatthemagazine ver sure,and theDecemberissuedid originally expected,tobe encouraging-better thanwehad ing). then, incaseyouwerewonder- from-a mentalinstitutionsince been committedto-andreleased sleep fortwodays(yes,Ihave were terriblytired,Icouldn't it. Eventhough,asaresult,we good aswecouldpossiblymake ensure thatever almost astraightmonthto had workedinsanehoursfor php|a hitthevirtualstands,we By thetimefirstissueof fire" tomakeorbreakyourday As aresult,youwillfind Luckily There isnothinglikea"trialby y well.Manyofyouwroteus y good-itgaveusguid- , theresultswere · PHP Architect yone. chitect" atthebot- ything wasas , andthat · www .phparch.com . a goodone). cially owemeadrink.Makethat us (notetoBrian-younowoffi- only behappytohavehimwith process toourteam,andwecan knowledge oftheeditorial technical expertiseandvaluable guage. Brianbringshisexcellent whom Englishisthefirstlan- person inoureditorialstafffor that thereshouldbeatleastone good job,butitbecameevident thought wehaddoneapretty the Decemberissuewasout,we Jones from thisissuefor but atleastwe'retr they say Whether wesucceedornotis,as information availableoutthere. by increasingthequalityof ects, andthatcanonlybedone choice forenterprise-levelproj- beloved languageaninvaluable that ofhelpingtomakeour role inthePHPcommunitytobe ics wecoveraswell.W improved thequalityoftop- us out. just nowgettingachancetotr and welcometothosewhoare those whohavebelievedinus- our waytosaythankyouall this, isthatthisissuefree.It's noticed bythetimeyouread no doubtwillhavealready Happy reading! joins oureditorialteam.After Finally The othergoodnews,asyou W ith thisissue,Ithinkwehave , I'mhappytosaythat, , forposteritytodecide, ward, BrianK. ying! e wishour y Inc., P Editorial: General mailbox: tained hereinorinallassociatedmaterial. ities withregardsofusetheinformationcon- and figures,thepublisherassumesnoresponsibil- azine, includingallassociatedsour assuring theaccuracyofcontentsthismag- Although allpossiblecarehasbeenplacedin Canada. Subscriptions: twelve timesayearbyMar php|ar Sales T John W echnical Jorm, TheoSpears,Mar Arbi Arzoumani,ShawnBedard, Copyright ©2002-2003Mar php|architect Associates, & chitect (ISSN1705-1142)ispublished . O. Box.3342,Markham, advertising: V Contact Information: support: . olume II Graphics & Holmes,JayeshJain,David Januar Administration Emanuela Corso Arbi Arzoumani Arbi Arzoumani Brian K.Jones Mar Mar Leon V I nc. —AllRightsReser Publisher Authors Editors co T co T support@phpar editors@phpar subs@phpar sales@phpar info@phpar y ismer , - Issue1 co T 2003 abini abini Layout abini & co T ce code,listings co T ch.com ch.com ch.com O N ch.com abini & ch.com Associates, L3R 6G6, abini, ved 4 January 2003 N E W S T U F F NEW called ConstructionerW new ContentManagementSystembasedonPHP announced inearlyDecemberthepublicationofits web ser PHP asaseparateexecutabletorunscriptsthrough PHP vs.theCGIexecutable,whichisusedwhenusing naming oftheCLI(command-lineinter has allbutdominatedthemailinglistsoflate—the and thankfullyonlylastedafewdays. bugs markedas“critical”inthebugtrackingsystem, commit tothePHPCVSrepositor before thefinalrelease—developershavebeenaskedto http://www when theCMSengineisusedinapublicwebsite. which retailsfor$399(US),mustbeobtainedonly ers—there arenotimelimitsonthetrialversion.Akey The softwareisavailableforfreedownloaddevelop- languages, andcanbeintegratedwithDreamweaver agement system,supportforanarbitrar Constructioner featuresaweb-basedWYSIWYGman- ment solutionaimedprimarilyatnon-technicalusers, it. with theproductandalsofindmoreinformationabout V The PHPdevelopershavealsosolvedadilemmathat The newversionofPHPisout.RC4wasthelaststep A livesampleisavailableat Conceived tobeaninexpensivecontentmanage- ienna, Austria-basedArtwareMultimedia STUFF ver . New PHP-basedCMS · PHP Architect .constructioner Artware Releases PHP 4.3IsOut e b T .com, whereyoucanplay · www echnology y onlychangesthatfix .phparch.com . face) versionof y numberof , . , http://www be takenwithinamonthofregisteringforit. According totheExpertRatingwebsite,exammust paid onlinethroughasecurecreditcardform. mailing. advanced subjectslikeregularexpressions,sessionsand like operators,syntax,andtypecasting—tomore topics rangingfromthebasicsofPHPlanguage— your basicmid-termnightmare.Thequestionscover which couldbecorrect— answers, oneormoreof two andeightdifferent tions, eachfeaturebetween forty multiple-choiceques- launched anewcertificationexamforPHPdevelopers. For moreinformation,youcanfollowthislink: The ExpertRatingexamcosts$10(US),whichcanbe The examtakesplaceentirelyonlineandconsistsof Online certificationcompanyExpertRatinghas php| A Professional. ExpertRating LaunchesPHP W .expertrating.com/details.asp?examid=91. e Certification Exam Subscribe tophp|aT DareY W T i n abookfromW ar o Be chitect The MagazineF rox Press oday and ou or PHPP r ofessionals php |a 5 January 2003 P H P -W IN PHP L of itsintuitiveinter cation, Iwouldhavetoincludeatleast30screenshots just callitacodegenerator like toputCodeChargeinitsowncategor code generator—runforthehills!".However the web.Someofyoumightthink"Ohno,another CodeCharge isapower pose. It'sagreatlearningexperience.Innutshell, must sitdownandactuallyuseitforapracticalpur- 'Component Builders'are: wizards called'Component Builders'.Someofthe erate codeandletyoumanage itwithease. another V engine usingXMLfileformats.Ifyouthinkthis is 1.1, ColdFusion4.01,andPerl5.How?ItusesanXSL ASP generation forthefollowingprogramminglanguages: you canusetheprogramfor30days.Itsupportscode lation wasstraightfor copy andstartusingit. this review and publishyourproject.Isuggestthat,onceyouread Grid Builder- Letsyouquicklycreatedatabase CodeCharge comeswith a listofcodegenerating Let's startbycoveringthebasicgrounds.Theinstal- an easyreview et mestartbyconfessingtothefactthatthiswas .NET (C#),ASP3.0,PHP4.0,JavaSer - WIN isual Studio,thinkagain—thisbabycangen- , gototheirwebsiteanddownloadthetrial · PHP Architect C . T o face toconfigure,manage,modify o ward. Ifyoudon'thavealicense, fullyappreciatethisproduct,you d ful codegeneratingsoftwarefor . T e · www o C fullyexplorethisappli- .phparch.com h Reviewed ForY a y vlets 2.2,JSP , ratherthan By ArbiAr r , Iwould g not e , S zoumani accounts. security loginpage.Or pages (ie.registrationsforms). forms. Thisishandyforboth front-endandback-end management tools. Login Builder-What'saback-end withoutaproper Record Builder-Rapidlycreatedatamaintenance grids onyourpages.Thisisgreatforthosebackend t tion technologyin1999.Itwascompleted2001. company Delaware andareaself-fundedprivatelyheld Application Development)tools.Theyarebasedin Y Company Background: CodeCharge CodeCharge HomePage: 30-day trial The CodeChargedownloadisafullyfunctioning Download limitations: CodeCharge Download Page: File Size16.7MB 20MB HardDriveSpace 64MB RAM W Requirements: CodeCharge Studio:$279.95 CodeCharge: $149 The Cost: o esSoftware Inc.developsandmarketsRAD(Rapid u i ndows '95/'98/ME/NT4/2000/XP u d . Theybegindevelopingthecodegenera- i o , haveyourusersloginto their 1 . 0 6 PHP-WIN CodeCharge Studio 1.0
On top of these code generating wizards, sits the submit button. Application Template Library, a set of built-in templates HTML - Here you can edit the HTML directly. Since for common web solutions that can be configured and the HTML code is kept separate from the actual server launched in no time. The version of CodeCharge that side code, it's easier to modify any visual elements of a I had came with the following solutions: Employee page. Directory, Bug Tracking, Task Manager, Portal, Code - As expected, this is a fully syntax highlighted Registration Form, Forum, and a Book Store. editor. It is less colorful compared to the built-in PHP Naturally when creating a project, you are asked if show_source() function, but it does the job. you want one of the above solutions or a blank project. Preview - This mode will display the HTML code with- A blank project is not actually 'blank'—there are at least out any special tags (seen in the design mode). 6 common files that are always included in the source Live Page - By providing the URL to the live site, the of every page. These common files can be regarded as page is displayed live from the server. the framework behind the IDE. It's possible to define multiple database connections For those of you using MS FrontPage, here's the good in the same project. This can be useful to pull data news. You can get an add-in and convert your MS from different sources—for example, user data stored in FrontPage into a powerful code-generating monster. a MySQL server, and product catalogue data stored in Take a look at Figure 1 for the added CodeCharge tool- a different location on Oracle. The code generator bars. includes support for the following database libraries: CodeCharge comes with a complete IDE interface. JET, ODBC, JDBC, ADO, DBI, and PHPLib. Before publishing any of the pages generated with the The database connection properties was a little con- Application Builder, the developer can modify anything fusing to setup. I had some trouble setting up a con- from the HTML to the code. There are 5 different views nection string to a MySQL server. (the product kept on of a certain page: asking me for a ODBC driver). Design - A WYSIWYG editor for manipulating your One of great features of CodeCharge lies in its flexi- page. You can drag and drop different components bility: the user can modify any generated code prior to right into your page. For example, an input box, or a publication. All modifications are locked and are not
January 2003 · PHP Architect · www.phparch.com 7 PHP-WIN CodeCharge Studio 1.0
overwritten during any subsequent code generation. shortly, and some of the new features being planned Some of you are probably wondering how good is include: this generated code actually is. Lets not forget that it comes from templates written by other developers— -Integration with source control and versioning other than the common files discussed earlier, the rest systems of the code is fairly well commented. It can be easily -VB.NET support understood and modified by an intermediate develop- -NT and LDAP authentication er—as long as that person understands the language -Generation of site diagrams and test scripts that the code was generated in. The code language -Additional components and builders can be changed at anytime during the development -Enterprise CRM, CMS and team collaboration process. Here's a tip for all of you generating PHP code: solutions built with CodeCharge Studio Make sure you define your session.save_path in your php.ini file prior to previewing your code on the live Conclusion server. The PHP code uses session_start() in its com- mon files. Another thing I noticed is that any modifica- As I suggested before, anyone interested in this appli- tions made to the common files will be overwritten—I cation should download the trial version and check it guess you can't change the framework. out—there are a lot of other features that I did not have What CodeCharge does not provide is a debugging time to cover in this review. From what I heard version tool. However, the folks at YesSoftware have come up 2.0 is going to be a big upgrade. For its price tag this with some nifty XSL templates to generate code. In the code generation application is well worth it. One great near future, users will be able to generate their own application that I can see this being used for is creating templates, themes, components and even wizards prototypes of web applications in very short periods of using an SDKthat is currently in the works. time. In other words, last minute proposals. Also, version 2.0 of CodeCharge will be released php|a
Figure 1
January 2003 · PHP Architect · www.phparch.com 8
January 2003 F E A T U R E S FEA to PHP Oriented (OO)structure.WhenIwasfirstintroduced no realattempttosupportanorganizedObject in fearandagonyasitspopularitygained.Therewas and easy Inexperienced developersloveditbecausewasquick of scopecontrol,dataabstractionandextensibility processing scripts,itscaledver Although thisallowedforrapiddevelopmentofform needed wasrightthereinhandyglobalvariables. processing andpersonalwebpages.Ever 1995, itwasacutelittlescriptinglanguageforform ably soundOO programmingenvironment. But,being was enhancedforbetterencapsulation andareason- ment platform.Therelease ofversion4inMay2000 a scriptingenvironment.It becameaviabledevelop- the languagetoanewstage. Itbecamemorethanjust helped outbyAndiGutmans andZeevSuraskitomove was notgoingwell.Fortunately starting tobuildsizablewebapplicationsinPHPand it real softwareapplications..Developerswereactually tried tobuildanythingofsubstance. It wasmorelikeanobjectspaghettistructureifyou The OOPfunctionalitybuiltintoPHPmakesitpossibletoaccessinformationstoredinadatabasebyusingstruc- When PHPwasfirstdevelopedbyRasmusLerdor The focuswentfromscriptinguppagestobuilding tured, portableandeasilyextensibleapproach--nottomentionthatyoucangetridofthoseuglySQLstatements TURES I m , Iwasalittleuncomfortablewithitsar P , buttheseasonedsoftwareengineerscringed · PHP Architect ·www e p Introduction r l e s m i s y poorlyduetothelack , thecreatorofPHPwas .phparch.com e t e n ything you embedded inyourscripts! chitecture. By ShawnBedard n t Jig T P i c f in echnologies n H . e g works--the persistencelayer cle describesthedevelopmentofonethoseframe- tional OOframeworkstobecreatedforPHP awkward structure.Thishasallowedformoretradi- extending thelanguagebeyonditsinitialbuggyand there hasbeenalotofgoodworkoptimizingand to beandithadalotofotherroughedges.Sincethen, a firstrelease,itwasbuggy classes fromapermanentsour that allowsdeveloperstostoreandaccessobjects or problem. Thepersistencelayerisacollectionofclasses framework inPHPaddressesthisobjectpersistence pear your objectsinthesessionassessionstendtodisap- to stuffanobjectinthem,norisitreasonablestore most commonrelationaldatabasesdonotmakeiteasy can't keepthemaroundforawhile?Unfortunately becomes apparent.What'stheuseofobjectsifyou need topersisttheseobjectsonapermanentbasis can beafileormemor P W REQUIREMENTS PHP Additional Software: O/S: L ith theincreaseduseofobjectclassesinPHP . However D V Any ersion: a , thedevelopmentofapersistencelayer 4.0 andabove a y t e N/A y spacebutinpracticedatais a , abitslowerthanitneeded r . ce. Intheor b s a i s y thissour n . Thisarti- e , the ce , 10 FEATURES Implementing Database Persistence Layers in PHP
generally stored in a database. miscellaneous groups of variables such as really long First I will explain the concepts of OO programming parameter lists in a method call or 32 session variables. and how persistence layers are used for applications All this is eliminated by architecting a good object built in that manner. With that foundation, I will out- model. The long parameter list gets replaced by a sin- line three approaches to designing persistence layers. gle object. The 32 variables in the session can be stored Finally, I will describe the architecture of persistence lay- in 1 or 2 nicely formed objects. ers using the robust persistence layer approach and There are, however, some not-so-pleasant qualities of how it can be applied in common application develop- OO programming in PHP that should be noted. One of ment. these qualities is the performance hit in creating the object constructs and calls to access data. However, Object Oriented Programming and the performance hit is no longer a real concern for Persistence Layers most applications as memory prices decrease and processor speeds increase. So long as your app can As previously mentioned, a persistence layer is used reside in memory and ultra high performance is not a for persisting objects in a permanent fashion. This con- concern, this performance hit will be negligible. cept is not a new one--persistence layers have been Another quality is the complexities of storing objects in very prevalent in more "developed" languages like Java, common permanent storage mechanisms such as data- C++ and even newer enterprise frameworks like .NET. bases and file systems. This complexity can be However, we have only very recent developments to abstracted away from the developer in the form of a thank for PHP's emergence as a real OO architecture, persistence layer. A persistence layer will enable the allowing for constructs such as persistence layers to developer to effectively and easily store business classes become a viable addition to an application. into a permanent storage. Although some developers are very familiar with In PHP, it might not always be appropriate to use this objects and OO programming, it is worth discussing kind of OO programming style. For instance, if you are just what this is, in order to provide a bit of context. simply creating a form with a few fields and passing on OO programming is a type of programming in which the data in an email, the overhead of an OO framework programmers define data structures to group related is not likely necessary. No data is saved, and no state pieces of data. This data is accessed and acted upon by really needs to be preserved. Since a persistence layer accessor functions. In this way, the data structure is in the business of persisting objects or classes, it does becomes an object where internal data is encapsulated not make sense to be using it if you don't have any and accessed through these functions. The resulting objects to persist. However, if that form feeds data into created objects can have relationships in a hierarchical an application that needs to access the data at a later fashion known as inheritance. Thus, objects can inher- time, then OO development makes a whole lot of it attributes and functionality from other objects by an sense. inheritance mechanism. OO programming is the implementation of this object relationship. Approaches to Persistence Layers When developing an OO-architected system, it is often very useful to develop an object model describing Not all persistence layers are created equal. There are what objects exist in a system. This object model will various approaches to creating this kind of framework. also describe how these objects relate to each other. Some require more effort and are good for larger appli- The object modeling exercise allows architects to view cations and some are much lighter weight and are the system in a graphical format before any code is cre- appropriate for smaller applications. ated. This helps to ensure that the application being built can be extended, maintained and effectively Hardcoding SQL developed. At the end of the day, what you end up with is a class (business object) for each of the objects The most common and least palatable approach to created in the object model. developing a persistence layer is hardcoding Structured One of the principal advantages of OO programming Query Language (SQL) in the business classes. (See techniques over their older procedural programming Figure 1) Many people develop this type of persistence ancestors is that they enable programmers to create layer without even knowing it. To illustrate, lets take modules that do not need to be changed when a new the example of creating a User class or object with the type of object is added. A programmer can simply cre- attributes of name, uid, and pwd. The User class would ate a new object that inherits many of its features from need the SQL "select name, uid, pwd from…" embed- existing objects. This makes object-oriented programs ded in the class to retrieve the necessary data from the easier to modify. database and a routine to bind the results to the appro- The other advantage of OO programming is the abil- priate local member variables of the class. Likewise, an ity to pass structured objects instead of long arrays or insert, update and delete would require the same kind
January 2003 · PHP Architect · www.phparch.com 11 FEATURES Implementing Database Persistence Layers in PHP
Figure 1 - Hard-coding SQL in your domain/business classes.
Class 1
Class 2
SQL
Class 3 RDB
Class 1
of routine and SQL. The advantage of this approach is that it allows you Data Classes to write code very quickly and it is a viable approach for small applications and prototypes. The disadvantage is A slightly better approach to developing persistence that it tightly couples business classes with the schema layers is where the SQL statements for your business of your relational database. This would mean that a classes are encapsulated in one or more "data classes." simple change such as renaming a column may require (See Figure 2) Once again, this approach is suitable for a reworking of the code. In the above User example, prototypes and small systems of less than 40 to 50 busi- adding a column would require at least six changes to ness classes. This helps abstract things a bit more your code. The insert, update and select would need a because one or more domain classes can access a sin- change in the SQL plus each of the local variable gle data class. For instance, you could have the domain update routines. This would be multiplied by the num- classes 'user login' and 'user update' accessing a single ber of domain classes that accessed that table. One can user object. User login would simply call the user quickly see how maintenance mayhem can develop object's 'select' method with the userid and password with larger systems. set. If a row is found then the login object returns true,
Figure 2 - Hard-coding SQL in your separate date classes.
Class 1
Class 2 Class 1
Class 2 SQL
Class 3 RDB Class 3
Class 4
Data Classes Domain Classes
January 2003 · PHP Architect · www.phparch.com 12 FEATURES Implementing Database Persistence Layers in PHP
otherwise a false is returned. The user update would ed code. (See Figure 3) If we use the example above simply set all the object values and run the update of adding or removing a column in a table we can see method. how our job becomes somewhat easier. If you are The major disadvantage here is that SQL and object adding a new column to a particular object you do not update routines are still hardcoded. This means that have to change the three SQL statements and an adding or removing a column needs to have three or update routine in the code. Instead all that is needed more SQL statements changed along with the object is to update the one data object to include the extra updating routines. However, if modeled correctly, this local member and the persistence layer takes care of kind of update will only have to be done once per table the rest. All of a sudden, your once-frustrated PHP change. This was not the case in our previous example. developer has started dancing for joy at all the extra Previously, this kind of change had to be done for each time he has saved in making DB updates. This means domain class that accessed this table. So, for those more time to attend rave parties--or whatever it is that who need to access the same data in 32 different ways interests PHP developers these days. need to change 32 domain classes! Since most folks The main advantage of this approach is that your are happier to update one object instead of 32, this application programmers do not need to know a thing new approach makes for a more joyous PHP developer about the schema of the relational database. In fact, when DB changes are made. After all, no one likes a they do not even need to know that their objects are grumpy PHP developer! being stored in a relational database. This approach Other examples of this approach include developing allows your organization to develop large-scale, mission stored procedures in the database to represent objects critical applications. However, there is a performance (replacing the data classes of Figure 2) and Microsoft's impact to your applications--a minor one if you build ActiveX Data Object (ADO) "strategy". The best thing the layer well, but there is still an impact. that can be said about this approach is that you have at least encapsulated the source code that handles the Example Persistence Layers hard-coded interactions in one place: the data classes. This approach also helps keep SQL out of the domain Now that several approaches have been outlined at a classes, making them more readable. high level, we will present details of a particular imple- Unfortunately, not all database systems support mentation. This implementation aims to provide the stored procedures-this is particularly true of many robust persistence layer described above. It was devel- open-source servers like MySQL-and therefore this oped to separate the database layer from the business approach may not be suitable for your purposes. layer giving three distinct advantages. First, removing the hardcoded SQL makes the application easier to Robust Persistence Layer extend. Second, complex applications are more main- tainable because a lot of the data access code is central- A robust persistence layer maps objects to persistence ized in a single location. Finally, code in the business mechanisms in such a manner that simple changes to layer becomes cleaner and more readable. the relational schema do not affect your object-orient- In practice, it is difficult to build an efficient persist-
Figure 3 - Robust data persistence layer.
Class 1
Class 2
SQL
Class 3 Robust Persistance Layer RDB Class 4
Domain Classes
January 2003 · PHP Architect · www.phparch.com 13 FEATURES Implementing Database Persistence Layers in PHP
ence layer that will provide the developer with all the these functions can be used multiple times using a sin- mechanisms available in SQL directly . As such, this gle instance of the object. This means that during the implementation described does not support the com- lifetime of this object multiple updates can take place plete array of relational DB functionality abstractly. without recreating the object several times. This is Support for DB features like grouping, sorting and important for performance in situations where an insert internal DB functions can be added to this framework and many updates need to take place. but this entails extra processing which in turn will lead DBMultiObject represents a single row of two or to a greater performance hit. Also, the extra code more joined tables in the database. Due to the nature needed would cause the framework to use more mem- of this query it is a read only object and can only per- ory. As a result, this support has not been added into form selects. Generally this kind of limitation is not a the framework explicitly. problem as this kind of access is typically read only any- To avoid the use of "special case" SQL by a PHP devel- way. However, if a write is needed, the ids can be oper within the framework, we can opt to write SQL in obtained from the resulting select to create the appro- the business classes. If a true OO programming prac- priate DBObjects. Since at the end of the day this is tice was being adhered to this would not have to be really a join between two tables, a join clause must be done. However, this is a compromise between specified to join the tables appropriately. This unfortu- abstracting the DB away from the business class devel- nate necessity makes this object less of an abstraction oper 100% and developing a framework that is efficient and more complicated for the end developer. and lightweight. However, it provides flexibility and possible perform- There are basically three parts to this framework: con- ance gains over two separate queries. figuration, logging and the persistence layer itself. The The DBSetObject object is a utility class for using in configuration drives all the settings for this framework. set data. Although by itself this represents a single row It includes things like db connection info and logging in the database result, it can be used in conjunction parameters. The logging system is an extremely sim- with DBSet or DBMultiSet to provide a representation plified logging mechanism that outputs informational for multiple rows. DBSet is used to query multiple rows messages to a text file specified in the configuration. in a single table and DBMultiSet is used to query multi- The actual persistence layer is a set of objects to be ple rows in a multiple table join. Due to the latter, extended and code that dynamically generates the SQL DBSetObject is a read only object and supports select to persist object information via the database. operations only. Ideally, it would be able to support the same insert, update and delete as DBObject, but that One of the principal advan- would be beyond the scope of this article. tages of OO programming Implementation techniques over their older Now that you have an idea of how this possible archi- tecture might work, there's nothing like some good old procedural programming fashioned functional implementation examples to clar- ify things. These examples will illustrate how this ancestors is that they enable implementation can be used. Let's start with a couple of tables. For illustration purposes we have chosen user programmers to create mod- and address where one address can have many users ules Figure 5 Architecture Details CREATE TABLE users ( user_id INT PRIMARY KEY The actual implementation of the theory is likely to auto_increment, be of greatest interest to developers looking to use a password varchar(15) default NULL, persistence layer. Below in figure 4 is the class diagram first_name varchar(63) default NULL, last_name varchar(63) default NULL, for an implementation of a robust persistence layer. client_id varchar(63) default NULL, The most interesting classes are those classes that can address_id INT(2) be extended to create persistent data objects. Those ) TYPE=MyISAM; objects are DBObject, DBSetObject, and CREATE TABLE address( DBMultiObject. address_id INT(2), DBObject basically represents a single row in the street VARCHAR(30), database or a single instance of an object. As such, it city VARCHAR(30) has the ability to select, update, insert, and delete. All ) TYPE=MyISAM;
January 2003 · PHP Architect · www.phparch.com 14 FEATURES Implementing Database Persistence Layers in PHP
Listing 1 - user.php 1 DBObject(); 14 // Set the keys and fields 15 $this->log ( "Initializing Object as a Users" ); 16 $this->addKey ( USER_UID, "user_id", DB_STRING ); 17 $this->addField ( USER_PWD, "password", DB_STRING ); 18 $this->addField ( USER_FNAME, "first_name", DB_STRING ); 19 $this->addField ( USER_LNAME, "last_name", DB_STRING ); 20 $this->addField ( USER_CID, "client_id", DB_STRING ); 21 // Defing the table to be operated on. 22 $this->table_name = "Users"; 23 } 24 } 25 26 ?>
Figure 4 - Class diagram of example implementation
Persistance Layer Class Diagram
Bas e DBObje ct +Query : Query BaseDB +table_name : String +field_name[] : String +object_logger : Logger +key_name : String +field_type[] : String +join_clause : String +log(in msg : String) +addKey(in ind : Integer, in name : String, in type : String) +make_clause(in clause : String) : String +make_fields(in field_name : String) : String +addField(in idx : Integer, in name : String, in type : String) +setField(in idx : Integer, in value : String) +getFieldByName(in name : String) : String +getField() : String
DBSe t DBSe tObje ct DBM ultiObje ct +objectArray[] : String +objectItem : Object +getTableName() : String +select(in clause : String = "") : String[] +DBSet(in objectItem : Object) +getFieldNames() : String[] +retrieveSet(in clause : String = "") +getJoinClause() : String +getList() : String[] +getNew Instance() : Object
DBM ultiSe t DBObje ct +objectArray[] : String +objectItem : Object +DBMultiSet(in objectItem : Object) +select(in clause : String = "") : String[] +retrieveSet(in clause : String = "") +insert() +getList() : String[] +delete(in clause : String = "") +update(in clause : String = "")
Que ry +link_ID : Object +squery : String = "" +result : Integer = 0 Logger -query_logger : Object +logfile : String +log() : String +log() +squery(in query : String) : String[][] +fetch_row () : String[] +num_row s() : Integer +insert_id() : Integer
January 2003 · PHP Architect · www.phparch.com 15 FEATURES Implementing Database Persistence Layers in PHP
Listing 2
1 setField(USER_UID,1); 10 $user->select(); 11 12 // print out some info. 13 echo $user->getField(USER_FNAME)." "$user->getField(USER_LNAME); 14 echo "has the userid ". $user->getField(USER_UID) 15 16 // update a field and update save it to the database. 17 $user->setField(USER_UID,"newuserid"); 18 $user->update(); 19 20 // print out some info and notice the change. 21 echo $user->getField(USER_FNAME)." "$user->getField(USER_LNAME); 22 echo "has the userid ". $user->getField(USER_UID) 23 24 // delete that object from the database 25 $user->delete(); 26 27 ?>
(see Figure 5). in the 'where' clause. Passing in the clause breaks the The easiest thing one might want to do is obtain and abstraction of this layer but gives the developer the manipulate a single user. As mentioned above, ability to handle special cases. Listing 1 is an example DBObject gives the developer the ability to insert, of extended DBObject as the file user.php. update, select and delete. If these methods are called Using the object is relatively straight forward. A with no parameters, these actions will be performed select, update and delete looks like Listing 2. based upon the value of the key(s). However, the user As you can see here, we have done a select, update, has the option to overwrite this functionality by passing and delete with relatively few lines of code and no SQL.
Listing 3 - An example of the UserList extending DBSet in the file userlist.php 1 DBSetObject(); 14 15 $this->log ( "Initializing Object as a UserList" ); 16 17 $this->addKey ( USERLIST_UID, "user_id", DB_STRING ); 18 $this->addField ( USERLIST_PWD, "password", DB_STRING ); 19 $this->addField ( USERLIST_FNAME, "first_name", DB_STRING ); 20 $this->addField ( USERLIST_LNAME, "last_name", DB_STRING ); 21 $this->addField ( USERLIST_CID, "client_id", DB_STRING ); 22 $this->table_name = "Users"; 23 24 } 25 function getNewInstance() { 26 return new UserList(); 27 } 28 } 29 30 ?>
January 2003 · PHP Architect · www.phparch.com 16 FEATURES Implementing Database Persistence Layers in PHP
Listing 4 - Accessing data 1 retrieveSet( "where user_id > 0" ); 10 $ulArray = $userlist->getList(); 11 12 13 // print out some info. 14 foreach($ulArray as $key => $valueObj) { 15 echo "User's ID:".$valueObj->getField(USER_UID)."
"; 16 echo "User's First Name:".$valueObj->getField(USER_FNAME)."
"; 17 } 18 19 ?>
The business class developer has a very readable clean ed in Listing 4. set of code. In addition, developing further functional- Although this example has SQL, it is not necessary if ity using this object is very quick and easy. the desire is to retrieve all the rows from the table. Those of you who are familiar with this type of work Again, most of the details about how the data is being know that it is not always practical to retrieve one retrieved have been abstracted away from the develop- object at a time. It is often necessary to use a collec- er making the code simpler and more readable. If the tion of objects. This is often used for listing out infor- developer wanted to retrieve another list from the mation in the system. The DBSet and DBSetObject table, no new objects would need to be created, as the objects are used for this type of listing. For the userlist object could be reused again. moment these collections are read only so only the It is often desirable to obtain data from two or more select feature can be used. Listing 3 is an example of different tables during the same transaction. In some the UserList extending DBSet in the file userlist.php. cases it is possible to retrieve the required data with one Like DBObject, the select statement can be passed a access to the database. For performance reasons one 'where' clause to specify which rows to retrieve. query is usually preferred over two or more. This imple- However, if no clause is specified then this call will sim- mentation has taken this possibility into account, in ply retrieve all the rows in the table specified. Using the addition to queries across multiple tables. The object is a bit more complicated because the results are DBSetObject and the DBMultiObject allow users to returned in an object array. So accessing the data must specify multiple tables in the form of a join clause. An be done in an iterative fashion like the for loop illustrat- example of the DBSetObject being extended is shown
Listing 5 - An example of the DBSetObject being extended 1 DBSetObject(); 9 10 $this->log ( "Initializing Object as a UserMultiList" ); 11 12 $this->addKey ( USERLIST_UID, TU.".user_id", DB_STRING ); 13 $this->addField ( USERLIST_PWD, TU.".password", DB_STRING ); 14 $this->addField ( USERLIST_FNAME, TU.".first_name", DB_STRING ); 15 $this->addField ( USERLIST_LNAME, TU.".last_name", DB_STRING ); 16 $this->addField ( USERLIST_CID, TU.".client_id", DB_STRING ); 17 18 $this->addField ( USERLIST_CITY, TA.".city", DB_STRING ); 19 $this->addField ( USERLIST_STREET, TA.".street", DB_STRING ); 20 $this->join_clause = TU." LEFT JOIN ".TA." ON ".TU.". 21 user_id=".TA.".address_id"; 22 } 23 24 ?>
January 2003 · PHP Architect · www.phparch.com 17 FEATURES Implementing Database Persistence Layers in PHP
Listing 6 1 retrieveSet( "" ); 5 $ulMultiArray = $userMultiList->getList(); when they 6 7 foreach($ulMultiArray as $key => $valueObj) { 8 echo $valueObj->getField(USER_UID); let you touch it. 9 echo $valueObj->getField(USER_STREET); 10 } 11 Anyone can teach PHP. But getting 12 ?> your hands on the keyboard is the quickest and surest way for you to in Listing 5. le a r n everything from PHP and Like DBSet the retrieveSet method can be passed a MySQL to advanced topics like class- where clause to specify which rows to retrieve. es, objects, templates, and PDFs. However, if no clause is specified then this call will sim- Th a t ’ s what we do at TAPI n t e rn e t . ply retrieve all the rows in the table join specified. As You walk in. Sit down. Grab a before, accessing data must be done in an iterative ke y b o a r d. You walk out feeling confident that you can fashion like the for loop illustrated in Listing 6. handle anything the PHP/MySQL world can throw at you. As you can see, there is no SQL code in this listing. All the details of the data layer have been abstracted away FIV ED AY SO F PUR E PLE A S U R E . from the developer. Tap Internet provides everything you need: Hands-on building of dynamic web sites in a lab designed specifically Concluding Remarks for teaching. Eight hours of daily instruction for five full days. Over 40 hours of hands-on topics ranging from Hopefully, this article provides some insight as to why basic PHP to output buffering and template techniques. a persistence layer is useful as well as some insights to various implementations. This kind of implementation DIDW E NEG L E C TT O MEN T I O N FUN ? is not at all useful for a 'build-a-form-in-fifteen-minutes' Ev e r ything is designed to keep you motivated and kind of project. However, if you find yourself building le a r ning, including ‘Quick Challenges’ that give you a rea l l y larger applications with a complex set of logic in the good feel for how to use the language. It keeps things backend, this abstraction layer is invaluable in trying to in t e r esting. Heck, it keeps yo u in t e r esting, because you’re keep your application maintainable. interacting with other students as you learn. As shown in the example above, you can easily per- Scott Nichols from Shoe Carnival told us that what he sist objects using a database with little or no SQL and liked best was, “...the personal attention and ability to ask very little PHP code. This allows the developer to cre- questions ... I was treated as a guest.” ate applications that are maintainable and extendable. Not exactly what you’d expect from a geek, eh? Furthermore, faster development will be facilitated by abstracting away the complexities of persisting an LOGO N NOWT O LEA R N MOR E . object via a database. These advantages are best Want to master PHP/MySQL in a heartb e a t ?T h e n achieved using the third approach. Using frameworks beat it on over to http://www.t a p i n t e rn et.com/php and see like this will allow developers to build PHP applications how much more there is to TAPI n t e rn e t . that can quickly adapt to the changing requirements of Or give any of the guys a call: 1-866-745-3660. software. But do it now. The next course is about to begin.
Acknowledgments
I would like to thank Raymond Gigliotti for helping TAPI N T E R N E T produce some of the PHP code for the persistence layer example. Also, I would like to thank Nancy Lam for PH PC O U R S E S helping to better formulate my ideas for this article. HAN D S -ONT R A I N I N GF R O MT H EG E T -GO . CO-SP O N S O R E DB Y ZEND TEC H N O L O G I E S php|a Shawn Bedard is a senior architect based in Toronto, Canada. The Classes enrolling now. 1-866-745-3660 code he presents in this article is based on his database persistence layer ht t p : / / w w w. t a p i n t e rn e t . c o m / p h p / code available at https://sourceforge.net/projects/dbpl. You can reach Shawn at [email protected].
January 2003 · PHP Architect · www.phparch.com 18 January 2003 F E A T U R E S FEA T MemberName arguments may bepassed,oneforeach functions. Anynumber ofMemberT of whichisdefunctasPHP4.2.3: mers. and themyriadoflibrariesbuiltonittoPHPprogram- This extendsboththefeaturesofW functions andmemberobjectsofanyW (W sions, butanewexperimentalextension,w32api these featuresarenot(yet)providedforbyPHPexten- reading andwritingtheregistr file system,accessingnetworkingconfigurationand ulating windowsandgraphicalwidgets,accessingthe to per functions orobjects,similarconceptuallytoUNIX’ All intrinsicandmostthirdpartylibrariesforW Used todefineadatatype forusewithotherw32api bool The w32apiextensioncontainsonly5functions,one A TURES indows 32API)allowsPHPprogrammerstocallthe A spread acrossseveralDLLsallowingaprogrammer he W Using thew32apiExtension form anyW w32api_deftype indows APIprovidesacollectionoffunctions c P · PHP Architect c I indows task:constructingandmanip- a e ( String String String s L · www n s y andeventlog.Manyof i MemberName MemberType TypeName n .phparch.com d i n indows platform k advantage ofthemfromwithinPHP o , indows DLL. ) , g L ype and i ndows areDLLs(DynamicLinkLibraries).acompiledsetof By DavidJorm s .so(SharedObject)files.Thisarticleshowsyouhowcantake t t h i b h to theDLLisnotrequiredasthisprovidedby the nameofDLLcontainingfunction.Thepath other windowsDLLs.TheLibrar w32api_deftype() types, acceptedasargumentsofsomeW data types,theyareacollectionofvariablesdiffering member variableofthetype.Forthoseunfamiliarwith functions. type. may bepassed,oneforeachmembervariableofthe e Used toregisterfunctionsfromtheW Used tocreateaninstanceofadatatypedefinedwith resource bool REQUIREMENTS r PHP O/S: Additional Software: e r a V W w32api_register_function ersion: W indows D w32api_init_dtype r . 4.0 andabove String String String String i e y i . AnynumberofV N/A n s ReturnType FunctionName Library TypeName n d ( a , y argumentshouldbe , Mixed o ) m , a w ( lue arguments indows APIor Value i ndows API i c ) s 19 FEATURES Accessing the Windows API & other DLLs
DLL’s registry entry. Most Windows API functions have Three Log Files: Application, System and Security two names, one of which is an alias. When giving the The Event Log data is stored in seperate flat log files for FunctionName argument, the alias must be used. For each category of event. It is possible to add extra log example, you would use “MessageBeepA” instead of files representing different categories of events, but this “MessageBeep”. The ReturnType argument must be is not normally required. either string, long, int or bool. The Event Log Viewer: The Event Log Viewer is an mixed w32api_invoke_function ( administrative tool that ships with Windows NT, 2000 String FunctionName, and XP that is used to view, filter and manage the con- String FuncArgument) tents of the event log files. Defunct as of PHP 4.2.3, used to invoke a function registered with w32api_register_function(). Any number of FuncArgument arguments may be w32api (Windows 32 API) passed, one for each argument accepted by the Windows API function being called. Functions regis- allows PHP programmers to tered with w32api_register_function() are now available as normal PHP functions, called by the call the functions and member name with which they were registered, so this function objects of any Windows DLL is no longer required.
void w32api_set_call_method (Int Method) Windows API Functions: The Windows API exposes functions from advapi32.dll providing the program- Sets the call method used by the w32api extension. matic ability to read and write to and from the event The Method argument must be one of the constants log and to register and unregister event sources. DC_CALL_CDECL or DC_CALL_STD. DC_CALL_STD is the default. Binary Format Message Files: The messages given by each event source are defined using ASCII text in a To explore these functions, we will cover three exam- binary format message file. This is a DLL built by the ples: Visual Studio MC (Message Compiler), which automat- ically assigns numbers to each message and generates 1. A site logging security violations to the a table of the message text. The event logging func- event log tions provided by the Windows API use the messages 3. A page displaying windows system defined in this file to write the description of each event information to the event log. Message files allow for text in various 2. Enhancements to a command line languages to be set as the description of each event. application using the Windows API The event logging service will write the description to the event log in the language appropriate to the oper- Accessing the Event Log ating system’s native language.
The Windows platform contains an integrated log- Event Source Registry Entries: Each application or ging and log management framework called the Event service writing to the event log should have its own Log. The Event Log provides a standard, centralized event source. Event sources are defined in the registry mechanism for all applications to record software and by creating a subkey underneath: hardware events. When an error occurs, the system administrator must determine what caused the error, HKEY_LOCAL_MACHINE\System\CurrentControlSet\Serv attempt to recover any lost data and prevent the error ices\Event Log\{Log Name}\{Event Source Name} from recurring. It is helpful to this process if both the operating system and userland applications record sig- This subkey must have two values: nificant events. The system administrator can use the event log to help determine what conditions caused EventMessageFile: A REG_SZ value of the the error and the context in which it occurred. absolute path (environment variables allowed) to the message file DLL containing the event Event Log Design descriptions for this event source.
The Event Log is comprised of five key components: TypesSupported: A REG_DWORD value repre- senting which event types are supported by
January 2003 · PHP Architect · www.phparch.com 20 FEATURES Accessing the Windows API & other DLLs
this event source. This is a bitmask created by ORing one or more of the values shown in Building a Message File Figure 1. For example, Error, Warning and Information types have the value 0x0007. The first step to building a message file is to create an .mc file defining the message resource table. This is simply an ASCII text file with an entry for each event in Figure 1 the format shown in Figure 2. For our example web application, the .mc file should Event Type Value be as shown in Figure 3. Error 0x0001 Compiling this message file into a resource-only DLL (the most efficient kind) is then a three step process, Warning 0x0002 assuming the .mc file is named messages.mc:
Information 0x0004 1. Use the Message Compiler to create an .rc file from the .mc file using the command: Audit Success 0x0008
Audit Failure 0x0010 mc messages.mc
Figure 2 - .mc file format and description
Text Entry Purpose
# Comment Here Comments are preceded by #
Hexadecimal value of the Message ID MessageID=0x1
Severity of this event. Can be Error, Warning, Success or Severity=Warning Information
SymbolicName=WWW_AUTH_FAILURE Name of the event.
Language=English Language of the message description.
A user has failed to authenticate for the web application. Description of the event.
. Single period to terminate the message.
Figure 3 - message.mc file
MessageId=0x1 Severity=Warning SymbolicName=WWW_AUTH_FAILURE Language=English A user has failed to authenticate for the web application. . MessageId=0x2 Severity=Success SymbolicName=WWW_AUTH_SUCCESS Language=English A user has successfully authenticated for the web application. . MessageId=0x3 Severity=Error SymbolicName=WWW_AUTH_NOFILE Language=English The web application was unable to open the authentication file. .
January 2003 · PHP Architect · www.phparch.com 21 FEATURES Accessing the Windows API & other DLLs
This should create two files: Long NumStrings, Long DataSize, Long Strings, MSG00001.bin Mixed RawData) messages.rc long DeRegisterEventSource ( Long LogHandle ) 2. Use the Resource Compiler to create a .res file from the .rc created by the Message Compiler: The LogHandle argument of ReportEventA() must be a handle returned by rc -r -fo messages.res messages.rc RegisterEventSourceA(). The NumStrings, DataSize, Strings and RawData arguments are all 3. Use the linker to create a .dll file: used to provide strings of additional data with an event report. This data is shown in the Event Viewer as either link -dll -noentry -out:messages.dll messages.res bytes or DWORDs. This article only covers events with- out strings of additional data attached. Using these options will create a resource-only DLL. These are smaller and faster than normal DLLs. Finally, Putting It All Into a Class messages.dll should be copied to C:\WINNT\System32\. Since event logging is a clumsy process to replicate Creating an Event Source each time an event is reporting, we can simplify mat- ters by creating and event logging class, as shown in The next step is to link the message file DLL we have Listing 1. created to the name of the event source. This is done by creating a single key in the windows registry. Since the web application will want to log to the ‘Application’ Building The Authentication Page log with a source name of ‘WebApp’ this key will be: The final step is to construct a HTML form accepting HKEY_LOCAL_MACHINE\System\CurrentControlSet\Serv a user’s authentication credentials so we can authenti- ices\Event Log\Application\WebApp cate them and report the triggered events to the event The key will require values: log. This is done in Listing 2.
Name: EventMessageFile Console Enhancements Type: REG_SZ Data: %SystemRoot%\System32\messages.dll Although PHP contains intrinsic functions allowing Name: TypesSupported for the display and collection of data on a command Type: REG_DWORD line console, the Windows API can enhance this func- Data: 7 tionality for Windows console applications. API calls including message boxes and sounds can be used to %SystemRoot% will be substituted by the system’s create PHP console applications with the same interface root directory, by default C:\WINNT. This key can be and features of native windows console applications. added manually using regedit or by creating a .reg file and importing it into regedit. Neither of these tasks are Console Title within the scope of this article. Setting and retrieving the title of a command line Reporting Events console is one of the easiest tasks within the Windows API. Many functions require, as we have seen earlier, Reporting an event is a three step process, involving user defined types and constants to work, neither of registering an event source, reporting an event from which are required for this task. The Windows API that event source and, finally, deregistering the event exposes two functions from kernel32.dll used to set and source. These tasks are handled by three functions retrive a console title: exposed by advapi32.dll: bool SetConsoleTitleA (String Title) long RegisterEventSourceA (String ServerName, String SourceName) long GetConsoleTitleA (String TitleBUffer, Long BufferLength) long ReportEventA (Long LogHandle, Long Type, Long Category, There are two important points to note with these Long EventID, functions. The first point is that the first argument taken Mixed UserID,
January 2003 · PHP Architect · www.phparch.com 22 FEATURES Accessing the Windows API & other DLLs
Listing 1 1 hEventLog=RegisterEventSourceA(NULL, —WebApp“); 25 } 26 27 // Report Event Method 28 29 function reportevent($eventid, $logtype) { 30 $logtypefound=false; 31 32 // Match the string log type passed to a value from the array of constants 33 for ($i=0; $i
by GetConsoleTitleA() is a buffer to contain the $TitleBuffer = str_repeat(“ “, 255); string returned by the function, while the function’s return code is an indicator of success. When providing Secondly, when using SetConsoleTitleA(), the a buffer using a language with explicitly typed variables console title will only remain set while the program has such as C or Visual Basic, you must fill the buffer with control of the console. Once the program exits and space characters in order for it to be long enough to control returns to cmd.exe, the console title reverts to hold the required data. AlthoughPHP uses scalar vari- that set by cmd.exe. ables, the buffers must still be spaced out in orderto work with the Windows API. This can be done easily Sounds using str_repeat(). The following line of code would fill $TitleBuffer with 255 space characters: Basic waveform sounds can be played using the MessageBeep() function from user32.dll. This func-
January 2003 · PHP Architect · www.phparch.com 23 FEATURES Accessing the Windows API & other DLLs
Listing 2 1 2
3Authentication Failed
\n"; 24 25 // Instatiate an eventlog object, report the event and destroy the object 26 $el_obj = New eventlog(); 27 $el_obj->reportevent(1, "EVENTLOG_WARNING_TYPE"); 28 $el_obj->destructor(); 29 unset($el_obj); 30 } 31 } 32 33 function auth($u, $p) { 34 if ($u == 'testuser' && $p == 'testpass') 35 return true; 36 return false; 37 } 38 39 class eventlog { 40 41 // Properties 42 // Build an array of the log type constants and their corresponding values 43 var $log_types=array( 44 array("EVENTLOG_SUCCESS", 0), array("EVENTLOG_ERROR_TYPE", 1), 45 array("EVENTLOG_WARNING_TYPE", 2), array("EVENTLOG_INFORMATION_TYPE", 4), 46 array("EVENTLOG_AUDIT_SUCCESS", 8), array("EVENTLOG_AUDIT_FAILURE", 10)); 47 var $logtype; 48 var $hEventLog; 49 50 51 // Constructor 52 function eventlog() { 53 54 // Register w32api functions 55 w32api_register_function("advapi32.dll", "RegisterEventSourceA", "long"); 56 w32api_register_function("advapi32.dll", "ReportEventA", "long"); 57 w32api_register_function("advapi32.dll", "DeregisterEventSource", "long"); 58 59 // Register event source 60 $this->hEventLog=RegisterEventSourceA(NULL, "WebApp"); 61 } 62 63 // Report Event Method 64 function reportevent($eventid, $logtype) { 65 $logtypefound=false; 66 67 // Match the string log type passed to a value from the array of constants 68 for ($i=0; $iJanuary 2003 · PHP Architect · www.phparch.com 24 FEATURES Accessing the Windows API & other DLLs
Listing 2: Continued From Page 24... 72 } 73 } 74 if (!$logtypefound) 75 return false; 76 77 // Report the event 78 if (!ReportEventA($this->hEventLog, $this->logtype, 0, $eventid, NULL, 0, 0, NULL, NULL)) return false; 79 return true; 80 } 81 82 // Destructor 83 function destructor() { 84 // De register the event source 85 DeregisterEventSource($this->hEventLog); 86 } 87 } 88 89 ?> 90 91
106