1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Php | architect docx

73 324 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề PHP | Architect
Tác giả Rick Morris, Man-ping Grace Chau, Peter B. MacIntyre, Ilia Alshanetsky, Allen Smithee, Andi Gutmans, Marco Tabini
Trường học php|architect
Chuyên ngành PHP Development
Thể loại tài liệu
Năm xuất bản 2004
Thành phố Toronto
Định dạng
Số trang 73
Dung lượng 3,69 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

All the richness that you can find in a desktop application is absent: the form only refreshes upon submit, a lot more code is needed to make a dynamic UI, HTML cannot support ‘complex’

Trang 2

Certification Central

Trang 4

by Andi Gutmans and Marco Tabini

Managing Distractions and Engineering Abstractions

Practical Caching for the PHP Developer

TM

Trang 5

*By signing this order form, you agree that we will charge your account in Canadian dollars for the “CAD” amounts indicated above Because of fluctuations in the exchange rates, the actual amount charged in your currency on your credit card statement may vary slightly.

Choose a Subscription type:

CCaannaaddaa//UUSSAA $$ 9977 9999 CCAADD (($$6699 9999 UUSS**)) IInntteerrnnaattiioonnaall AAiirr $$113399 9999 CCAADD (($$9999 9999 UUSS**))CCoommbboo eeddiittiioonn aadddd oonn $$ 1144 0000 CCAADD (($$1100 0000 UUSS))((pprriinntt ++ PPDDFF eeddiittiioonn))

Your charge will appear under the name "Marco Tabini & Associates, Inc." Please allow up to 4 to 6 weeks for your subscription to be established and your first issue

to be mailed to you.

*US Pricing is approximate and for illustration purposes only.

php|architect Subscription Dept.

VISA Mastercard American Express

Credit Card Number:

Expiration Date: _

more information or to subscribe online.

Signature: Date:

php|architect

The Magazine For PHP Professionals

Subscribe to the print edition and get a copy ofLumen's LightBulb — a

$499 value absolutely FREE †!

Login to your account

for more details

EXCLUSIVE!

† Lightbulb Lumination offer is valid until 12/31/2004 on the purchase of a 12-month print subscription.

Trang 6

Graphics & Layout

php|architect (ISSN 1709-7169) is published twelve times a year by Marco Tabini & Associates, Inc., P.O Box 54526, 1771 Avenue Road, Toronto, ON M5M 4N5, Canada

Although all possible care has been placed in assuring the accuracy of the contents of this magazine, including all associated source code, listings and figures, the publisher assumes no responsibilities with regards of use of the information contained herein or in all associated material.

Contact Information:

General mailbox: info@phparch.com

Editorial: editors@phparch.com

Subscriptions: subs@phparch.com

Sales & advertising: sales@phparch.com

Technical support: support@phparch.com

Copyright © 2003-2004 Marco Tabini & Associates, Inc — All Rights Reserved

Ihave a confession to make I’m an XML-phobe I know, in today’s

soci-ety of political correctness and respect for other cultures, that’s nothing

short of inexcusable, but what can I say? I’m getting old and, therefore,

cranky.

When I first heard of XML a while back, I couldn’t help but thinking of

it as the answer to a question nobody asked This feeling was, in fact,

aug-mented by the continuous misuse of this outrageously verbose in all sorts

of places where it really didn’t belong Have a configuration file? Let’s

make it XML Need to store data? Why use a database—we have XML!

At the time, I was part of a team whose job was interfacing a

Microsoft-based web system to a legacy mainframe system, which, at the time, was

no walk in the park, as everything had to take place through a

carefully-choreographed exchange of text files I remember that, at some point, the

irony of it all struck me: here was a perfect scenario in which being able

to use XML would have been, at last, beneficial (although manipulating

text files with ASP was about as pleasant as stapling your lips together)

and, of course, there was no way I could have used it, because it would

have required too much work on the mainframe side On the other hand,

I had to use XML for pretty much half of the configuration files on the

Windows machine Lovely.

As time has gone by, the XML craze has somewhat faded to a more

rea-sonable level: we now use it for its intended purpose—the structure

com-munication of data between two or more heterogeneous systems—more

often than not It has become the basis of XHTML, whose importance is,

in my opinion, not in the beauty of a “well-designed” web page, but in

the fact that any robot should be able to parse XHTML, thus paving the

way for better search engines, more focused online advertising, and so on.

Still, despite (or, more probably, because) XML was designed to be a

human-readable format, manipulating an XML document “by hand” is

not fun—regardless of how good your particular platform is at handling

strings and arrays What it takes is a strong set of tools designed

specifical-ly to parse, modify and produce XML documents and are capable of

inter-facing with the underlying platform in a way that hides the minutiae of

the language from the developers

PHP 4 had what could be considered a germinal XML infrastructure, but

with PHP 5 we now have a robust toolset (despite a few kinks here and

there) that can be used to perform all sorts of XML manipulations—and

which will be indispensable to the introduction of PHP in an enterprise

environment that requires interoperation between a variety of different

systems

I had a taste of just how important this is to our readers during

php|works, when I sneaked into Ilia Alshanetsky’s session on PHP 5 and

XML… and had to leave because I couldn’t get a seat Once the

confer-ence was over, therefore, I had to ask Ilia if he wanted to write a

compa-rable article for the magazine; the result is this month’s main piece.

As usual, Ilia came through in style with an article that explores every

single facet of the functionality available in PHP 5 (with a quick look at

what was available in PHP 4), with plenty of practical examples and

Trang 7

Zend announces the PHP 5 Coding Contest Winners

Zend has released the names of the winners of the PHP 5 Coding Contest!!

“ It really wasn’t that easy to choose between the top applications; there are quite

a few that ended up in the top 20 or so that could just have easily been in the

top 6 Without your input, we’d still be arguing over them!

A special mention goes to MyObjects * , a project that provides its own persistent

object library and tools for generating classes directly from a MySQL database A

minor coding style issue was all that prevented the project from being one of the

top prizewinners The voters liked it too, and it ended up coming in 7th place.

Keep an eye out for the author, Erdinc Yilmazel of Turkey - we’d put money on

his winning next time, if there’s a next time!

Another special mention goes to Hive ** , which came in 41st because nobody in

the public domain voted for it We disagreed it ranked 3rd in the judges list

-so we’ve scrambled around to find a judges prize for the author, Robert

Janeczek Ironically, Robert describes Hive as ‘a low-level version of the PRADO

project’

Our judges and the public agreed over PRADO *** , which won outright All we

need to do now is get a laptop to Qiang Xue, the author of the winning

applica-tion, and then we can sit around in the office drinking too much caffeine and

playing hangman with a clear conscience “

For more information, and to try the winning software for yourself, visit

MySQL 4.1 can be downloaded now

guest-PHPX is a constantly evolving and changing Content Management System (CMS) PHPX is highly cus- tomizable and high powered all in one system PHPX provides content management combined with the power of a portal by including in the core package modules such as FAQ, polls, and forums PHPX uses dynamic-template-design, what this means is that you have the power to control what your site will look like.

Themes are included, but not required You can create the page however you want, and PHPX will just insert code where you want it.

No more 3 columns if you don’t want it! Written in the powerful server language, PHP, and utilizing the amazingly fast and secure database MySQL, PHPX is a great solution for all size website communities, at the best price possible free! “

Zend Encoder for MAC OSX Now Available

Zend has announced the release of Zend Encoder for Mac OS X.

“ The Zend Encoder is the recognized industry standard in PHP intellectual property

protection The Zend Encoder allows an unlimited number of PHP applications to

be distributed, while ensuring your investment and source code are protected

from copyright infringement.

Independent Software Vendors (ISV’s) and Professional Service Providers (PSP’s)

rely on the Zend Encoder to deliver their exclusive and commercial PHP

applica-tions to customers without revealing their valuable intellectual property By

pro-tecting their PHP applications, these and other enterprises expand distribution

and increase revenue.

The Zend Encoder compiles and converts plain-text PHP scripts into a

platform-independent binary format known as a ‘Zend Intermediate Code’ file These

encoded binary files are the ones that are distributed instead of the

human-read-able PHP files The performance of the encoded PHP application is completely

unaffected!

The Zend Optimizer, a free download, is the run-time environment that enables

end-users to transparently execute these files as if they were regular PHP scripts.

The Zend Optimizer not only provides an additional level of increased security

against reverse engineering, it also improves performance speed “

For more information visit: www.zend.com

Trang 8

Apache HTTP Server 1.3.33 Released

From Apache.org:

“ The Apache Software Foundation and The Apache HTTP Server Project are pleased to announce the release of version 1.3.33 of

the Apache HTTP Server (“Apache”) This Announcement notes the significant changes in 1.3.33 as compared to 1.3.31 (1.3.32

was not formally released) The Announcement is also available in German and Japanese

This version of Apache is principally a bug and security fix release A partial summary of the bug fixes is given at the end of this

document A full listing of changes can be found in the CHANGES file Of particular note is that 1.3.33 addresses and fixes 2

potential security issues: CAN-2004-0940 * Fix potential buffer overflow with escaped characters in SSI tag string And

CAN-2004-0492 ** Reject responses from a remote server if sent an invalid (negative) Content-Length

We consider Apache 1.3.33 to be the best version of Apache 1.3 available and we strongly recommend that users of older

ver-sions, especially of the 1.1.x and 1.2.x family, upgrade as soon as possible No further releases will be made in the 1.2.x family.

Apache 1.3.33 is available for download from http://httpd.apache.org/download.cgi

* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0940

**http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0492

PostNuke Security Alert

Postnuke.com has posted a new security alert regarding a Hack into the the ZIP archive of PostNuke 750

“ We discovered last night that http://downloads.postnuke.com was the target of a malicious attack and files in the ZIP archive

of PostNuke 750 were changed Immediately upon discovering this all links to the downloads section were removed and on

Tuesday the 26th at 8:30 GMT the original download package was restored.

Our investigations so far have revealed the attack was initiated on Sunday, 24.Oct, at 23:50 (11:50 PM) GMT The attacker used

an exploit in the download management software pafiledb to change the download address of PostNuke-0.750.zip to point to a

compromised archive We must stress this is a security compromise of paFileDB and has nothing to do with the PostNuke

appli-cation.

Note, if you downloaded the tar.gz archive you are not affected so you do nothing, only those who downloaded the zip version

were affected and must take immediate action as detailed below.

The changes made by the hackers were in two places First, during the installation routine all data submitted (this includes the

server, the database credentials, the admin name and password) is sent to a different server Second, in one file there was code

allowing a malicious user to execute any shell command on the web server.

As noted before, immediate action is required from everyone who downloaded the zip package between Sunday (24.Oct) at

23:50 GMT until Tuesday (26.Oct) at 8:30 GMT “

For more information visit: news.postnuke.com

Take Advantage of Marco’s Wonky Math and Save Up to $80

Our fall/winter 2004 subscription campaign is in full effect—and this year we have some great offers for all our scribers, regardless of whether you’re becoming a member of our family for the first time or if you’re been looking forward for your copy of php|a since the very beginning.

sub-Signing up for a php|a subscription (or adding another 12 months to your existing one) right now means some great offers, which include:

• A $80 discount on the Zend Certification Guide

• A free 64MB USB Memory Key, complete with the php|architect logo

For more information, visit our website at http://www.phparch.com/wonky

Errata

In last month’s Tips & Tricks column, John mentioned that a reader had pointed out a small flaw in his random-line access

algo-rithm In true php|architect fashion, we misspelled his name—quoting him as Chris Cowell, while his real name is Chris Dowell Sorry, Chris!

Trang 9

Looking for a new PHP Extension? Check out some of the lastest offerings from PECL.

WinBinder 0.27.093

WinBinder is an extension that allows PHP programmers to build native Windows applications It wraps a limited but important subset

of the Windows API in a lightweight, easy-to-use library so that program creation is quick and straightforward.

Parsekit 1.0

This package provides a userspace interpretation of the opcodes generated by the Zend engine compiler built into PHP.

This extension is meant for development and debug purposes only and contains some code which is potentially non-threadsafe.

Imlib2 0.1

imlib2 is a very fast image manipulation library, but without the support for as many image formats as other libraries such as

imagemagick.

You will need the imlib2 library from http://sourceforge.net/projects/enlightenment/ in order to compile this extension.

This extension is experimental It's been tested on a number of Linux installs, but nothing else Please report any bugs to the

main-tainer!

Translit 0.1

This extension allows you to transliterate text in non-Latin characters (such as Chinese, Cyrillic, Greek etc) to Latin characters Besides the transliteration, the extension also contains filters to convert to upper- and lower-case words in Latin, Cyrillic and Greek, and per- form special forms of transliteration, such as converting ligatures such as the Norwegian "ÃE" to "ae," as well as normalizing punctua- tion and spacing.

Check out some of the hottest new releases from PEAR.

PHPUnit 2.1.2

PHPUnit is a regression testing framework used by the developer who implements unit tests in PHP.

DB_odbtp 1.0.2

DB_odbtp is a PEAR DB driver that uses the ODBTP extension to connect to a database.

It can be used to remotely access any Win32-ODBC accessible database from any platform.

Mail_mbox 0.3.0

This extension can split messages inside an Mbox, return the number of messages, return, update or remove a specific message, or

add a message to it.

I18Nv2 0.9.1

This package provides basic support to localize your application, like locale based formatting of dates, numbers and currencies.

It also attempts to provide an OS-independent way to sseettllooccaallee(()) and aims to provide language and country names translated into many languages It provides these classes:

• I18Nv2-OS-independent (Linux/Win32) sseettllooccaallee(()), other utilities

• I18Nv2_Locale-locale based formatter

• I18Nv2_Negotiator-HTTP negotiation of preferred language and charset

• I18Nv2_Country-multilingual list of country names

• I18Nv2_Language-multilingual list of language names

• I18Nv2_Charset-list of common and not so common charsets and aliases

• I18Nv2_AreaCode-list of international area codes (phone)

Stream_Var 1.0

Stream_Var can be registered as a stream with ssttrreeaamm rreeggiisstteerr wwrraappppeerr(()) and allows stream-based access to variables in any

scope Arrays are treated as directories, so it's possible to replace temporary directories and files in your application with variables.

Trang 10

Distractions Abound

Apparently, a few of our loyal readers have been

won-dering just when Part II of this series would come out,

or whether it had vanished into the //ddeevv//nnuullll

bitbuck-et Please bear with me; since writing that first article I

have gone through three South Florida hurricanes and

the birth of my second child (a boy!) So, suffice it to

say that there have been a few distractions in my life

But, in the best tradition of making lemons into

lemon-ade, let’s think about what distractions can teach us

Foremost, I would have to say that they highlight the

need to think clearly and accomplish as much as

possi-ble in the shortest possipossi-ble time (and if my parents had

known when I was 16 that I would grow up to write a

line like that, they would truly believe in miracles)

With that in mind, let’s think about how databases

help us manage distractions I have a very small

synop-sis of what the relational model of data affords us: the

ability to name things in order to control them That may

seem a tad simplistic, but think about it: relational

data-bases give us the ability to apply a distinct and clear

name with a value attached to everything—and, most

importantly, they don’t require any other mechanism

than a simple declaration of the named element and its

attributes in order to retrieve the associated value In

other words, you don’t need to think about “the

infor-mation in column #2 of row #34,” or “the eeyyee ccoolloorr

field is in column #4 of this table.” Instead, the

mecha-nism for accessing your data simply is the statement of

what you are looking for “Get all eeyyee ccoolloorr values for

employees born before 1968” can be directly

translat-ed into SSEELLEECCTT eeyyee ccoolloorr FFRROOMM eemmppllooyyeeee WWHHEERREE

eemmppllooyy eeee bbiirrtthhddaayy >>== ‘‘11996688 0011 0011’’;; The fact that most base systems also allow you to ask for the data on row

data-#34 and the value in column #2 should be regarded as

a nuisance rather than a feature, if you truly follow theprinciples of relational database design

Distractions also teach us that abstraction helps us

manage the organization of our lives If we had to thinkabout every single step we took, we would be prettyfrustrated by the end of the day, but our bodies allow

us to abstract that into a general concept called ing.” Thus, rather than thinking about moving our feet

“walk-up and down in the exact steps we will have to take inorder to get to the refrigerator, we just decide to walk

to the refrigerator, and let the abstraction take over(believe me, with a wife, a 4-year-old and a newborn, Ihave been doing a lot of walking to the refrigeratorlately) In the same way, both relational database sys-tems and object-oriented programming allow us to cre-ate abstractions that save us time in the future Theyjust do so in different ways

What’s wrong with this picture?

As we discussed in Part I, one of the biggest distractions

in modern programming is the “object-relational

by Rick Morris

PHP: 4.x+

OS: Any Other software: PostgreSQL version 7.4+

Code Directory: relational

REQUIREMENTS

To many object-oriented developers, there is a sense that

the relational model for data management is at odds with

the concepts of object-oriented development Are these

views justified? Are they practical? In part II of this

two-part series, we build a simple example of an

object-orient-ed application that derives business logic from the

data-base without object/relational mapping.

Managing Distractions and

Reverse-Engineering

Abstractions

Trang 11

impedance mismatch.” For example, let’s look at a

basic SQL query and online form that a PHP developer’s

apprentice might create Our developer has been wise

in taking advantage of abstraction, so she uses the PEAR

HHTTMMLL QQuuiicckkffoorrmm class to generate the form for a simple

user signup script (see Listing 1) It is, undoubtedly, a

nice choice—and kudos to our aspiring guru for taking

the time to read, instead of just hacking a quick-n-dirty

HTML form with interspersed PHP We will, for the

moment, assume that $$ddbb is an instance of a database

abstraction class with nice methods like ccrreeaattee eennttrryy(())

and llaasstt eerrrroorr(())

This example might look nice, clean and readable—

really a pleasure to look at if you are tired of the

spaghetti code littering many web-based applications

So what’s wrong with it? Well, just think about what

has to be done if you have to modify the database: your

developer will have to modify every script that interacts

with the table and other DB structures that have been

changed Amazingly, this is the expected—and

accept-ed—state of affairs for most application programming

out there, especially in the area of web-based software

The benefits of the relational model are often seen to

be at odds with the capabilities of Object-oriented

Programming While the relational model is based on

set-oriented thinking, which presents a unified logical

method of accessing and modifying all kinds of data,

object-oriented programming provides a metaphorical

approach to data and essentially uses custom functions

to bundle behaviors with it While at first it seems

logi-cal that one would just develop objects in parallel with

the tables in one’s logical database design, we saw that

this leads to a fundamental problem: you inevitably end

up duplicating effort, as you slavishly model one ronment to follow the other

envi-Really, the best parallel to objects and behaviors inthe relational world could be datatypes and operators.Think about it The real objection is that datatypes areseen as “scalar” and “primitives,” but there is actuallynothing in the relational model itself that preventsdatatypes/domains from being complex, composite, oreven customized by the user, along with customizedoperators This begs the question, however, since mostdatabase systems don’t have a truly comprehensiveway to deal with custom datatypes However, we can atleast take a step in that direction with the use ofdomains

A Note on Terminology:

Since this is an attempt at a serious look at what can beaccomplished by programming in accordance with therelational model, we will use relational terminology.Rather than “datatype”, we will refer to “domain” and,rather than “table,” we will use the term “relation”.There is a good reason for this: we should be able totreat custom domains the same way as baseline scalardatatypes like IInntt and, in fact, a domain is simply the

“set of all possible values” for a certain term (thinkabout your high school algebra) Also, a table is a rela-tion, but so is a view (in fact, so is the result set fromany query or stored procedure) The point here is thatthere is a decided advantage to our programming

front-end if we don’t make distinctions between

datatypes and custom domains, or between tables and

views Your application front-end has noreal need to know the underlying design

of your database, but simply what is sented to it by the developer Also, since

pre-we are discussing an object-orientedframework for PHP as it interacts withrelational databases, every classname willhave the prefix RReell This is especially nec-essary since PHP—even version 5—doesnot have namespaces

What would happen, though, if we did

associate every datatype in our DBMS(along with custom domains and com-posite types), to a class in our program-ming framework? Of course, there wouldstill have to be some work done to tie inthe application framework with the data-base, but it would not have to be associ-ated with specific business logic, focusinginstead on more generic, abstract con-cerns—the perfect case of code reuse, ifyou will

Now, what would happen if youdesigned other classes “by composition

7 $form = new HTML_QuickForm ( ‘user_signup’ , ‘get’ );

8 $form -> addElement ( ‘header’ , ‘’ , ‘New User Sign-up’ );

9 $form -> addElement ( ‘text’ , ‘username’ , ‘Username’ );

10 $form -> addElement ( ‘password’ , ‘password’ , ‘Password’ );

11 $form -> addElement ( ‘text’ , ‘firstname’ , ‘First Name’ );

12 $form -> addElement ( ‘text’ , ‘lastname’ , ‘Last Name’ );

13 $form -> addElement ( ‘text’ , ‘email’ , ‘Email Address’ );

14 $form -> addElement ( ‘reset’ , ‘btnClear’ , ‘Clear’ );

15 $form -> addElement ( ‘submit’ , ‘btnSubmit’ , ‘Submit’ );

16

17 $form -> addRule ( ‘username’ , ‘Your username is required’ , ‘required’ );

18 $form -> addRule ( ‘password’ , ‘Your password is required’ , ‘required’ );

19 $form -> addRule ( ‘email’ , ‘Your email address is required’ , ‘required’ );

Trang 12

rather than inheritance” to automatically “know” what

to do when presented with a specific table, query, or

other database construct, given that you already have a

class that parallels each datatype? Are these just

rhetor-ical questions? Not really

If you think this through a little, you’ll find that the

concept we presented in the last article hints exactly at

this type of solution In other words, rather than the

peculiarly brittle approach of creating a parallel class for

every table, we instead opt to model orthogonal

con-cerns, leaving us much freer to change one aspect of

the system without changing another Now, if we want

to change the way our application deals with

autonum-bered primary key columns, for example, we just have

to change it in one place, instead of many Adding

val-idation capabilities to our front-end is not such a

frus-trating experience anymore

If you use domains, you have even more control For

example, if you decide that wherever the “zipcode”

domain is used as a column definition, you want the

application to present it in the Courier font, it is a

one-time change (I’m sure you can imagine far more usefulways of applying this approach to your own applicationproblems)

Of course, in order to do this sort of thing, you notonly need a class for every domain, but you also need

a way to “reverse engineer” every relation that you aredealing with, in order to get the metadata for columndefinitions, datatypes used, primary keys, and so on

“What a huge task,” you might be thinking.Fortunately, most of this work has already been donefor you; if you use either MySQL or PostgreSQL, youwill easily realize that phpMyAdmin and phpPgAdminhave code that accomplishes all of the above—andmore In fact, there is one such application for theFireBird SQL engine as well (IBWebAdmin), and evenone for Oracle (phpOracleAdmin) You can think of thisreverse engineering to be similar to the concept of

“reflection” as used in programming languages toreverse-engineer functions, classes, and objects in orderfor a program to “understand itself” and modify itsbehavior according to rules set by the programmer

23 $this -> relation = $relation ;

24 //$this->dbconn = $this->relation->dbconn; //share the

same database connection already established in the $relation

32 $valid_modes = array( “list” , “view” , “edit” , “add” ,

“insert” , “update” , “search” );

33 //view, list, edit, etc

34 if( in_array ( $mode , $valid_modes ))

44 //if mode is not ‘list’, it is implied that we

are in single-record view/edit mode

45 $this -> gui = new HTML_QuickForm ( { $this ->

rela-tion -> relname } , ‘POST’ );

56 function prepare ()

57 { 58

59 $this -> metadata = $this -> relation -> get_metadata ();

73 if( class_exists ( $classname ))

75

76 //compose column types in here

77 $this -> data [ $colname ] = new $classname ; 78

82

83 //default to char domain

84 $this -> data [ $colname ] = new rel_text ; 85

92 function render ()

93 { 94

95 $this -> relation -> do_select ();

Trang 13

The more advanced ANSI-compliant systems such as

PostgreSQL have a very easy way to query metadata

through SQL (in PostgreSQL you query tables and

views in the iinnffoorrmmaattiioonn sscchheemmaa schema/namespace)

Armed with the tools above to extract metadata, we

can easily construct a very basic system to present an

example of these ideas: first, we create a basic

“inter-face” class called RReellDDoommaaiinn, then a class for each

domain/datatype—for now, we’ll limit ourselves to

RReellIInntt, RReellFFllooaatt, RReellCChhaarr, RReellTTeexxtt (Listing 2 - found in

this month’s code package) Next, we create a class

called RReellaattiioonn (Listing 3 - found in this month’s code

package), which will be composed of all domain

objects needed for any specific relation It also

incorpo-rates whatever methods are needed to extract

metada-ta from the given relation

Now, this is one aspect of how to combine an

object-oriented application framework with a relational

data-base system It deals with your datadata-base at the scopic level What about dealing with your database onthe macroscopic level? What if you could just “throw”

micro-a tmicro-able nmicro-ame micro-at micro-a certmicro-ain clmicro-ass or group of clmicro-asses, micro-andhave the application just read the table metadata,instantiate the right objects for each datatype in a col-umn, and automatically build your form? If this soundslike a too-good-to-be-true theoretical approach, justthink about it a moment: if you have a class for everydatatype, as well as classes to handle all the “mechani-cal” aspects of connecting to the database, querying,retrieving data, and so on, then all you need is a class

or set of functions for retrieving table/view metadataand some methods for tying these classes together into

a logical interface for the database Finally, we will have

a class called RReellGGuuii (Listing 4) to handle the displayand user interaction RReellGGuuii can inherit from someexisting classes, such as PEAR’s HHTTMMLL QQuuiicckkFFoorrmm, andHHTTMMLL TTaabbllee (and many additional helpful PEAR classes,

if you wanted it to) The whole idea here is that yourentire application can pass every database interactionthrough a dispatch file that looks essentially like the oneyou see in Listing 5, with the classes in the listings men-tioned above In addition, the code in Listing 6 tiesthem together as required files Of course, as I men-tioned earlier, PEAR’s HHTTMMLL TTaabbllee and HHTTMMLL QQuuiicckkffoorrmmare required

Briefly, here is what is going on in these files:

• When a browser request is made to Listing

5, at a minimum, the GET parameters forrreellnnaammee and mmooddee need to be passed as part

1 <?php

2

3 /* file: relpage.php */

4

5 include ( ‘./relfiles.php’ ); //include Domain.php, all

datatypes, and Relation.php

31 $gui -> set_mode ( $_GET [ “mode” ]); //valid modes are “list”,

“view”, “edit”, “add”, “insert”, “update’, “search”

Trang 14

capa-of the URL This tells the program what

rela-tion to deal with, and how we want to

inter-act with the relation Valid modes (for now)

are lliisstt, vviieeww, eeddiitt, and sseeaarrcchh In “list”

mode, the table will be queried, and the

data output as rows

• When the user clicks an “edit” link on one of

the rows, the page re-draws itself in “edit”

mode, using URL-encoded arguments

passed in the link to provide enough

infor-mation for the WWHHEERREE clause in SQL A form is

then drawn, based on the relation metadata(column definitions) and the values for eachcolumn in the fetched row The user canthen edit the row and submit the new val-ues

To look a little deeper, the code in Listing 5 first tializes a new RReellaattiioonn object, based on the rreellnnaammeeparameter, and then passes a database connectionidentifier to it The Relation object prepares the meta-data for the given table/view Then, the code initializes

ini-a new RReellGGuuii object ini-and pini-asses the RReellini-aini-attiioonn object to

its constructor The appropriate mode

is passed as well, so that rreellGGuuii canautomatically know how to display thedata If the mode is lliisstt, for example,then the page looks like Figure 1 If themode is eeddiitt, RReellGGuuii automaticallyknows to create an editable form (asyou can see in Figure 2)

Inside Listing 3, you will see that,after extracting the basic metadatawith ppgg mmeettaa ddaattaa(()), we loop throughthe basic information to first create therelated object for each domain—andthen run some more sophisticatedqueries in PostgreSQL to get furthermetadata We take advantage of PHP’svariable classname calling on lines 68and 75 of Listing 4 to create ourdomain/datatype objects, thus allow-ing RReellGGuuii to derive hints on presenta-tion, and other aspects of the GUI Ofcourse, it is clear that we could do thiswithout creating the custom RReellDDoommaaiinnclasses, but then we would lose much

of the ability to add extra behavior todifferent column types To further illustrate the idea of how we can affect any area of the system through this, uncomment $$tthhiiss

>>sseettCCssssSSttyyllee((aarrrraayy((‘‘ccoolloorr’’==>>‘‘rreedd’’))))

in the rreell iinntt class stored on line 43 ofListing 2 Now, any integer type col-umn will display in red (the new stylewill be added to the fourth parameter

of HHTTMMLL QQuuiicckkffoorrmm’s AAddddEElleemmeenntt call inListing 4) There are many more thingsthat can be added this way, if you want

to play around with this concept,including additional HTML attributes,Javascript event handlers, and so on

What About MySQL?

You might be wondering how you canimplement these concepts if you are

F

FE EA AT TU UR RE E Object-oriented vs Relational Part II

Figure 1

Figure 2

Trang 15

using MySQL While it is true that MySQL offers far less

functionality, lacking views, constraints, and domains,

than other DBMSs, it is precisely our sort of framework

that can help overcome some of these difficulties For

example, if you exercise a certain amount of discipline

in table design, you can “fake” domains by naming

columns after PHP classes you have created, and use

the column names as you reverse-engineer your tables

This way, if you have a column named “zipcode”, you

can assume that it corresponds to your rreell zziippccooddee

class in PHP Also, you could compensate for the lack of

views by creating a class that maintains a lookup table

with a list of names, and associate them with stored

queries, and uses the metadata functions in the

RReellaattiioonn class to return all the column definitions for

these “views” Similarly, you could maintain a lookup

list of constraints expressed in PHP which apply to

cer-tain tables, column names, and so forth The same

could also apply even more to SQLite, or other

light-weight database engines It’s a win-win situation

Garbage Collection: A Few Final Notes

Of course, a perfectly valid complaint about this sort of

approach is “what about efficiency?” Don’t all these

extra classes and methods present a serious

perform-ance problem? It’s possible As a general rule,

hard-cod-ing can lead to increased performance, and that would

apply to how we build our forms and interact with the

database However, as usual again, this comes at the

price of flexibility and manageability (or “developer

performance”) Which is cheaper, computer

perform-ance or your performperform-ance as a programmer? If you

want these advanced capabilities but are worried about

performance consider three things: first, the code

pre-sented here is not optimized; there should be plenty of

ways—especially with PHP5—to get better

perform-ance Second, there are several good PHP optimization

systems, such as the Zend Optimizer and Zend

Accelerator, as well as the Ioncube Accelerator and the

PPEECCLL::::aappcc extension, for example, and Third, computer

hardware is really cheap these days It would probably

cost less than a week’s wages to upgrade a server

sig-nificantly in performance

Therefore, performance concerns notwithstanding, in

the end we have an interesting situation We are using

quite a few of the concepts of object-oriented

program-ming: inheritance, encapsulation, aggregation, and

composition, without once infringing on the database’s

handling of business logic Now I agree that this small

example of coding here is incomplete (it is up to the

reader, for example to implement the

insert/update/search modes), and the data

presenta-tion leaves much to be desired In order to really create

a seamless whole between the hardcore logic

manage-ment in the database and the interactivity/presentation

of the application layer, one would probably need ten

118 $escaped_args = urlencode ( serialize ( $row ));

//argumenst to uniquely identify a row

119 $this -> gui -> setCellContents ( $rownum , $colnum ,

“<a href= \”{ $_SERVER [ “PHP_SELF” ]} ?relname= { $this -> relation -> name } &mode=edit&arguments= { $escaped_args }\” >edit</a>” );

136 $this -> gui -> addElement ( ‘header’ , ‘’ , “Edit

{ $this -> relation -> relname } );

137

138 $row = $this -> relation -> fetch_row ();

139 140

141 foreach( $row as $colname => $colval )

143

144 $html_attribs = array( “value” => $colval );

145

146 //additional HTML attribs are set here

147 if( is_array ( $this -> data [ $colname

]-> css_attribs ))

149 $html_attribs = array_merge ( $html_attribs ,

$this -> data [ $colname ]-> css_attribs );

151 if( is_array ( $this -> data [ $colname ]-> css_class ))

153 $html_attribs = array_merge ( $html_attribs ,

$this -> data [ $colname ]-> css_class );

155

156 //set max size attribute for textboxes

157 if( $this -> metadata [ $colname ][ ‘len’ ] > 0 )

174 } Listing 4: Continued from page 11

Trang 16

times as much code as we have here This article,

how-ever, provides a basic prototype on how to handle this

sort of thing Again, PEAR can come to our rescue in

handling more sophisticated presentation and

interac-tion needs, with such classes as the following:

With these classes and the concepts presented in this

article, one could construct a very sophisticated set of

tools, not only for an application framework, but even

for an application development framework Think about

the possibilities of creating something what would be

like the web-based version of commercial systems like

Access, Paradox, or FileMaker Pro In one sense, our

tools could be even better, because the forms could

correctly adjust themselves to changes in the database,

which is something even the commercial tools

men-tioned above don’t really handle properly Where this

sort of approach can really shine, though, is in the ation of large enterprise applications, where theremight be several development teams, database admin-istrators, and sysadmins Imagine being on the phonewith the database administrator saying “sure, go aheadand make that change, then see what the form lookslike” and wondering what the look on his face looks like

cre-as he hears you speaking!

F

FE EA AT TU UR RE E Object-oriented vs Relational Part II

About the Author ?>

To Discuss this article:

http://forums.phparch.com/181

Rick Morris heads application development for MOS Imaging Systems in Miami, Florida (w www.mos.us s, w www.netcompass.us) He lives near Fort Lauderdale, Florida with his wife, 2 children, and the world’s laziest cat.

Available Right At Your Desk

All our classes take place entirely through the Internet and feature a real, live instructor that interacts with each student through voice or real-time messaging.

What You Get

Your Own Web Sandbox Our No-hassle Refund Policy Smaller Classes = Better Learning

Sign-up and Save!

For a limited time, you can get over $300 US in savings

just by signing up for our training program!

New classes start every three weeks!

http://www.phparch.com/cert

Trang 18

Most XML generators are desktop applications—you

can drag-and-drop beautiful GUI nodes to build a DOM

document The XML generator introduced here is a

web application All the richness that you can find in a

desktop application is absent: the form only refreshes

upon submit, a lot more code is needed to make a

dynamic UI, HTML cannot support ‘complex’ data

structures like DOM, the browser cannot maintain

state, and so on Would a web XML generator

imple-mented in PHP be able to overcome all these

con-straints?

This generator was developed in the Infospheres Lab

at the California Institute of Technology to help users

generate state/transformation files for a crisis

manage-ment system The states inside the system are described

by XML files During an event, an agent changes its

state in ways described by XSL files For more details

about the crisis management system,

you can refer to the Infospheres web site at

w

www.infospheres.caltech.edu Making this XML generator

a web application has the advantage of being

light-weight—the client only needs an Internet connection

and a browser to use the service, thus it is platform

independent The server can also keep track of all the

files generated and save copies As with all web

appli-cations, efficiency is always the first priority to ensure

performance and reduce server workload

Let’s understand how it works by looking at a fire

accident scenario The initial state is ‘at peace’: state

name – normal; dead – 0; injury – 0; police – sleep; fire

station – sleep; and so on By putting all these values

into the generator (Figure 1), the corresponding XMLfile (Figure 2) is generated A message will be delivered

to the system when a fire breaks out, indicating the ‘fireagent’ should change its state The transformation rulefor this transition (e.g.: if the number of injuries stated

in the message is greater than four, the state nameshould change to ‘critical’) is specified in the XSL gen-erator (Figures 3 and 4) to generate the correspondingXSL file (Figure 5) The flowchart of the entire genera-tor is shown in Figure 6 As you can see, different XSLfiles will be invoked upon different events; for example,hhaannddlleettiimmeeoouutt xxssll will be invoked during timeout

UI that represents a changing datasetwith complex data structure

Initially, there are only four nodes under the root node

in the XML generator (Figure 7) A new input form ismade when the user modifies this structure (Figures 8and 9) The user interface is dynamically generatedafter every refresh/submit, based on the different

‘states’ (which consist of datasets) In addition, we have

to maintain ‘state’ change, which is based on the vious ‘state’ and the user’s modifications You shouldimmediately think of MVC (Model/View/Controller)

Code Directory: xmlgen

REQUIREMENTS

Developing a UI that manipulates large data sets is difficult Developing a UI dynamically upon user request is even more difficult This article aims to discuss the difficulties in developing a complex UI, demonstrated by the XML/XSL genera- tor made in the Infospheres Lab at the California Institute of Technology Examples of how to generate JavaScript dynam- ically at run time and how to represent a complex DOM tree with simple HTML data structure will also be shown Furthermore, the article will discuss the optimization of input validation Several error checking/correction algorithms will

be demonstrated This application is developed in PHP5, with extensive use of the new XML library.

Trang 20

devel-here: the Model encapsulates the

‘states’; the Controller interprets theuser’s input, modifies the ‘states’ in theModel and chooses a new View; theView generates the UI based on thedatasets in the Model (Figure 10) Themain focus here is the datasets:

in order to make an efficientModel/View/Controller, the datasetshould be easy to manipulate Thereare already many articles about theMVC design pattern; you can refer tothe book Design Patterns by ErichGamma, Richard Helm, Ralph Johnsonand John Vlissides or to Jason Sweat’sarticles that have appeared on thepages of php|architect for more infor-mation

By just looking at the form, it seemsthat appending a child is as simple asadding one more row to the table It is,indeed, easy to manipulate a table—but this is only half of the picture Thistable actually represents a DOM treeand the rows are the child nodes at dif-ferent levels (you can see in Figure 11how the node level is indicated in theinput table) Thus, the dataset should

be a DOM document, with its structurespecified by the user The problem aris-

es that HTML does not support plex data structures like DOM, andthere is no way to POST a DOM node.The ‘most complex’ data structure sup-ported by HTML POST is an array Insolving this problem, we retrieve theuser’s input in such a way that the itcan be mapped to the DOM documentinside the Model

com-Even if you ignore the previous lem, imagine how complicated itwould be to generate the HTML inputtable from a DOM document.Therefore, let’s look at the problem inanother way: as mentioned, the mostcomplicated data structure supported

prob-by POST is an array; is it possible that

we can switch the dataset from a DOMdocument to an array? This may seemquite difficult, but PHP makes it less so.PHP is a scripting language, whichmeans no compilation is needed Itsupports many more powerful opera-tions on arrays than most compiled lan-guages, such as the ability to changethe size of an array at run time and bet-ter support for associative arrays An

Trang 21

XML structure like the one in Figures 12and 13 can be represented by an array

as shown in Figure 14 In storing thenodes’ values to generate a new file orform, variables with names like

$$aattttrriibbuuttee 22, which can easily bemapped to the array, are used for theattribute of the second child of the rootnode This is necessary, as the arraycannot store the values and structure atthe same time (you can easily deter-mine this by looking at the ‘parentnode’ in the array) After a POST, thevalues can be retrieved simply as

$$HHTTTTPP PPOOSSTT VVAARRSS [[$$vvaarriiaabbllee nnaammee]], inwhich the variable names can beassigned when we loop through theDOM-structure-array by using the arraykeys This approach solves two prob-lems at the same time without a com-plex algorithm: it is much easier to gen-erate the input table from an array (thatrepresents the structure) and variables(that store the node value) (Figure 15—HTML of input table); both simple vari-ables and arrays can be POSTed to noti-

fy the server of the changing structureand node content The algorithm forgenerating the XML file and retrievinguser input will be described in the fol-lowing sections, when we discuss theView and Controller As we will see, this

‘data structure’ also helps improve ciency

effi-Arrays in PHP are more useful than inother languages, since the structure can

be changed during runtime You caneasily devise a program that utilizesarrays, like, for example, a computerpurchasing application Let’s apply theMVC design pattern again: the Model isinitialized with all the computer modelsavailable; based on the Model, the Viewgenerates an input form to accept pur-chasing information for each computer.When the form is submitted, theController interprets the input and noti-fies the Model about this additionalinformation Then, based on thechanged Model, a new View selected

by the Controller generates the tion form or another more complicatedinput form An array is used herebecause it can simplify the mapping between the purchasinginformation/other more complex data

valida-Figure 13

Figure 14

Figure 15

Figure 16

Trang 22

and each computer, as demonstrated in Figures 16(array with computer models), 17 (array with buyer’sname), and 18 (array with extra hardware) This map-ping is not restricted to be a one-to-one relationship;multiple-to-one is also possible by using nested arrays.This is only possible if we can change the array size atrun time, because the amount of information is uncer-tain This helps a lot in terms of efficiency, because nosearching is needed during mapping and most algo-rithms that are based on this ‘data structure’ can be fin-ished in time linear with respect to the number of items

in the arrays The same approach is applied in makingthe XSL generator: the Model is initialized with theschema of the XML file and the corresponding transfor-mation rules are stored in arrays as mentioned above

In dealing with a changing dataset, the MVC designpattern is the only choice for a web application On theother hand, we need to take care of several thingswhen we use a certain way to store complex data: theefficiency of manipulating the data, the ease of gener-ating a user interface from the data, whether HTML isable to transmit those data, the ease of performing

8 $this -> statement = $this -> table -> tableStart ( , 4 );

9 $this -> statement = $this -> table -> rowStart ();

10 $this -> statement = $this -> table -> tableHeader ( “Node Level” , 1 , 1 );

11 $this -> statement = $this -> table -> tableHeader ( “Tag name” , 1 , 1 );

12 $this -> statement = $this -> table -> tableHeader ( “Defualt value” , 1 , 1 );

13 $this -> statement = $this -> table -> tableHeader ( “Attribute” , 1 , 1 );

14 $this -> statement = $this -> table -> tableHeader ( “Attribute value” , 1 , 1 );

15 $this -> statement = $this -> table -> rowEnd ( true );

16 $this -> file = $bean -> getValue ( $bean -> getName ());

17 $type = $bean -> getValue ( “type” );

18 if ( $type == 1 ) //special names for different files

31 $this -> xmlBuild ( $this -> info , $bean , “_” , $this -> dom );

32 $this -> dom -> save ( $filename );

33 $this -> statement = $this -> table -> tableEnd ();

34 $this -> statement = “<br><br><font size=\”3\” face=\”Verdana, Arial, Helvetica, sans-serif\” color=\”#9966FF\”>Agent name: “ ;

35 $this -> statement = $this -> expression -> drawName ( $this -> file , $filename );

36 $this -> statement = “</font>” ;

37

38 $string = file_get_contents ( “files/agents.dat” );

39 $array = explode ( “,” , $string );

Trang 23

error checking/correction on the data (which we will

look at in next section), and so on As arrays in PHP are

comparatively a lot more flexible than in other

lan-guages, we should try to make good use of them

Generating the UI/file

According to the MVC design pattern, the View is

responsible for generating the user interface/file The

XXmmllBBuuiilldd class in the XML generator belongs to the

View, which constructs the file based on the XML

con-tents specified by the user in the Model (Listing 1) It is

very similar to the BBuuiilldd class, which constructs the user

interface for retrieving the XML file content The file is

generated by calling the xxmmllCCrreeaattee function, which

invokes the recursive function xxmmllBBuuiilldd to build the

‘real’ XML document and draw the checking table As

you can see, the running time is linear in the number of

nodes, which is as efficient as we can get Two design

patterns are employed in drawing the checking table:

Bridge and Command

Class XmlBuild only states the logic

of how to construct the table, while the

implementation of the actual drawing

is delegated to an object instantiated

from class Table The Bridge pattern is

applied; this decouples the logic and

implementation in such a way that

changing either one will be easy For

desktop applications, the biggest

bene-fit of employing the Bridge pattern is

portability; different widget

implemen-tations for different platforms, like

Windows, Mac OS and X11, are

encap-sulated in classes that inherit from an

abstract base class WWiinnddoowwIImmpp By just

programming on the abstract base

class, we can specify the construction

logic for the UI on all platforms When

switching platforms, we only need to

replace the object for implementation

and the logic will stay the same Based

on the same principle, the Bridge

pat-tern in a web application enables us to

change the implementation of the UI

without modifying the logic, making a

switch from HTML to XHTML, for

example, quite easy (Figure 19) More

importantly, the UI in a web application

changes even more often than in a

desktop application What most web

applications do is more or less the

same: filling forms, saving or searching

records, and so on What makes a web

application outstanding is the user

interface—therefore, every developer

should try to make the interface

imple-mentation as flexible as possible

When the ddaattaaTTaabbllee function is called to draw a cell,

$$tthhiiss >>eexxpprreessssiioonn is passed as parameter This isemploying the Command pattern: the action of draw-ing the content in the table cell is encapsulated in theobject, $$tthhiiss >>eexxpprreessssiioonn in this case (Figure 20)

$$tthhiiss >>ttaabbllee is the ‘invoker’ that invokes the drawingand $$tthhiiss >>eexxpprreessssiioonn is the ‘command’ that knowshow to perform the drawing The action of drawingcan thus be parameterized before any action takesplace, as in Listing 2, where the node value is specified.This pattern is helpful in decoupling the objects thatinvoke the operations (table) from the objects thatknows how to perform them (expression) In addition,

it is easy to add new invokers or commands by classing In the original Command pattern, the invokerscall the ‘execute’ function in the command repeatedly

sub-to perform the action A restriction arises: only onemethod, ‘execute’, can be called by the invoker Themost straightforward solution is to perform condition-

1 <?php

2 /**

3 * Setup the data of the checking table

4 * (parameterized the action of drawing the checking table before drawing)

5 */

6

7 function setData ( $result , $mother , $key , $child )

9 $this -> tag = $result [ ]; //node tag

10 $this -> attr = $result [ ]; //node attribute

11 $this -> attrv = $result [ ]; //node attribute value

Trang 24

ing in the invoker (perhaps based on the input eters) to decide what function to call on command.However, this exposes the command object interfaceand renders the Command pattern ineffective

param-Another approach is to pass in function handlers It iseasy to create a function handler in PHP because it isonly a string containing the function name, and thefunction can be called by $$oobbjjeecctt >>$$ffuunnccttiioonn nnaammee(())(an example is ddrraawwLLeevveell in Listing 3 to print the nodelevel, called by the ttaabblleeDDaattaa function in Listing 4),which does not involve any ‘complex concept’ likefunction pointers in C and C++ In this case, the invok-

er is completely ignorant about the command object The main difference between rendering the file andthe UI is that we have to perform extra error checkingwhen the former is being handled For example,

F

FE EA AT TU UR RE E Developing a PHP - XML Generator

1 <?php

2 /**

3 * Draw the level of the node by comparing the last node

with the same level

8 $statement = “<TD COLSPAN=$colspan ROWSPAN=$rowspan>” ;

9 $statement = $expObj -> $function ();

Trang 25

adding a node without appending it to any parent in aDOM tree is invalid In this case, the node is valid when

we merely look at the node content, but when we look

at the tree structure as a whole, the node becomes anerror This kind of checking is unnecessary if we storethe values in a DOM document, but we store them sep-arately here Thus, we need the functions ggeettCCNNooddee

(Listing 5) and ggeettMMNNooddeefrom Listing 2 These functionsare responsible for error checking and for rendering thechild or parent node using the DOM functions in PHP5.The DOM functions throw exceptions for invalidexpressions, thus ensuring the correctness of the nodecontent In addition, ggeettCCNNooddee(())and ggeettMMNNooddee(())returnNULL when reading a node without tag names; thiscauses all the node’s children to be neglected becausethey do not have a parent With the checking per-formed by the Controller when appending a number ofchildren to the tree, the validity of the file can be guar-anteed

However, there are cases where checking cannot beaccomplished by just looking at the current value, butother entries also need to be taken into account This isinefficient because some values may be visited multipletimes for checking and the running time may becomeexponential If we apply this method to the XSL gener-ator, it does not even work—for example, if we try toidentify whether a node is a vvaalluuee ooff node or a textnode by looking at the node value (vvaalluuee ooff node inFigure 21; tteexxtt node in Figure 22) This is error pronebecause an expression like ////lleevveell++11 seems to be avvaalluuee ooff node, but may actually be a text node (using

a strange expression) The most robust solution is torequire the user to specify the types and store them inanother array, which again can be mapped to the orig-inal set of data easily This approach can be furtherapplied to mark whether a field is used, whether thenode is a child or parent, and so on Although moreresources are needed, this ensures that no node is visit-

ed more than once for error checking In addition, ithelps simplify the algorithm for building UI/file as allrelated information can be found easily without search-ing (Listing 6)

Input processing

The Controller is responsible for handling the user’sinput according to the MVC design pattern In order todesign an efficient Controller, we must first understandwhat data is transmitted to the server in a PHP webapplication

The GUI in a desktop application usually has eventhandling to invoke programs, for example MFC orWindow forms in NET, and so on However, in a webapplication, there is no way that you can ask a text box

to invoke a function from the server The only way forusers to communicate with the server is by submittingthe whole form, which means the server will be sent all

1 <?php

2 /**

3 * Identify the default value and save it

4 * Inside a foreach loop with $i, $j counting the level of

16 $defaultValue = trim ( $value [ $i ][ $j ]);

17 for ( $k = 0 ; $k < count ( $attribute [ $i ]); $k ++) //set

36 $text = $this -> dom -> createTextNode ( $this -> element );

37 $node -> appendChild ( $text );

38 return array( $node , array( $this -> tag , $this -> attr ,

$this -> attrv , $this -> element ));

40 }

41 ?>

Listing 5

Trang 27

the GUI information However, the server usually does

not want that much—fields that have not been

modi-fied do not contain any useful information Sending all

of them to the server wastes bandwidth and adds extra

workload to the server, as it needs to search for

specif-ic information If the data is sent in this way, it is

diffi-cult to develop an efficient Controller, as the

informa-tion to be processed will be overwhelming Thus,

before we design the Controller, let’s see what we can

do to restrict the amount of data sent

Let’s look at the XSL generator again (Figure 23)

When we click “Go!”, we only want to submit the

‘number of items’ for that particular table Only that

number is needed in drawing a new table, so sending

any more data would be a waste The only solution is

to make a form that only contains the ‘number of

items’ and the “Go!” button; thus, there will be

multi-ple forms in a single page However, this method does

not work when the input fields are interleaved, as the

contents in a single form must be grouped together

This is also true for the XSL generator; the input fields

of XSL node values are interleaved with the ‘number of

items’ text boxes (Figure 24), thus the input fields for

XSL nodes cannot be put in the same form

We can, however, use JavaScript to group these

entries In this example, these input fields actually do

not belong to any form The values in the fields are

extracted by JavaScript during submit and placed into

another separate form, in the corresponding hidden

fields (figure 25) The caution: the JavaScript fails if it

operates on non existing fields Thus, the JavaScript

must also be dynamically generated if the form is

dynamically generated; we discuss this in the next

sec-tion

We are able to limit the amount of data sent in the

above example, so the Controller does not have to

search for the information However, in some cases,

most data in the form are needed and therefore it is

wasteful to write so much extra code to restrict the

amount of data sent In these situations, we need to

fig-ure out how to process the data efficiently Let’s look at

the XML generator as an example When we append

children to a node, all data in the form except the

“number of children to append” for other nodes are

needed (Figure 26) The user’s input will be in one of

the “number of children to append” fields and we need

to search that out One way is to walk through all of

them and search for the one that contains a number

The running time here is linear in the number of nodes

Can it be more efficient? Yes, when we can utilize the

data sent The button data is also sent at submission

time Interestingly, when a button name is specified as

an array (e.g button[0][0][1][0]), the submitted data is

an array as well (Figure 27) We can find out what

but-ton the user has pressed and retrieve the corresponding

“number of children” without visiting all the input

fields Listing 7 shows how to find the node and

modi-1 <?php

2 /**

3 * The recursive function to find which button is pressed

4 * and the number of children to append

13 $newAlready = $already ”_” $key ;

14 $newInput = $input [ $key ];

15 $deepChild = $child [ $key ];

16 $get = $this -> findChild ( $value , $deepChild ,

$newInput , $newAlready , $HTTP_POST_VARS );

17 if (! $get ) //wrong input

Trang 28

fy the “DOM array tree” The running time becomeslinear in the depth of the tree, which is much more effi-cient In addition, we perform error checking to discov-

er whether the user has entered any malformed input(like negative numbers or letters) The original ‘DOMarray’ remains untouched in such a case

Dynamic UI

As mentioned in the last section, JavaScript can helprestrict the amount of data sent to the server In addi-tion, it can produce a truly dynamic user interface InJavaScript, the change in user interface is performed bythe browser instead of the server More specifically, wecan specify a function and ‘relate’ it to a control so thatthe browser will invoke the function when that

F

FE EA AT TU UR RE E Developing a PHP - XML Generator

1 <?php

2 function toString ( node ) {

3 var str = “” ; // the var keyword makes str a local

21 } else if ( dataType == “var” ) {

22 if ( getSelectedValue ( node ) != “NULL” ) {

23 if ( getSelectedValue ( node ) == “default” )

36 if ( getSelectedValue ( node ) == “NULL” ||

getSelectedValue ( node ) == “null” ) {

51 } else if ( dataType == “edit” ) {

52 str = node firstChild value ;

10 function newOption(value, text) {

11 var option = document.createElement(“option”);

13 for ($j = 0; $j< count($this -> operand); $j++) {

33 return $statement1;

35 ?>

Listing 10

Trang 29

control is triggered For more detail see

h

http://www.w3schools.com/, where you can find lots of

good tutorials on JavaScript Let us examine the XSL

generator to see how JavaScript can produce a

dynam-ic UI This is the expression generator (Figure 28) It can

generate simple expressions as shown in Figure 29, or

complex expressions as shown in Figure 30 Thedynamic UI part is in adding and removing terms withparentheses, changing the type of expression (Figure31) and switching between self-defined values and sys-tem-provided variables (Figure 32) In this example, notonly is a dynamic UI rendered, but bandwidth is alsosaved and error checking is performed; instead of send-ing the menu values one by one, they are combined as

a string and the expression is checked for validitybefore sending to the server by the ttooSSttrriinngg functionshown in Listing 8)

However, there is no formal way to generate theJavaScript using PHP at runtime We need to do sobecause the content of our client-side script cannot befixed when the data is encapsulated in the PHP script

In this example, the number of input fields that theJavaScript needs to operate on is not fixed until theXML file is parsed If the scripting mechanism is care-lessly implemented, everything turns into a big bowl ofspaghetti code, and changing either the server- orclient-side scripts becomes extremely difficult

Therefore, let’s solve it step by step The first thing to

do in separating the JavaScript code is to encapsulate itinto PHP functions and put it into a single class, which

I called CCoommmmoonnJJSS Some functions can be hardcoded(Listing 9), while others need to get parameters fromthe function callers (Listing 10) Next, we separate thecode and define a class to call the functions, calledEExxpprreessssiioonn here EExxpprreessssiioonn somehow gets all parame-ters required by the CCoommmmoonnJJSS functions from differentparts of the system, and calls the functions fromCCoommmmoonnJJSS Thus, the CCoommmmoonnJJSS interface is only exposed

to EExxpprreessssiioonn The Bridge pattern is again applied: theimplementation part is in CCoommmmoonnJJSS and the logic part is

in EExxpprreessssiioonn; this way, changing either of those will beeasy (in most cases, we are just changing the imple-mentation part)

So far, so good However, there are two problems:

• What happens if there is more than oneobject that wants to call the JavaScript func-tions? These objects may call the same func-tion twice, passing different parameters, andthe JavaScript will crash

1 <?php

2 /**

3 * Draw the JavaScript header

4 * Collect function handlers as well as parameters

5 * merge them before calling the function from $js

31 $statement = $this -> js -> generate ( $para , $boo );

32 $statement = $this -> js -> footer ();

8 $obj =& $booObject -> getDataSet ();

9 $name = $obj -> getDataName ();

Trang 30

• How can EExxpprreessssiioonn get the parameters

from the whole system? If this is

implement-ed carelessly, EExxpprreessssiioonn may know about

the interfaces of most parts of the system,

and we would need to rewrite EExxpprreessssiioonn

whenever more data is added

The solution to the first problem consists of

introduc-ing a new class, JJSSDDrraawweerr, to be the only function caller

of CCoommmmoonnJJSS (instead of EExxpprreessssiioonn) It retrieves function

handler/parameters from different objects and merges

them before calling the functions from CCoommmmoonnJJSS

(Listing 11) All functions are called exactly once The

function handlers (Listing 12) are again only strings

that contain the function names In this case, no

mat-ter how many objects need to call the JavaScript tions, it can be done through JJSSDDrraawweerr, as long as theseobjects have the same functions to provide the functionhandlers and parameters

func-The solution to problem number two is to require thesystem to put data in a centralized object, namedDDaattaaSSeett in my case This way, EExxpprreessssiioonn will be ‘fed’

by DDaattaaSSeett for the parameters and remain unaware ofthe rest of the system In the previous case, ifEExxpprreessssiioonn asks the system ‘explicitly’ for data, it has to

be rewritten when more more data from other parts ofthe system is included However, this is not necessarywith DDaattaaSSeett; storing all data collectively in this struc-ture also allows passing the data from page to page byserialization and session mechanisms (Listing 13), and

F

FE EA AT TU UR RE E Developing a PHP - XML Generator

51 $new = $this -> file ”,” $string ;

52 file_put_contents ( “files/agents.dat” , $new );

63 //$info is the structure-array

64 //$bean contains XML data

65 //$mother is the strings indicating node level

66 //$motherNode is the parent DOM node

72 $this -> domWriter -> setData ( $bean , $mother , $key , false );

73 $result = $this -> domWriter -> getMNode ();

74 if ( $result != NULL )

76 $motherNode -> appendChild ( $result [ ]);

77 $this -> expression -> setData ( $result [ ], $mother , $key , false );

78 $this -> statement = $this -> table -> rowStart ();

79 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawLevel” , 1 , 1 );

80 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawTag” , 1 , 1 );

81 $this -> statement = $this -> table -> tableInfo ( “N/A” , 1 , 1 , NULL );

82 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawAttr” , 1 , 1 );

83 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawAttrV” , 1 , 1 );

84 $this -> statement = $this -> table -> rowEnd ( true );

85 $newMother = $mother $key ”_” ;

86 $this -> xmlBuild ( $value , $bean , $newMother , $result [ ]);

92 $this -> domWriter -> setData ( $bean , $mother , $key , true );

93 $result = $this -> domWriter -> getCNode ();

94 if ( $result != NULL )

96 $motherNode -> appendChild ( $result [ ]);

97 $this -> expression -> setData ( $result [ ], $mother , $key , true );

98 $this -> statement = $this -> table -> rowStart ();

99 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawLevel” , 1 , 1 );

100 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawTag” , 1 , 1 );

101 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawValue” , 1 , 1 );

102 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawAttr” , 1 , 1 );

103 $this -> statement = $this -> table -> tableData ( $this -> expression , “drawAttrV” , 1 , 1 );

104 $this -> statement = $this -> table -> rowEnd ( true );

Trang 31

introduces one more way of storing data: storing the

serialized DDaattaaSSeett in a file

Review

There are many more constraints in implementing the

user interface for a web application than for a desktop

application As we walk through examples of how to

display complex data from changing datasets, how to

generate a UI, how to process users’ input and how to

produce a dynamic UI, we see that the approaches are

completely different Besides functionality,

perform-ance and flexibility are also important: the server will be

easily overloaded if the code is inefficient, and UI of

web applications changes often so the cost of

redevel-opment should be minimized

The XML/XSL generator can be found online at

h

http://unity.cs.caltech.edu/~mpchau13/start.php It is still

in the prototype stage—and you are, of course,

wel-come to report any bugs you encounter

Acknowledgements

I would like to thank Prof K Mani Chandy and Dr

Daniel M Zimmerman for their unfailing guidance and

support, and for the freedom to conduct the research

Thanks also to Mr Elliott Michael Karpilovsky, Mr

Jonathan Lurie, Mr Shaun Lee and Mr Siu-on Chan fortheir valuable comments and advice This project isfinancially supported by the Hong Kong Chapter of theCaltech Alumni Association

About the Author ?>

To Discuss this article:

http://forums.phparch.com/182

Grace is a year-three undergraduate student at the Chinese University of Hong Kong, majoring in information engineering She earned her expenses by developing and maintaining over ten systems in PHP for the whole school, including all kinds of attendance record systems, as well as school project databases This XML generator is part of her Summer Undergraduate Research Fellowship at the California Institute of Technology.

Trang 33

One of the changes introduced in PHP 5 in regard

to XML handling is a change in the underlying

library that is being used to parse XML

docu-ments

In PHP 4, the Expat library was used to parse XML

documents when the standard XML parsing extension

was used To ensure that the XML extension would be

enabled by default, the Expat library was bundled with

PHP, meaning that you’d always have the necessary

dependencies—the fact that the library had a

PHP-friendly license and was quite small helped cement this

decision Furthermore, new versions of the library were

far in between, making the job of ensuring that the

lat-est stable release was always bundled with PHP fairly

simple

While this convenience was nice, it did cause a

num-ber of problems First of all, bundled libraries are built

into PHP directly during the compilation process,

meaning that, whenever you wanted to upgrade the

library, you would need to recompile your entire PHP

build Moreover, if PHP was used as a module—with

Apache, for example—the library could end up

conflict-ing with another Expat library variant used by another

piece of software, such as an Apache 2 server You

could compile PHP by specifying an external Expat

library via the ——wwiitthh eexxppaatt ddiirr flag, but very few

peo-ple actually did so Another problem with Expat is the

fact that its development cycle was quite slow and new

functionality was very rarely, if it all, added, meaning

that the capabilities of the library were somewhat

lim-ited Other XML extensions, such as DOMXML used a

different XML parsing library, Libxml2, which meant

that you could end up having PHP use two libraries thatduplicate each other’s functionality—never a goodidea

Libxml2: The Swiss Army Knife of XMLLibraries

With the impending release of PHP 5, in order to unifythe underlying XML parsers, all extensions that workwith XML were made to use the Libxml2 library, which

is an XML C parser and toolkit developed for theGnome project This library is a very popular XML pars-

er and virtually every modern *NIX distribution has itinstalled by default It is being very actively developedand, consequently, supports all of the new andadvanced XML features, such as DTD validation, Xpath,HTML support, and so on After much talk on the PHPdevelopment list, the decision was made not to bundlethe library, since it is quite burdensome (as a sourcepackage, at least, it’s almost as large as PHP itself) andits frequent releases would make bundling it a mainte-nance nightmare However, because the library can befound on virtually any system (for Win32 builds, thelibxml2.dll file is included with PHP) this not much of aproblem and actually allows easy upgrades of thelibrary without having to recompile PHP, since thelibrary is linked dynamically

Libxml2 happens to support an Expat-emulation

by Ilia Alshanetsky

PHP: 5.x OS: Any

REQUIREMENTS

When most people talk about PHP 5, they tend to concentrate on the many improvements in the way it works with objects, which is certainly a significant component of the new release This often leaves equally important improvements, such as the changes made to the way PHP works with XML, neglected This article’s goal is to familiarize you with how XML is handled by PHP 5 and how these changes make working with XML much easier.

Trang 34

mode, which makes it behave in an almost identical

manner to the original Expat library This means that,

for the most part, the behavior of the XML extension

based on Expat in PHP 4 is not different from the one

in PHP 5 The new library is significantly faster in

pars-ing XML documents, however, especially when DOM

trees are built This said, when using SAX, in some cases

the original Expat library will be a little faster, which is

why some people who only use Sax still can compile

the XML extension in PHP 5 against the Expat library by

specifying the ——wwiitthh lliibbeexxppaatt ddiirr configuration

direc-tive Keep in mind, however, that, since the Expat

library itself is no longer bundled, if you choose to go

this route, you will need to make sure that it is

separate-ly installed on your system before you configure and

compile PHP

The Traditional Way

The “oldest” way of parsing XML documents via the

XML extension—using the xxmmll ppaarrsseerr ** family of

func-tions—didn’t change much between PHP 4 and 5 The

only changes are caused by slight incompatibilities

between the underlying XML libraries, which, for the

most part, are fairly minor and hard to trigger and will

not, therefore, affect most users This parsing

method-ology uses the Simple API for XML (SAX), which is an

event-driven interface in which the parser invokes one

of several methods supplied by the caller “Events”

include recognizing an XML tag, finding an error,

encountering a reference to an external entity, or

pro-cessing a DTD specification The advantage of this

par-ticular approach is that it does not require you to have

the complete document in memory This is particularly

good for large XML files that would require immense

amounts of memory if they were loaded into memory

It also allows you to parse XML documents as you

receive them from external sources (such as an HTTP

feed) rather then having to wait for the entire

docu-ment to be retrieved before getting to the parsing

stage

Because the parser does not work with the entire

document, it cannot perform parsing optimizations

that result from knowing the document’s structure This

means that, for small XML documents that do not

require much memory, using DOM to create a DOM

tree would actually be faster

To handle the SAX events in PHP, you need to

speci-fy a function or a class method that will be used to

dle this particular event At minimum you need to

han-dle at least three events: tag start, tag end and tag data,

as shown in Listing 1

The parsing process does not return any data—the

job of collecting data and returning it in some way is

left to the event handler functions Those functions will

need to determine what tag they are operating on,

what event is being processed and use global variables

or class properties to store the data while the document

is being parsed—you can see an example of this inListing 2

Here, the ttaagg ssttaarrtt ssttaarrttfunction creates a rary array variable and stores the name of the currenttag, including its attributes (if available), into it It alsoinitializes the third array element, which later will beused to store the tag’s data If the tag contains anyattributes, they will be stored inside the $$aattttrr variable;these will be included in an array in which every ele-ment constitutes an attribute whose name is stored inthe key If no attributes are available, the variable willcontain NNUULLLL

tempo-Listing 3 shows the data handling function, whichsimply appends any data passed to it to the data ele-ment of our temporary array It is important to appendthe data, rather than to assign it directly, since if the

F

1 <?php 2

3 $x = xml_parser_create (); // initialize XML parser

4 // specify tag start and end handlers

5 xml_set_element_handler ( $x , ’tag_start_func’ , ‘tag_end_func’ );

6 // this function will handle the data inside the tag

7 xml_set_character_data_handler ( $x , ‘tag_data_func’ );

8 xml_parse ( $x , “xml_file.xml” ); // parse document

9 xml_parser_free ( $x ); // free memory

10

11 ?>

Listing 1

1 <?php 2

3 function tag_start_func ( $x , $tag , $attr ) {

4 global $tmp_data ; 5

6 $tmp_data = array( $tag , $attr , ‘’ );

7 } 8

9 ?>

Listing 2

1 <?php 2

3 function tag_data_func ( $x , $data ) {

4 global $tmp_data ; 5

6 $tmp_data [ ] = $data ;

7 } 8

9 ?>

Listing 3

1 <?php 2

3 function tag_end_func ( $x , $tag ) {

4 global $final , $tmp_data ; 5

6 if (isset( $final [ $tag ])) {

7 $final [ $tag ] = array();

14 ?>

Listing 4

Trang 35

tag’s data is very large or contains new lines it may be

returned in portions Thus, appending ensures that all

of the data for the tag will be fetched, rather than just

the last portion

When an end of the tag is encountered, the XML

parser will call our ttaagg eenndd ffuunncc function, shown in

Listing 4 Here, we place the data inside the $$ffiinnaall

global variable, which at the end of the parsing process

will contain the data from the XML document The tag

name is used as the key of the return array and itself

points to an array of values, since a tag is likely to occur

more the once The value stored contains all the

attrib-utes of a tag and their value Once the data has been

stored, the temporary $$ttmmpp ddaattaa array is destroyed, so

that its values will not conflict with the next tag

When Simple and XML Meet

As you can imagine, this does not make for a very

sim-ple imsim-plementation, which is why very few developers

actually like SAX Unfortunately, in PHP 4 the

alterna-tive—that is the DOM extension—had, until very

recently, a variety of serious problems, which

prevent-ed it from being a true alternative to XML/SAX

Additionally, because PHP code is heavily involved in

the parsing process, it does not make for a very fast

parser, since every tag results in at least three PHP

func-tion calls So, it is hardly surprising that developers

spent the time needed to improve this process for PHP

5!

One of the new extensions designed specifically for

fast and simple parsing of XML documents is

SimpleXML This extension heavily relies on the new

object-oriented features of PHP 5 to make the process

of parsing XML documents as trivial as possible Unlike

the XML extension, this extension uses the Document

Object Model (DOM) approach to parsing documents

This means that, in order to process a document, the

entire contents of the document must be retrieved—

and only then will a DOM tree representing the

docu-ment be created in memory This is quite fast for small

documents, which don’t require too much memory

and can be quickly retrieved even when they are stored

on remote servers However, when dealing with an

XML document whose size is in the tens of megabytes,

this may become quite slow due to the significant

memory requirements Fortunately, not many people

encounter such large XML files, so for the most part this

is a perfectly acceptable limitation

Parsing a document with SimpleXML could not beany simpler (no pun intended) As you can see inListing 5, it only takes a single function call, which takes

a single parameter that contains the XML data to beparsed This data can come from a local or remote file

or even a text string

The return value of SimpleXML’s ssiimmpplleexxmmll llooaadd **(())

functions is an object that represents the supplied data.You can now access that data as if it were a regular PHPobject, with each XML field stored in a separate prop-erty of matching name The attributes become thearray keys of the XML field to which they belong to, asshown in Listing 6

In the event that there are multiple instances of a ticular field, you can use to ffoorreeaacchh(()) language con-struct to iterate through the XML elements as if theywere an array and retrieve the data in the form of anobject It should be noted that while ffoorreeaacchh(()) itera-tions will work, you cannot use most of PHP’s arrayfunctions on objects created by SimpleXML

par-In the example shown in Listing 7, another OO ture of PHP 5 is being used: while $$aa is actually anobject, SimpleXML implements ttooSSttrriinngg(()), whichallows you to “print” the object and get the value ofthe data stored inside it In PHP 4, this would outputsome useless text, completely irrelevant to the neededoutput This is one of the reasons why SimpleXML can-not be back ported to PHP 4, where the Zend Engine 1simply lacks the functionality this new extension needs.Another neat feature of SimpleXML is the ability toaccess a particular element of the XML document with-out having to iterate your way to it In fact, this can bedone in more than one way The simplest and fastest

fea-1 <?php 2

3 $s = ‘<xml><a>Value 1</a><b id=”1”>Value 2</b></xml>’ ;

4 $x = simplexml_load_string ( $s ); // parse XML string

5 echo $x -> a ; // will print value of <a> field, “Value 1”

6 echo $x -> b ‘id’ ]; // will print attribute of b field, “1”

7

8 ?>

Listing 6

1 <?php 2

3 $s = ‘<xml><a>Value 1</a><a>Value 2</a></xml>’ ;

4 foreach ( simplexml_load_string ( $s ) as $a ) {

5 echo $a ; // print value of element <a>

6 } 7

8 ?>

Listing 7

1 <?php 2

3 $s = ‘<xml><b><c><a>Value 1</a><a>Value 2</a></c></b></xml>’ ;

Trang 36

approach consists of using indirect object references to

simply access the desired element from the DOM tree

The example that you can see in Listing 8 will make

PHP print the value of the second <<aa>> element, which is

contained within the <<cc>> element, itself a child of the

<<bb>> element SimpleXML is intelligent enough to figure

out that, when the array key is numeric, I am actually

attempting to access a particular element rather than

one of its attributes The one thing to be aware of is

that, if you access a non-exist element, SimpleXML will

not print any warning message—your output will

sim-ply be NULL Therefore, in order to verify that the

ele-ment exists, you should always use the eemmppttyy(())

con-struct Even if, for whatever reason, the value of the

ele-ment is blank, you’ll still have an object as the result,

meaning that eemmppttyy(()) will return false, indicating that

the element that you’ve tried to access does in fact

exist

XPath

Another way to retrieve a particular element from a

DOM tree is by using the XPath query language that

SimpleXML supports XPath is language—ratified by

W3C—for addressing parts of an XML document This

language allows accessing an XML document as if it

were a file system and each element were either a file

or a directory It also supports the ability of searching

for a particular element inside the document regardless

of its location

The example in Listing 9 will access the text contents

of the second <<aa>> element; please note that in XPath,

unlike what happens with PHP, the element count starts

from one and not zero The output of the xxppaatthh(())

method is going to be an array of matching entries,

unless nothing can be matched, in which case a

Boolean value of FFaallssee will be returned Each element

of the array is an object containing the value of the

matching element—in this case, the value will be

“Two”

As an alternative, you can try searching an XML

doc-ument for an element whose attribute value matches

the one you are looking for, as shown in Listing 10 In

this case, SimpleXML will use libxml2 facilities to search

for an <<aa>> element inside the document and isolate the

element (or elements) that contain the iidd attribute and

whose value is equal to 3 The one thing to remember

when using the XPath query language is that searching

through an XML document—especially a large one—is

not a very fast operation Therefore, if you know the

location of the data, it would be far more efficient to

reference it by hand from the DOM tree object

Aside from data retrieval, SimpleXML can also be

used to modify the existing XML documents However,

you can only modify existing elements and not add

new ones The process of modifying the data is quite

simple; all you do is assign an alternate string or integer

value to the property (element value) or the array key(attribute) The modified document can then bereturned as an XML string, as shown in Listing 11

The Document Object Model Extension

While SimpleXML cannot add new elements to anexisting document, you can convert SimpleXMLobjects to DOM-extension objects by calling the ssiimm pplleexxmmll iimmppoorrtt ddoomm function The DOM extension canthen be used to perform any number of modifications

to the converted object and, if necessary, convert itback to a SimpleXML object via the ddoomm iimmppoorrtt ssiimm pplleexxmmll function This is an advantage of having bothextensions use a DOM tree to represent the XML doc-ument while utilizing the same underlying library

This brings us to another new XML extension in PHP5: the DOM extension, which is a complete rewrite ofthe DOMXML extension that was available in PHP 4

The new extension, like SimpleXML, makes use of thenew PHP 5 OO features and addresses some of the lim-itations found in the older code, as well as introducingnew functionality Most importantly, it suffers fromnone of the problems that plagued the DOMXMLextension in PHP 4, such as memory leaks The newinterface makes it much simpler to work with XML doc-uments, which you can create, modify, join and evenvalidate The extension supports the ability to workwith HTML documents, even if they are not wellformed, which gives you the ability to easily parseHTML without writing a custom parser

While the DOM extension can be used to parse uments, the process is not quite as simple as it is withSimpleXML, which is why interoperability with the lat-

doc-F

1 <?php 2

3 $s = ‘<xml><b><a id=”1”>One</a><a id=”3”>Two</a></b></xml>’ ;

3 $s = ‘<xml><b><a id=”1”>One</a><a id=”2”>Two</a></b></xml>’ ;

4 $r = simplexml_load_string ( $s );

5 $r -> b -> a 0 ][ ‘id’ ] = 5 ; // modify attribute of 1st <a> element

6 $r -> b -> a 1 ] = “Three” ; // modify value of 2nd <a> element

7 echo $r -> asXML (); // print modified XML

8

9 ?>

Listing 11

1 <?php 2

3 $s = ‘<xml><b><a id=”1”>One</a><a id=”3”>Two</a></b></xml>’ ;

Ngày đăng: 21/12/2013, 12:15

TỪ KHÓA LIÊN QUAN