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

Tài liệu The iterator pattern pptx

68 452 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 đề The Iterator Pattern
Tác giả Jason E. Sweat
Trường học University of Phoenix
Chuyên ngành Web Development
Thể loại Giáo trình
Năm xuất bản 2005
Thành phố Unknown
Định dạng
Số trang 68
Dung lượng 3,75 MB

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

Nội dung

So, we end up with: • Users, groups and roles • Permissions • Objects and object categoriesUsers can be part of one or more groups, and eachgroup can have a parent group, to allowing the

Trang 2

ences dedicated to the wonderful world of PHP and advanced Web development What’s best, you get access to both great conferences for one low price!

http://www.phparch.com/works

Hurry! Space is limited Prices start at just $349 US!

Rasmus Lerdorf–Identifying and Preventing XSS Attacks, John Coggeshall–PHP Enterprise Architecture, Wez Furlong – PHP Streams: Lucky Dip, George Schlossnagle–Regex Unlimited, Ilia Alshanetsky–Managing PHP Performance, Derick Rethans–How PHP Ticks, Chris Shiflett–Hands-on PHP (BYOL), Marcus Böerger–Happy SPLing, Dan Scott–LIMIT Yourself

to MySQL No More, Daniel Udey–Separating Content and Design, Lukas Smith–Database Abstraction, Paul Reinheimer–REST,

Robert Reinhardt–Multilingual Flash, Ron Harwood–Web Games with PHP

Trang 4

14 The Interator Pattern

Making Manipulating Object Collections Easy

by Jason E Sweat

25 PHP Library for Permissions Management

A Generic Permissions Management PHP Library

by Simone Grassi and Bernhard Gaul

35 Change Your Life with Version Control

10 TIPS & TRICKS

Input Filtering: Part 1

Trang 6

ast month, my wife, daughter, and I moved out of our (what we’d come to

refer to as ghetto) apartment, and into our first house

I hate moving I hate packing every little thing I own into boxes, and

disassem-bling the furniture I hate trying to wedge the n-hundred pound sofa-bed out the

all-too-narrow doors, and trying to move the refrigerator without breaking any of

the ceramic tiles that make up the kitchen floor (“oops”)

Then, after many hours of what seemed like endless stair-climbing, box taping,

keep-or-toss decision making, and one too many not-as-fun-as-it-sounds

Tetris-like games of van and truck packing (“Can we get the rest in this trip? What if we

move this box, and put the chairs in the other truck? I think we need one of those

tall skinny pieces.”), the process is reversed, and we’re left with the joyous tasks

of unloading, more stair climbing, stacking, new-paint scrape-avoidance, more

narrow-door squeezing, trying to remember how to re-assemble the

customer-assembled furniture, and a basement full of boxes that were poorly labeled (in

haste)

To top it all off, my genius (and by “genius,” I mean moronic) telephone

com-pany somehow couldn’t figure how to reconnect our phone, properly, no matter

how many times we “call[ed] back in three hours.” As a result, we spent a full

week offline—it took me days to catch up on email

Fortunately, I have wonderful friends and family—some of whom traveled over

1000 km to help us get the house ready (and visit us, of course)—who worked

for nothing more than pizza, cold beer a sincere “thank you.”

As much as I hate all things related to moving, and am glad it’s over, there’s a

great joy that accompanies moving into our first house—our own first house

I see a parallel between upgrading our home, and upgrading my development

and production environments PHP 5.1 is on the horizon, and while I truly hate

the stress that upgrading a production environment brings (no matter how well

tested), I’m always—ok, usually—left with a similar joy of a successful upgrade,

better performance, and new features As always, we’re developing in exciting

times!

This month, we have a special treat for you: a chapter from our

soon-to-be-released php|architect’s Guide to Design Patterns, by Jason Sweat In it, he’ll show

you the ins and outs of Iterators in PHP, whether self-constructed, or built on a

foundation like PHP 5’s Standard PHP Library (SPL) The piece is literally full of

code, and it’s sure to whet your appetite for more design pattern goodness

Security corner is back, rounding out our full lineup of columns, and Peter has

reviewed the newest version of FPDF, a library that, if you haven’t used, you’ve

probably heard of

Happy reading! Now, I must go back to painting, landscaping, plastering,

wiring, cleaning, organizing and unpacking

php|architect

Volume IV - Issue 7 July, 2005

Publisher

Marco Tabini

Editorial Team

Arbi Arzoumani Peter MacIntyre Eddie Peloke

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, list- ings 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-2005 Marco Tabini & Associates, Inc — All Rights Reserved

TM

p pe ea ar r u up pg gr ra ad de e

H Ho om me e_ _R Re es si id de en nc ce e

L

Trang 7

"PHP 5.1 Beta 2 is now available! A

lot of work has been put into this

upcoming release and we believe it

is ready for public testing.

Some of the key improvements of PHP

5.1 include:

• PDO (PHP Data Objects) - A

new native database abstraction

layer providing performance,

ease-of-use, and flexibility.

• Significantly improved

lan-guage performance mainly due

to the new Zend Engine II

exe-cution architecture.

• The PCRE extension has

been updated to PCRE 5.0.

• Many more improvements

including lots of new

functional-ity & many bug fixes, especially

in regards to SOAP, streams and

SPL.

• See the bundled NEWS file

for a more complete list of

changes.

Everyone is encouraged to start

playing with this beta, although it is

not yet recommended for

mission-critical production use."

Check out all the latest info at

php.net.

phpBB 2.0.16

phpBB.comhas released the latest version of their open source bulletin board package.

What's new? Phpbb.com lists the changes as:

• Fixed critical issue with highlighting

• Url descriptions able to be wrapped over more than one line again

• Fixed bug with eAccelerator in admin_ug_auth.php

• Check new_forum_id for existence in modcp.php

• Prevent uploading avatars with no dimensions

• Fixed bug in usercp_register.php, forcing avatar file removal without ing avatar informations within the database

updat-• Fixed bug in admin re-authentication redirect for servers not having index.php as one of their default files set

Visit phpbb.comfor all the latest info.

FUDforum 2.6.14RC2

Fudforum.organnounces their latest release:

"The 2nd release candidate for 2.6.14

is now out, aside from a number of bug fixes few important developments were done as well

• FUDforum can now make use

of PDO Database driver for PHP 5.0/5.1 with support for MySQL,PostgreSQL and SQLite backends.

• FUDforum can now be installed on systems running PHP 5.1, the few BC changes introduced by this release are now being accommodated.

• The temporary table usage is now optional, which means forum install no longer requires this permission to be

available."

To grab the latest release or for more info, visit fudforum.org.

SOLAR 0.5.0

Solar.php announces the latest release

of their "simple object library and application repository" version 0.5.0.

paul-m-jones.com announces some of the highlights as:

• Unit tests for Solar_Base, _Cache, _Error, and _Locale

• End-user documentation (not just API docs) for those same classes, plus the overarching Solar class itself For all the highlights, visit

solarphp.com.

AjaxAC 0.4.1

Do you have a project which requires the use of AJAX? Check out the latest release of

AjaxAC a "PHP framework which can be used to develop, create, and generate AJAX

applications" According the announcement, version 0.4.1 includes:

"The ArithmeJax sample application was created The JavaScript escape() was

replaced with encodeURIComponent() The hook name generator was changed to

include in front of the hookname due to an IE6 compatibility error The redundant

AjaxAC class was removed and this functionality was moved to the AjaxACApplication

class All examples were updated to reflect the removal of the main AjaxAC class."

Grab the latest release from http://ajax.zervaas.com.au/

phpReports 0.4.1

phpReports report generator has announced the latest release, version 0.4.1 According to the announce- ment, this release includes:

"The setPageSize(size) and getPageSize() methods were added to the PHPReportMaker object Now you can specify the page size using code like "$oRpt = new PHPReportMaker();

$oRpt->setPageSize(30);" This method overrides the XML value."

Visit http://phpreports.source forge.net/for more information or to download.

Trang 8

Check out some of the hottest new releases from PEAR.

XML_RPC 1.3.1

A PEAR-ified version of Useful Inc's XML-RPC for PHP It has support for HTTP/HTTPS transport, proxies and authentication

This release is security related, and solves the recently discovered, and widespread remote-code-execution

vulnerabili-ty All users are strongly encouraged to upgrade immediately.

Translation2 2.0.0beta7

This class provides an easy way to retrieve all the strings for a multilingual site from a data source (i.e db).

The following containers are provided, more will follow:

It is designed to reduce the number of queries to the db, caching the results when possible.

An Admin class is provided to easily manage translations (add/remove a language, add/remove a string).

Currently, the following decorators are provided:

• CacheLiteFunction (for file-based caching)

• CacheMemory (for memory-based caching)

• DefaultText (to replace empty strings with their keys)

• ErrorText (to replace empty strings with a custom error text)

• Iconv (to switch from/to different encodings)

• Lang (resort to fallback languages for empty strings)

• SpecialChars (replace html entities with their hex codes)

• UTF-8 (to convert UTF-8 strings to ISO-8859-1)

Mail 1.1.5

PEAR's Mail:: package defines the interface for implementing mailers under the PEAR hierarchy, and provides supporting functions useful in multiple mailer backends Currently supported are native PHP mail() function, sendmail and SMTP This package also provides a RFC 822 Email address list validation utility class.

HTML_QuickForm_advmultiselect 0.4.0

The HTML_QuickForm_advmultiselect package adds an element to the HTML_QuickForm package that is two select boxes next to each other emulating a multi•select.

DB_ldap 1.1.1

The PEAR::DB_ldap class provides a DB compliant interface to LDAP servers.

We're proud to announce the release of php|architect's Guide to PHP Design Patterns,

the latest release in our Nanobook series.

You have probably heard a lot about Design Patterns -a technique that helps you design rock-solid solutions to practical problems that programmers everywhere encounter in their day-to-day work Even though there has been a lot of buzz, however, no-one has yet come

up with a comprehensive resource on design patterns for PHP developers—until today.

Author Jason E Sweat's book php|architect's Guide to PHP Design Patterns is the

first, comprehensive guide to design patterns designed specifically for the PHP developer This book includes coverage of 16 design patterns with a specific eye to their applications in PHP when building complex web applications, both in PHP 4 and PHP 5 (where appropriate, sample code for both versions of the language is provided).

For more information, http://www.phparch.com/shop_product.php?itemid=96.

Trang 9

• RFC compliant HTTP date handling

• Parsing of HTTP headers and messages

• Caching by "Last-Modified" and/or ETag

(with 'on the fly' option for ETag generation from buffered output)

• Sending data/files/streams with (multiple) ranges support

• Negotiating user preferred language/charset

• Convenient request functions built upon libcurl

• HTTP auth hooks (Basic)

• PHP5 classes: HttpUtil, HttpResponse, HttpRequest, HttpRequestPool, HttpMessage

runkit 0.3.0

Replace, rename, and remove user defined functions and classes Define customized superglobal variables for general pose use Execute code in restricted environment (sandboxing).

Trang 10

pur-Filter input What does that

mean? Well, in short, it means

what it says, but there’s

some-thing deeper hidden behind these

words, something sinister Yes,

these words mean user input

can-not be trusted For that matter, no

input, regardless of its source—

forms, RSS feeds, cookies, etc.—is

trustworthy In fact, the level of

dis-trust in input must be so high that

you no longer accept anything

from these sources at face value

Always verify the input data to

ensure it’s the expected, genuine

article

But why is this so hard to do? Is itbecause we innately want to trustpeople and other sources? Heavens,no! It’s hard because programmersare naturally lazy

Filtering input means writingmore code, writing smarter code

For those who wish to finish a ect quickly, this is daunting, and sothey quickly scribble down somecode—if, in fact, code can be scrib-bled—and deploy a release hoping

proj-to catch the problems in later

bug-fix (sometimes called security)

releases This can, however, causegreat problems in the meantime,not the least of which could consist

of SQL injection or cross-site ing (XSS)… or just plain bad data.Ensuring against bad datathrough filtering input is what we’llfocus on over the next three install-ments of Tips & Tricks So, comealong with me, and before we’refinished, you’ll be cynical and dis-trustful with the best of them—nolonger able to trust input of anykind—and, thus, security-con-scious

script-Input Filtering, Part 1:

Why Filter?

by Ben Ramsey

This year has seen an increased focus on PHP security, and this is good for

the language, developers, and business community One phrase that comes

to mind when discussing secure coding practices is Chris Shiflett’s mantra

of “filter input, escape output.” While we know what this means in a

gen-eral sense, practical examples elude us, so for the next three months, Tips

& Tricks will give practical suggestions for input filtering, chock full of code

examples.

Trang 11

Why Filter Input?

Input is bad In fact, it’s evil Just get

that through your head, and you’ll

be off to a great start

Input is evil because its source

cannot be trusted and the type of

data expected is not always the

type received, and all the client-side

validation scripts in the world can’t

stop input coming from another

source completely invalidated

What do I mean by “another

source?” I mean: another form on

another Web site that makes use of

your form (often referred to as a

spoofed form) for some insidious

means—or someone or some script

posting by any number of

alterna-tive means

Let’s take, for example, the form

in Listing 1, which is located at theimaginary URL

h t : / x m l e / o m h ml (We’ll continue to come back to thisform during the next few months;

don’t worry—the code will beincluded in each column.) Now,this is a form we’ve all seen; it asksfor a name and contact informa-tion—no doubt, you’ve used a sim-ilar form in the past, and there’snothing wrong with this form, butthere are a few assumptions oftenmade about it

One assumption is that the

m x e g h attribute of the fields pre-h

vents a user from entering moretext than allowed This is wrong.While a Web browser can correctlyprevent a user from doing sothrough this particular form, there’snothing to stop the re-creation ofthis form on another server andusing it to submit a much longerstring of data

Another assumption is that theuser may pick states only fromamong the options listed in the

s a ee drop-down field Again, this iswrong and for the same reasons.The Web browser might preventsaid user from entering other values

when using this form, but if

recreat-ed, the sky’s the limit

We’re starting to see a patternemerge A Web form/application issafe only when used properly This

is obvious But if used improperly,then processing scripts can receiveany and all kinds of input

Still, let’s look at two moreassumptions about this form—justfor the heck of it

This form has a set number offields Does that mean these are theonly fields that can be submitted?No! Also, can we assume that theprocessing script([process_form.php] in this case)can only receive submissions fromthis form? The answer, again, is no.The form in Listing 2 illustrateswhy these assumptions are wrong.This form lives on another server—for example, at h t : / v l e a -

devi-s a ee field now has a value of “TheShire.” Wait a minute… that wasn’t

in our option list, but it doesn’tmatter because it’ll post just fine.Thirdly, this form includes a newfield: the j nk field This doesn’t domuch now, but consider a server

TTIIPPSS && TTRRIICCKKSS

1 <!— A form located at: http://example.net/form.html —>

2 <form method=”POST” action=”process_form.php”>

3 Name: <input type=”text” name=”name” maxlength=”50” />

3 <input type=”hidden” name=”name” value=”Frodo Baggins” />

4 <input type=”hidden” name=”state” value=”The Shire” />

5 <input type=”hidden” name=”postal”

6 value=”It is my precious!” />

7 <input type=”hidden” name=”junk”

8 value=”Junk data being passed” />

9 <input type=”submit” value=”Submit” />

6 $req -> setMethod ( HTTP_REQUEST_METHOD_POST );

7 $req -> addHeader ( ‘Referer’ , ‘http://example.net/form.html’ );

8 $req -> addPostData ( ‘name’ , ‘Gandalf the Grey’ );

9 $req -> addPostData ( ‘state’ , ‘Middle-earth’ );

10 $req -> addPostData ( ‘email’ , ‘Olorin I was in my youth’ );

11 $response = $req -> sendRequest ();

12 ?>

Listing 2

Input Filtering, Part 1: Why Filter?

Trang 12

where rr g s e _ l b ls is enabled

and variables aren’t initialized—

think about what it can do

The R f r r Question

Invariably, the question now arises:

But what about the R f r rr? Yes,

what about it? I can check it, right?

Sure, go ahead, but it’ll bite you in

the end

It is a common misconception

that every request includes a

R f r rr header and that the value

of this header always represents the

origin of the request In truth and

practice, the origin of the request is

always the client The client can be

a Web browser or it can be a script

that resides on a server,

some-where It may or may not choose to

include a R f r r header in

requests The R f r r, when includ-r

ed, may or may not indicate the

previously requested parent

resource In fact, some proxy

servers have been known to modify

or drop the R f r rr header

alto-gether, thus blocking entire offices

and even ISPs from viewing Web

sites programmed to check for it

All this amounts to the fact that

R f r rr is highly unreliable as a

means of protecting Web

applica-tions from outside posting

Furthermore, it is not as important

to ensure input comes from a

spe-cific place as it is that the input

received conforms to expectations

Nevertheless, we’ll take a look at

how scripts use R f r r to blockr

requests from other sites:

if

(strcmp($_SERVER[‘HTTP_REFER-ER’],

‘http://example.net/form.html’)

== 0) {

// It came from the right

place, so let’s process it }

Now, this snippet of code will erly thwart a form such as the one

prop-in Listprop-ing 2 from postprop-ing to

p o e s f r hp, so long as theclient includes a R f r rr headerthat doesn’t match, but mischie-vous users aren’t in the business of

being foiled by clients Let’s

consid-er anothconsid-er means of posting andtake a look at Listing 3

The code in Listing 3 is similar tothat found in Listing 2 in that itposts to p o e s f r hp from adifferent location and bypasses allthe local constraints placed on it(e.g m x e g hh and any client-sidescripting) However, Listing 3 is dif-ferent because it doesn’t rely on a

Web browser and, thus, can modifyany part of the request In this case,

P A : H T _ e u st generates avalid P ST request, while adding a

R f r rr header Thus, the scriptsuccessfully posts to

p o e s f r hp because it sends

a valid R f r rr header with a valuethat p o e s f r hp expects

Now You’re Getting It

And so, we must filter the input It’sthat simple We cannot be sure theinput comes from the proper loca-tion, nor are we sure it is exactlywhat we want In fact, we’re prettysure it’s not

Feeling distrustful yet? Good.Great, even Do not trust inputfrom users, from anywhere This iswhy it’s important to ensure thatinput received is input expected

1 <?php

2 function filter (& $input , $allowed ) {

3 $validated = array();

4 foreach ( $input as $key => $value ) {

5 if ( in_array ( $key , $allowed )) {

6 $validated [ $key ] = $value ;

Trang 13

The approach we’ll take to filter

input is often called a “whitelist”

approach (as opposed to a

“black-list” approach) Instead of using a

blacklist to tell our script what kind

of input we won’t allow (e.g input

coming from somewhere other

than ff r t l, as in the l R f r r

example), we’ll use a whitelist to

tell it exactly what to allow

This is actually a much simpler

approach because, now, we don’t

have to think of the myriad kinds of

data an attacker might try to

sub-mit to our script Instead, we need

only know what we want to receive

and ensure that the received input

matches up

Capturing and Taming Input

Now, let’s talk about capturing

some of this evil input.

There are a few places we’ll

con-sider looking for input: $ G T,T

$ P ST, and $ C O IE We’ll not look

in $ R Q E TT, though it does

con-tain the values from each of these

superglobal arrays In short, we

want to know the exact scope of

the input, so we’ll use the specific

superglobal for the location we

expect to find it For example,

$ R Q E T ‘ a e ]] could refer to

$ G T ‘ a e ], ] $ P S [ n m ’], or

even $ C O I [ n m ’], so we want

to be sure it’s coming from the

cor-rect location, which is P ST in this

case

Luckily for us, PHP has already

done the work of capturing the

input In p o e s f r hp, the

val-ues passed by the input from—

f r t l (or from wherever it wasl

submitted)—are in $ P ST But the

data in $ P ST, you’ll remember, is

still evil data We must first filter it

There’s more than one way,

however, to filter form input, and I

won’t pretend that my suggestions

are any more than what they are:

suggestions They are not the right

way, but they are a way, and these

tips are sure to help control input

and provide a foundation on

which to build What’s important is

to write code with a

security-con-scious mindset, and part of thatmindset includes being wary ofinput

Now, to keep track of our good

data, we’ll store everything that’sconsidered clean (as in: it conforms

to expectations) to the aptly named

$ l an array, which will somewhatmimic everything that’s in $ P ST—

without all the evil tendencies

One approach that I often see is asanitizing function that gets applied

to the $ P ST array, as seen inListing 4 While this type ofapproach removes harmful charac-ters, it does not provide a whitelistsolution Instead, it blacklists poten-tially harmful characters (controlcharacters) and escapes the input(with h m e t t e ( ), which is not

a part of the filtering process We’re

only concerned with filtering the

input at this point, so we want theraw data—filtered, but raw

Escaping will take place during theoutput stage, which isn’t coveredhere

A whitelist approach defines thevalid range of characters/numbers,the acceptable values (of a s l c

field, for example), and the allowedfields For now, let’s take a look atdefining the allowed fields toensure we receive and processnothing more than expected

Listing 5 gives a whitelist examplefor defining the allowed fields First,

we use the $ h t _ i tt array todefine the allowed fields Then, werun the $ P ST array through the

f l e ( function using

$ h t _ i tt as a model What’sreturned to the $ l an array is theexpected input Anything unex-pected is left back in $ P ST where

it safely remains excluded from therest of the script

This is a very simple approach

that does not include any furtherinput checking—for now Though, Ihope it is evident how thisapproach adds a level of flexibility

to the filtering process For ple, imagine a $ o t w i e l st,

Wrap Up

By now, you should be fully vinced that all input is evil and whyit’s important to filter all incomingdata When it comes to input, thereare no guarantees as to the origin ofthe data or the type received.Whether working with GET, POST,cookies, RSS feeds, and the like,always filter input—regardless

con-Tune in next month when we’llwrestle more input to ensure inputreceived is input expected

TTIIPPSS && TTRRIICCKKSS

To Discuss this article:

http://forums.phparch.com/238

Ben Ramsey is a Technology Manager for Hands On Network in Atlanta, Georgia He is an author, Principal member of the PHP Security Consortium, and Zend Certified Engineer Ben lives just north of Atlanta with his wife Liz and dog Ashley You may contact him at r ra amsey@ @php p .net tor read his blog at h ht ttp:// /benra amse ey y.com/ /.

Input Filtering, Part 1: Why Filter?

Trang 14

Object-Oriented Programming encapsulates

application logic in classes Classes, in turn, are

instantiated as objects, and each individual

object has a distinct identity and state

Individual objects are a useful way to organize your

code, but often you want to work with a group of

objects, or a collection A set of result rows from a SQL

query is a collection

A collection need not be homogeneous either A

W n ow object in a graphical user interface framework

could collect any number of control objects — a M nu,

a S i er, and a B t on, among others

Moreover, the implementation of a collection can

vary: a PHP array is a collection, but so is a hash table,

a linked list, a stack, and a queue

The Problem: How can one easily manipulate any

col-lection of objects?

The Solution: Use the Iterator pattern to provide

uni-form access to the contents of a collection

You may not realize it, but you use the Iterator

pat-tern every day—it’s embodied in PHP’s a r y type andy

rich set of array manipulation functions (Indeed, giventhe combination of the native array type in the lan-guage and a host of flexible functions designed to workwith this native type, you need a pretty compelling rea-son not to use arrays as your means of manipulatingcollections of objects.)

REQUIREMENTS

Code Directory iterator

You have probably heard a lot about Design Patterns -a

technique that helps you design rock-solid solutions to

practical problems that programmers everywhere

encounter in their day-to-day work Even though there

has been a lot of buzz, however, no-one has yet come up

with a comprehensive resource on design patterns for PHP

developers -until today In this excerpt from Jason E.

Sweat's book php|architect's Guide to PHP Design

Patterns, you'll learn about the Iterator pattern, whether

custom-built, or with PHP 5's new Standard PHP Library.

Pattern

by Jason E Sweatauthor of

php|architect’s Guide to PHP Patterns

Trang 15

FEEAATTUURREE

Here’s native array iteration in PHP:

$test = array(‘one’, ‘two’, ‘three’);

echo $output; // produces ‘onetwothree’

The r s t )function restarts iteration to the beginning

of the array; c r e t )returns the value of the current

element; and n x ( advances to the next element in

the array and returns the new c r e t ) value When

you advance past the end of the array, n x ( returns

f l ee Using these iteration methods, the internal

implementation of a PHP array is irrelevant to you

Iterator couples the object-oriented programming

principals of encapsulation and polymorphism Using

Iterator, you can manipulate the objects in a collection

without explicitly knowing how the collection is

imple-mented or what the collection contains (what kinds of

objects) Iterator provides a similar interface to different

concrete iteration implementations, which do containthe details of how to manipulate a specific collection,including which items to show (filtering) and in whatorder (sorting)

Let’s create a simple object to manipulate in a

collec-tion (Though this example is in PHP 5, Iterators are not

unique to PHP 5 and most of the examples in this ter work in PHP 4 as well, albeit with a healthy amount

chap-of reference operators added) The object, L n a le,represents media such as movies and albums and isintended to be part of a web site or service to let usersreview or lend portions of their media collection toother users (For this example, do not concern yourselfwith persistence and the like.)

Let’s start with the code in Listing 1 as the basis forthe class and write some tests

To implement the requirements of this initial test, ate a class with a few public attributes and some meth-ods to toggle the values of these attributes, such as that

cre-in Listcre-ing 2

L n a le is a good, generic start Let’s extend it totrack items like DVDs or CDs

Figure 1

Trang 16

M d a extends a L n a le and tracks details about

spe-cific media, including the name of the item, the year it

was released, and what type of item it is See Listing 3

To keep things simple, M d a has three publica

instance variables, M d a : a e, e M d a : e rr, and

M d a : y e The constructor takes two arguments ande

stores the first in $ a e and the second in e $ e rr The

constructor also allows an optional third parameter to

specify type (which defaults to “dvd”)

Given individual objects to manipulate, you can now

create a container to hold them: a L b a y Like a reg-y

ular library, L b a yy should be able to add, remove and

count the items in the collection Eventually, L b a y

should also permit access to individual items (objects)

in the collection (which is shown momentarily in the

Sample Code section of this chapter)

For right now, let’s build a test case for L b a y:y

class LibraryTestCase extends UnitTestCase {

Now add some interesting features to the test:

class LibraryTestCase extends UnitTestCase {

An easy way to implement a d ) is to piggyback on

PHP’s flexible array functions: you can add items to an

array instance variable and use c u t ) to return the

number of items in the collection

L b a yy is now a collection, but it provides no way to

retrieve or manipulate the individual members of the

collection

Let’s move on to the purpose of the article,

imple-mentation of the Iterator design pattern.

The following UML class diagram shows the GoF

Iterator pattern with the M d a and a L b a y classes usedy

1 <?php

2 // PHP5

3 class LendableTestCase extends UnitTestCase {

4 function TestCheckout () {

5 $item = new Lendable ;

6 $this -> assertFalse ( $item -> borrower );

7 $item -> checkout ( ‘John’ );

8 $this -> assertEqual ( ‘borrowed’ , $item -> status );

9 $this -> assertEqual ( ‘John’ , $item -> borrower );

10 }

11 function TestCheckin () {

12 $item = new Lendable ;

13 $item -> checkout ( ‘John’ );

14 $item -> checkin ();

15 $this -> assertEqual ( ‘library’ , $item -> status );

16 $this -> assertFalse ( $item -> borrower );

6 public function checkout ( $borrower ) {

7 $this -> status = ‘borrowed’ ;

8 $this -> borrower = $borrower ;

9 }

10

11 public function checkin () {

12 $this -> status = ‘library’ ;

7 public function construct ( $name , $year , $type = ’dvd’ ) {

8 $this -> name = $name ;

9 $this -> type = $type ;

10 $this -> year = (int) $year ;

6 $this -> assertFalse ( $it -> isdone ());

7 $this -> assertIsA ( $first = $it -> currentItem (), ‘Media’ );

8 $this -> assertEqual ( ‘name1’ , $first -> name );

9 $this -> assertFalse ( $it -> isdone ());

10

11 $this -> assertTrue ( $it -> next ());

12 $this -> assertIsA ( $second = $it -> currentItem (), ‘Media’ );

13 $this -> assertEqual ( ‘name2’ , $second -> name );

14 $this -> assertFalse ( $it -> isdone ());

15

16 $this -> assertTrue ( $it -> next ());

17 $this -> assertIsA ( $third = $it -> currentItem (), ‘Media’ );

18 $this -> assertEqual ( ‘name3’ , $third -> name );

19 $this -> assertFalse ( $it -> next ());

20 $this -> assertTrue ( $it -> isdone ());

21 }

22 }

23 ?>

Listing 4

Trang 17

FEEAATTUURREE

to make the example concrete (GoF is the Gang of

Four— Erich Gamma, Richard Helm, Ralph Johnson,and John Vlissides, writers of the famous, and definitive

Design Patterns, Elements of Reusable Object-Oriented Software).

Your collection class must provide a FactoryMethod to create an instance of your Iterator

Iterator classes define an interface of f r t )to go tothe beginning of a collection, n x ( to move to the

next item in sequence as you iterate, c r e t t m ) toretrieve the current item from the collection as you iter-ate, and i D n ( to indicate when you have iteratedover the entire collection

In the next section, we are going to create the

L b a y o I e a or class as an example of a direct

implementation of the GoF Iterator design pattern—see

Figure 1

Sample Code

The first step in implementing the GoF Iterator pattern

within L b a y is to write a new test case for the newy

concrete Iterator Since each test method will be

manipulating a L b a yy filled with M d aa instances, youcan employ the U i T s C s : s t p ) method topopulate a variable with a L b a yy in a known state foreach test (For the purposes of this article, treat

U i T s C se as a generic unit testing suite The ated code does, however, serve to illustrate how

associ-L b a yy should perform.)

Start by adding the L b a y : e I e a o () method

as a FactoryMethod for instances of the

$this->assertIsA($it = $this->lib->getIterator() ,’LibraryGofIterator’);

} }

Here’s the implementation

class Library {

1 <?php

2 class LibraryGofIterator {

3 protected $collection ;

4 function construct ( $collection ) {

5 $this -> collection = $collection ;

6 function construct ( $collection ) {

7 $this -> collection = $collection ;

9 while ( $item = $it -> next ()) {

10 $output = $item -> name ;

4 protected $first = true ;

5 function construct ( $collection ) {

6 $this -> collection = $collection ;

7 }

8 function next () {

9 if ( $this -> first ) {

10 $this -> first = false ;

11 return current ( $this -> collection );

Trang 18

The g t t r t r ) method passes the L b a yy’s $ o

-l c i nn to the constructor of the new concrete iterator

This technique has two important implications: each

iterator is independent, so multiple iterators can

oper-ate at the same time Additionally, the iterator operoper-ates

on the collection as it existed at the time the iterator

was requested If another item is added to the

collec-tion at any time later, you must request another

itera-tor to display it (at least in this implementation)

Continue enhancing the test suite by adding

asser-tions to the T s G t o I e a o ( method to match

the Iterator design pattern The i D n ( method

should only be true if you’ve iterated over the entire

collection If the iterator’s just been created, i D n (

should obviously return f l ee to indicate it’s okay to

As usual with Test Driven Development (TDD),

imple-ment the simplest possible code that satisfies your test

So, what should happen during the first iteration.

c r e t t m ) should return the first M d a objecta

added in the I e a o T s C s : s t p ) method and

i D n ( should continue to be false, since two

addi-tional items remain to be iterated over

class IteratorTestCase extends UnitTestCase { function setup() { /* */ }

function TestGetGofIterator() {

$this->assertIsA($it = $this->lib->getIterator() ,’LibraryGofIterator’);

It’s critical that L b a y o I e a or receives the $ o

-l c i nn in the constructor (see the minimal tation of L b a y above) and returns the y c r e t )item

implemen-of that array from the c r e t t m ) method

class LibraryGofIterator { protected $collection;

function construct($collection) {

$this->collection = $collection;

} function currentItem() { return current($this->collection);

} function isDone() { return false;

} }

What should happen in the next iteration? The n x (

method should change what item is returned by the

c r e t t m )method This test captures that

4 function getIterator ( $type = false ) {

5 switch ( strtolower ( $type )) {

5 $this -> lib -> add ( $dvd = new Media ( ‘test’ , 1999 ));

6 $this -> lib -> add (new Media ( ‘name4’ , 1999 ));

7 $this -> assertIsA (

8 $it = $this -> lib -> getIterator ( ‘available’ )

9 , ’LibraryAvailableIterator’ );

10 $output = ‘’ ;

11 while ( $item = $it -> next ()) {

12 $output = $item -> name ;

19 while ( $item = $it -> next ()) {

20 $output = $item -> name ;

Trang 19

The third iteration looks much like the others, except

the i D n ( method must return t ue You also want

n x ( to indicate success of moving to the next

itera-tion

With small modifications to the [next()] and

[isDone()] methods, all of the tests pass (See Listings 4

and 5)

There’s just one problem with the Iterator test case: it

doesn’t reflect how iterators are typically used Yes, it

tests all of the features of the Iterator pattern, but

appli-cation code uses the Iterator in a much simpler way So,

the next step is to write a test to run more realistic

So far, the implementation of Iterator copies an array

(the collection) and uses PHP’s internal pointer to track

the iteration You can also implement the Iterator by

keeping track of the collection index by yourself Thisrequires a new accessor method in L b a yy to fetch anobject by key

class Library { //

function get($key) {

if (array_key_exists($key, $this->collection)) { return $this->collection[$key];

} } }

Also, you’d pass $ h s (the library itself) to the con-s

structor instead of $ h s > o l c i nn (the array taining the Media collection) in the

con-L b a y : e I e a o ( method

The “external” iterator would then just track a

point-er intpoint-ernally to know which element of the L b a y col-y

lection it’s currently referencing, and would use the erence to the L b a y passed in the constructor to cally

ref-the g t )method to retrieve the current object

The implementation seen in Listing 6 assumes thatyour collection array is indexed starting with 0 and iscompletely sequential

A Variant Iterator API

While the foregoing code is a complete

implementa-tion of the Iterator pattern as described by GoF, you

may find the four-method API a bit cumbersome If so,you can collapse n x ( , c r e t t m ), and i D n (

into just n x ( by having the latter either advance andreturn the current item from the collection or returnfalse if the entire collection has been processed

Listing 7 shows one way to write a test for this tion of the API

varia-Notice the simplified control structure for looping

n x ( returns an object or f l e, allowing you to per-e

form the assignment inside the w i ee loop conditional.The next few examples explore variations of the

Iterator pattern using the smaller interface As a

con-venience, change the L b a y : e I e a o ( method

to a parameterized FactoryMethod so you can get either

the four-method iterator or the two-method iterator(n x ( and r s t )from that single method)

class Library { //

function getIterator($type=false) { switch (strtolower($type)) { case ‘media’:

} }

3 protected $collection = array();

4 protected $first = true ;

5 function construct ( $collection ) {

6 $this -> collection = $collection ;

7 }

8 function next () {

9 if ( $this -> first ) {

10 $this -> first = false ;

11 $ret = current ( $this -> collection );

12 } else {

13 $ret = next ( $this -> collection );

14 }

15 if ( $ret && ‘library’ != $ret -> status ) {

16 return $this -> next ();

Trang 20

Here, L b a y : e I e a o ( now accepts a

parame-ter to select what kind of iparame-terator to return The default

is L b a y o I e a or (so the existing tests still pass

Passing the string m d a to the method creates anda

Oops! The dreaded test failure! What caused this?

Somehow, the first iteration was skipped—that’s a bug

To fix the error, return c r e t )for the first call of the

n x ( method

The code in Listing 8 corrects our logic error and vides a streamlined w i ee loop iterator

pro-Filtering Iterator

With Iterators, you can do more than just present each

item of the collection, you can also select which itemsare presented Let’s modify the L b a y : e I e a o (

to allow two additional iterator types (Listing 9)

The L b a y v i a l I e a or class should only ate over items that have a status of “library” (recall thatthe c e k u ( method changes the status to “bor-rowed”)

iter-The test in Listing 10 creates a new M d a instancea

and stores it in the variable $ vd The first highlighted

a s r E u l ) assertion verifies that the new item ispresent when iterating with L b a y v i a l I e a or.Next, the test uses the c e k u ( method and verifies

that the new item is missing from the display

The code to implement filtering (Listing 11) is verysimilar to the L b a y t r t r : e t ), except filtering

is done prior to returning the item If the current itemdoes not match the filter criteria, the code returns

5 $this -> lib -> add (new Media ( ‘second’ , 1999 ));

6 $this -> lib -> add (new Media ( ‘first’ , 1989 ));

7 $this -> assertIsA (

8 $it = $this -> lib -> getIterator ( ‘released’ )

9 , ’LibraryReleasedIterator’ );

10 $output = array();

11 while ( $item = $it -> next ()) {

12 $output [] = $item -> name ’-’ $item -> year ;

7 function construct ( $collection ) {

8 $this -> collection = $collection ;

18 $sort_funct ( null , null , $this -> collection );

19 $this -> sorted_keys = $this -> collection -> keys ();

20 usort ( $this -> sorted_keys , $sort_funct );

6 $this -> lib = new ForeachableLibrary ;

7 $this -> lib -> add (new Media ( ‘name1’ , 2000 ));

8 $this -> lib -> add (new Media ( ‘name2’ , 2002 ));

9 $this -> lib -> add (new Media ( ‘name3’ , 2001 ));

10 }

11

12 function TestForeach () {

13 $output = ‘’ ;

14 foreach( $this -> lib as $item ) {

15 $output = $item -> name ;

Trang 21

Sorting Iterator

An iterator can do more than show all or a portion of

the collection An iterator can also show the collection

in a specific order

Let’s create an iterator that sorts the MM d aa in the

col-lection by release date

For a test (Listing 12), add some M d aa instances with

dates older that those of the items added in the s t p )

method If the iterator works, these older items should

be sorted to the beginning of the iteration

This test uses the items in each iteration slightly

dif-ferently: instead of just appending the $ a e values in ae

string, a string is formed from both the $ a ee and $ e r

properties, which is then appended to an $ u p t array.t

The implementation of L b a y e e s d t r t rr is

nearly identical to L b a y t r t rr, except for one

additional line in the constuctor

class LibraryReleasedIterator extends LibraryIterator {

function construct($collection) { usort($collection, create_function(‘$a,$b’,

‘return ($a->year - $b->year);’));

$this->collection = $collection;

} }

The u o t )statement sorts the $ o l c i nn array prior

to iteration You can avoid copying all of the other codefor the class by simply inheriting from the

L b a y t r t rr class itself

Is it possible to use an external iterator to accomplishthis same sorted iteration? Yes, but you must pull a fewtricks to accomplish it See Listing 13

Key here is the creation of a utility function for

per-forming the sort The sorting function needs to haveaccess to the collection so it can fetch members forcomparison However, because the generated function

is used in a u o t ), you don’t have the option of ing the collection as an additional parameter Instead,you can use the trick shown in the code block above tostore a reference to the collection inside the functionprior to calling it with u o t )

pass-What you’re sorting is the list of keys for the tion When u o t )is complete, the keys will be sorted

collec-in order by the year attribute of each object collec-in the lection

col-In the n x ( method, an object in the collection is

accessed via the g t ) method, but indirectly through

the $ o t d k ys mapping If you recall the externalversion of the GoF-style iterator, arrays with gaps orstrings in the keys could be problematic This same trickcould be used for a simple external iterator to alleviatethe problem of gaps in the sequence of keys

SPL Iterator

No article on the Iterator design pattern and PHP would

be complete without discussing the “Standard PHPLibrary” (SPL) iterator

The w i e loop structure used so far is very compacte

and usable, but PHP coders may be more comfortablewith the f r a hh structure for array iteration Wouldn’t

it be nice to use a collection directly in a f r a hh loop?That’s exactly what the SPL iterator is for

(Even though this article has been written entirely for

5 $this -> lib = new PolymorphicForeachableLibrary ;

6 $this -> lib -> add (new Media ( ‘name1’ , 2000 ));

7 $this -> lib -> add (new Media ( ‘name2’ , 2002 ));

8 $this -> lib -> add (new Media ( ‘name3’ , 2001 ));

9 }

10 function TestForeach () {

11 $output = ‘’ ;

12 foreach( $this -> lib as $item ) {

13 $output = $item -> name ;

20 new StandardLibraryIterator ( $this -> collection );

21 $this -> iterator -> rewind ();

22 }

23 }

24 ?>

Listing 17

“I terator couples the object-oriented programming principals

of encapsulation and polymorphism ”

Trang 22

PHP 5, the following SPL code is the only code that

works solely in PHP 5, and then only if you’ve compiled

PHP 5 with SPL enabled Harry Fuecks wrote a nice

arti-cle introducing the SPL and covering the SPL iterator;

see hhttp://wwww sitepoint.com/ aarticle/php5-ss ttan

d

dardd libraryy.)

Using SPL is essentially a completely different way to

implement iteration, so let’s start over with a new unit

test case and a new class, the FF r a h b e i r ry, and

r w n ( k y )returns the current index of your

collec-tion r w n ( is like r s t ): iteration begins at the

start of your collection See Listing 15

Here we just implement the required functions

work-ing on our $ o l c i nn attribute (If you don’t

imple-ment all five functions and you add the i p e e t

I e a or to your class definition, PHP will generate a

fatal error.) The tests pass, and everything is happy

There’s just one problem: the implementation is

lim-ited to one style of iteration—sorting or filtering is

impossible

Can anything be done to rectify this? Yes! You can

apply the Strategy pattern and delegate the SPL

itera-tor’s five functions to another object

Listing 16 is a test for

P l m r h c o e c a l L b a yy

The only difference between this case and the test for

S l t r t r e t a ee is the class of the $ h s > i

attribute created in the s t p ) method That makes

sense: the two classes must behave identically

Listing 17 contains P l m r h c o e c a l L b a y.y

L b a y is extended to get the collection manipula-y

tion methods The SPL methods are added, too, all

del-egating to the $ t r t r attribute, which is created inr

r w n ( Below is the code for the

S a d r L b a y t r t r.r

The code in Listing 18 should look familiar:

essential-ly, it’s a copy of the five SPL functions from the

F r a h b e i r ry class The tests pass

OK, the code is more complex now, but how does it

support additional iterator types? Let’s add a test for a

“released” version of the iterator to see how additional

iterator types work in this design

The test case in Listing 19 should look familiar, too, as

it’s very similar to the previous “release” iterator, but

using the f r a hh control structure to loop

The new i e a o T p ( method (Listing 20) lets you

switch which style of iterator you want to use (Since

the iterator type isn’t chosen during the instantiation of

the object and because you can choose a different

iter-ator type on-the-fly by calling the i e a o T p (

method again, the code is actually implementing the

1 <?php

2 class StandardLibraryIterator {

3 protected $valid ;

4 protected $collection ;

5 function construct ( $collection ) {

6 $this -> collection = $collection ;

5 $this -> lib -> add (new Media ( ‘second’ , 1999 ));

6 $this -> lib -> add (new Media ( ‘first’ , 1989 ));

7 $output = array();

8 $this -> lib -> iteratorType ( ‘Released’ );

9 foreach( $this -> lib as $item ) {

10 $output [] = $item -> name ’-’ $item -> year ;

10 function iteratorType ( $type = false ) {

11 switch( strtolower ( $type )) {

22 $type = $this -> iterator_type ;

23 $this -> iterator = new $type ( $this -> collection );

24 $this -> iterator -> rewind ();

25 }

26 }

27 ?>

Listing 20

Trang 23

State pattern, rather than the Strategy pattern.)

You can easily implement RR l a e L b a y t r t r byr

extending S a d r L b a y t r t r and overriding ther

constructor to add the sorting of the incoming

array And with that you have a working

P l m r h c o e c a l L b a yy

Issues

Iterators are a nice way to standardize working with

col-lections of objects in your applications The examples

here have been based on arrays, but the ability to work

on non-array based collections with an identical

inter-face is powerful

The ability to use collections in the f r a hh control

structure is indeed cool The only unfortunate issue

with the SPL implementation is the significant potential

for namespace clashing with “I e a or” How much

PHP 4 object-oriented code has some sort of an

I e a or class as a base class for the libraries’ iterators?

Of those, how many define the five required methods

in the same capacity? Perhaps i p e e t FF r a h b e

would have been a less intrusive name If you choose touse the SPL, you should investigate the other support-

ed iterators, like R c r i e r a I e a or and ous other flavors

numer-F

FEEAATTUURREE

Available Right At Your Desk

All our classes take placeentirely through the Internetand feature a real, live instructor that interacts with each student through voice or real-time messaging

What You Get

Your Own Web SandboxOur No-hassle Refund PolicySmaller Classes = Better Learning

Sign-up and Save!

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

just by signing up for our training program!

New classes start every three weeks!

http://www.phparch.com/cert

To Discuss this article:

http://forums.phparch.com/233

Jason has been an IT professional for over ten years He is currently an application oper and intranet webmaster for a Fortune 100 company He has written several tutori- als and articles for the Zend website, and has recently contributed to the Wrox “PHP Graphics” handbook He is also the author of “php|architect’s Guide to PHP Patterns He resides in Iowa with his wife and two children Jason can be contacted at

devel-j

The Iterator Pattern

Trang 25

FEEAATTUURREE

Whether you need certain functionality for a big

software house or single developer, you want

to find good libraries that you can use,

direct-ly, via Application Programming Interfaces (APIs)

with-out having to modify the code This is possible by using

Object Oriented development and Pattern Design,

which are both commonly used to create re-usable

code for common tasks

What Do We Need to Manage?

The first objective of our library is to be able to managepermissions for many different types of projects Themain elements are users and permissions As far as usersare concerned, you usually need to manage groups androles Permissions are created as a flat list whereby eachapplication using the library shall be able to have itsown, independent permissions list Those permissionsmust then be applied to objects (e.g read or write per-mission on a specific document) To do this effectively,

an entity category of objects was introduced, thatallows grouping objects by type So, we end up with:

• Users, groups and roles

• Permissions

• Objects and object categoriesUsers can be part of one or more groups, and eachgroup can have a parent group, to allowing the cre-

A generic library to manage permissions is what you

would want for many projects It should have a generic

interface to populate the permissions database and

man-age permission needs so that they can be easily

personal-ized To achieve this, we created a PHP library generic

enough to satisfy the needs of most projects and also

pro-vided a Flash user interface to manage permissions that is

ready for deployment with any web project.

for Permission Management

by Simone Grassi and Bernhard Gaul

REQUIREMENTS

Other Software Apache, MySQL, Flash plug-in

Code Directory permissions

Trang 28

ation of group hierarchies Later, we will see why we

need roles and how they associate permissions to

objects

In an application that requires permissions, you will

usually have many different objects to which these

per-missions may be applies Each object will probably have

a unique key (database primary keys) within its

catego-ry If we use object categories it will allow us to apply

permissions to single objects by specifying the object

category as well as the unique id of the object The

per-missions database will use the same unique id of the

object that is used in the application database Our

library assumes that these unique identifiers are

inte-gers

Permissions to Users and Groups

A user can be assigned permissions, directly If, for

example, a RR AD permission is assigned to a user,

direct-ly, he will be granted this permission in any case, on all

objects of any possible object category Groups, on the

other hand, are useful in different ways: first to allow

the creation of hierarchies, using subgroups; second, if

a set of permissions is assigned to a group then every

user associated with the group will be granted those

permissions It will be enough to change the

permis-sions assigned to the group to change those associated

with the individual users

How do you associate permissions with users and

groups? There are three different possible ways:

• Directly: the assigned permission is valid on

all objects of all categories

• Relative to a category of objects: the sion applies to all objects that are part of thiscategory of objects

permis-• Relative to a single object: valid only for thespecific object within a specific categoryThe objective is to satisfy the requirements of differ-ent scenarios As an example, let’s imagine we have anapplication that manages users’ access to documentswithin different folders In this scenario, there are atleast two categories of objects: documents and folders.Assignment of a permission, directly to a user or group

of users, is useful, for example, to allow the tor to have write permissions on all folders and docu-ments (that is on all objects of all categories of objects).Assigning permissions to a single category of objectsallows, for instance, assigning read and write permis-sions to a single user on all folders, creating a sort offolder administrator Finally, assigning permissions on asingle object allows gives specific access—like read orwrite—on a single folder (e.g a specific user may onlyaccess a specified folder with write permission)

administra-Permissions can be assigned to groups in the sameway as to users—that is directly to the group, relative to

a specific category of objects, or to a single object Thisallows the creation of permission profiles, and usersassociated with a given group will inherit this profile(there could be, for instance, a group of folder admin-istrators or document administrators)

Figure 1

Trang 29

Why Groups are Not Enough?

We have seen that we can assign permission to both

users and groups (in a general way, to all objects, only

on a category of objects or on a single object) For

many projects, though, this will not be enough What

is needed is the possibility to assign a set of permissions

to a user or group, on a specific object or category of

objects To account for this need, we introduced the

concept of roles

Take a simple example: within a sample application

where users use and manage folders and documents,

there could be the need for a publisher role, defined as

a user allowed to “publish” documents—adding

docu-ments to folders A publisher would need to have

access permission on all folders to create new

docu-ments within them This role could be assigned to all

folders, in which case the role is assigned to the user

relative to a category of objects (the folder category)

Or, a user could be defined as publisher for just a single

folder In this case, the role is assigned to the user only

on the specific object (the folder that is part of the

cat-egory folders) As you can see from Figure 1, the

differ-ence between groups and roles is how those entities are

related to users A user is part or not part of a group,

but a role is assigned to a user relative to an object

cat-egory (or relative to a single object)

Note that Figure 1 does not show the “object” This

entity is undefined, as every application will have their

own entities that will act as objects We provided 3

fields, though, to associate object categories with

objects: oo j c _ d t b ee, o j c _ d f e d a e ande

o j c _ d d s r p i n f e d a e For each object cat-e

egory, o j c _ d t b ee is the name of the table that

stores the objects that are part of this category The

o j c _ d f e d a ee field stores the name of the field

that is the primary key of the object table Finally, the

o j c _ d d s r p i n f e d a ee field stores a tion (or title) of the object The use of those fieldsallows the developer to retrieve information about asingle object, directly from the table created by theapplication that uses the permission library

descrip-The Library

Like many other libraries, our permissions tion is a single class and can be used by “client”-soft-ware through a single API All data is stored in a data-base (we used MySQL), and PEAR::DB_DataObject isused as DB Abstract Layer which makes it easy to movethe library to other databases Configuration is simple,and a few parameters are enough to enable DataObject

implementa-to communicate with the DB

An Example Application: Folders and Documents

The code included with php|architect allows you to seethe library in action The example implementationshows permissions management in a small application.All we need to manage are folders and documents Wehave users, and each of them has different needs Toaccommodate these needs, we will use the differentcapabilities of the library The first thing that

e a p e p p (see the zip file that accompanies this arti-p

cle) needs to do is instantiate the class:

$auth = &new authorization_manager($username);

Passing the username is sufficient; it allows the class toretrieve permissions information about that user Still,you can see the API in action:

docu-w i ee, an array is prepared, it contains the d c m n _ d,d

d c m n _ a e and information about permissions Ase

you can see, to determine if the current user has R A

permission, we just call a t o i e ) The first ter is the requested permission, and the second param-eter is the object category (O J C _ Y E D C M NT) Theobject id, in this situation, is the d c m n _ d.d

parame-The API would return t ue if the current user has thispermission, false otherwise In the example, you cansee two tables: in the first, a list of folders; in the sec-ond, a list of documents from the current folder Thepermissions are represented by R AA (read-write-add ele-ments) for folders and RW (read-write) for documents.When the letter x is present, it means the current userx

does not have this permission

able to manage permissions

for many different

types of projects ”

Trang 30

Changing the user, by using the drop-down menu,

you can see how different permissions are assigned to

different users See the database entries to fully

under-stand how this is implemented, with groups, roles, and

direct permissions

Let’s see, user by user, how permissions are assigned

The ss p r s rr user has direct permission to R AD,

W I EE and A D E E E TS on everything

The d v l p rr user has permissions on documentsinside source folders This is implemented by assigningthe publisher role to this user

The f l e a m nn user has all permissions on all ers This is made possible by assigning the publisherrole to the user, but not to a specific object It isassigned to the f l e s object category This gives thes

fold-user permissions on all folders Note that this fold-user has

8 <form method=post action=”example.php” name=”perm_library”>

9 <a href=”example.php”>List of Folders</a><br/><br/>

10 <?

11 $users = array( 0 => ’superadmin’ , ’folderadmin’ ,

12 ‘publisher’ , ’reader’ , ’developer’ );

13 print ‘Select user:<select name=username ‘

14 ’ onChange=”javascript:window.document.forms[0].’

15 ’submit();”>’ ;

16 for ( $i = ; $i < count ( $users ); $i ++)

17 print “<option” (! strcmp ( $users [ $i ], $username )?

18 ‘ selected>’ : ’>’ ) $users [ $i ] ’</option>’ ;

26 // View the list of folders

27 $fold_db = &new DataObject_Folders ();

33 if ( array_key_exists ( ‘folder_id’ , $_REQUEST ))

34 $actual_folder_id = $_REQUEST [ ‘folder_id’ ];

35 while ( $fold_db -> fetch ())

36 {

37 $folders [ $i ][ ‘folder_name’ ] = $fold_db -> folder_name ;

38 $folders [ $i ][ ‘folder_id’ ] = $fold_db -> folder_id ;

39 $folders [ $i ][ READ ] = $auth -> authorize (

40 READ , OBJECT_TYPE_FOLDER , $fold_db -> folder_id );

41 $folders [ $i ][ WRITE ] = $auth -> authorize (

42 WRITE , OBJECT_TYPE_FOLDER , $fold_db -> folder_id );

43 $folders [ $i ][ ADD_ELEMENT ] = $auth -> authorize (

44 ADD_ELEMENT , OBJECT_TYPE_FOLDER , $fold_db -> folder_id );

50 $doc_db = &new DataObject_Documents ();

51 $doc_db -> father_folder_id = $_REQUEST [ ‘folder_id’ ];

52 $doc_db -> find ();

53 $i = 0

54 while ( $doc_db -> fetch ())

55 {

56 $docs [ $i ][ ‘document_name’ ] = $doc_db -> document_name ;

57 $docs [ $i ][ ‘document_id’ ] = $doc_db -> document_id ;

58 $docs [ $i ][ READ ] = $auth -> authorize (

59 READ , OBJECT_TYPE_DOCUMENT , $doc_db -> document_id );

60 $docs [ $i ][ WRITE ] = $auth -> authorize (

61 WRITE , OBJECT_TYPE_DOCUMENT , $doc_db -> document_id );

62 $docs [ $i ][ ADD_ELEMENT ] = $auth -> authorize (

121 if ( $auth -> authorize ( READ ,

122 OBJECT_TYPE_DOCUMENT , $docs [ $i ][ ‘document_id’ ]))

123 print ‘R’ ;

124 else

125 print ‘x’ ;

126 if ( $auth -> authorize ( WRITE ,

127 OBJECT_TYPE_DOCUMENT , $docs [ $i ][ ‘document_id’ ]))

Trang 31

no permission on individual documents Even if a user

has permission to an object category, he does not

auto-matically receive the same permission on objects

with-in this category

The pp b i h rr user is a bit different from the f l e

-a m nn He has the role of publisher on all folders, but

this role gives only R AD and A D E E E TT permissions

So, the publisher can add elements and access all

fold-ers, but cannot modify the folder itself (lmoving the

folder elsewhere, for example)

The v e er user has R AD permission on all This

per-mission is granted through group membership V e e

is part of the G O P V E E SS group, which is given R A

permission on both object categories (folders and

doc-uments)

Figure 2 shows the list of users s p r d in is

select-ed, and the relative permissions, directly assigned tothis user are shown Figure 3 shows a more complexuse of permissions, as used in a real application TheFlash GUI shows the object category information Foreach of them, you can see which permissions areassigned to users, through roles, groups or directly InFigure 3 C R _ C I T is the selected object category NoT

users or groups have relations with C R _ C I TT Onlythe A e d MM i AA m n s r t r RR le has been assigned

to (at least) one user, relative to C R _ C I TT

We have seen how to assign permission in many ferent ways, directly to users, using roles, and throughgroups This scheme grants flexibility and can be adapt-

dif-ed to many applications with good initial planning Thedeveloper must determine which permissions will beneeded within his application, differenciating betweenobject categories, groups, and roles Again, it’s impor-tant to define the correct list of permissions After thisscheme is created it’s straightforward to add a t o -

i e ) calls in your code to let your code reflect the

planned permission scheme

Authorize: Our Application User Interface

The current user needs to be identified to the librarywhen the application begins execution After this,requests for the permissions of the current user can bemade via a single method, called a t o i e ) Everykind of authentication can be used to identify the user,the user table is very general, and can be shared withyour preferred authentication library The authorizemethod can be called in three different modes:

A t o i e P R I S O _ E I E): This specifies onlythe requested permission Authorize returns true onlywhen the current user has this permission, but notwhen it is only relative to an object or on an object cat-egory The user must own the permission outright (foreach object type) This is typically used to create

“super” users

A t o i e P R I S O _ E I E O J C _ Y E) :Determine if the current user has been granted the P R

M S I N D F NE permission on a specific category ofobjects (called O J C _ Y EE) For example, a user could

NO OT TE E::The Flash client is provided

as compiled file only, but some tation details, such as the applicationmodel for validating input fields using reg-ular expressions, can be found onBernhard’s homepage athttp://www.bgxcomponents.com

Trang 32

implemen-have WW I EE permission on all documents (given that we

have a category of objects that includes all types of

documents)—this will grant W I EE permission on all

documents, but not on other categories of objects, like

folders, assuming we defined folders as a different

cat-egory of objects

A t o i e P R I S O _ E I E O J C _ Y E O J C _

D): You can determine if a given user has access to a

sin-gle, specific object To do this, you must specify both

the object category (O J C _ Y EE) and the unique id of

the object (O J C _ D) The D O J C _ D is unique only inD

the set of objects included in the O J C _ Y EE category

of objects

Common GUI for a common Library

So far, we’ve only talked about building a good library

that provides for the needs of many different

applica-tions, but what about administering the data? A

com-mon GUI, pre-built and easy to deploy, would be very

helpful Again, the objective is to provide a ready-made

package you can plug into your own application We

decided to provide this in form of a single, compiled

Flash file that communicates with the server via XML

Reasons to use Flash

For simple forms (e.g an ordering form, or even

shop-ping cart solutions) stateless HTML based GUIs that are

(re-)constructed and downloaded with every data

exchange are fine

For more complex applications like our permissions

editor, however, a solution that can maintain state on

the client and could also take care of some of the more

complex GUI components needed, like editable tree

structures, would be a distinct advantage

Flash provides rich, platform independent client

capabilities within a lightweight vector-based, easily

downloadable and well distributed runtime

environ-ment While Flash has always been very well known for

its graphic and animation capabilities, for our

permis-sions application it was more Flash’s extensive scripting

capabilities that were key In particular, Flash allows:

• data to be organized in such a way that onlysmall chunks need to be loaded as the userrequests them

• the use of complex data objects such asuser-permission trees on the client

• client-side state retention

• the creation of complex form based GUIs

• binding data to a large set of readily able GUI components like lists, combos, andtrees that can also be customized

avail-• the tracking of changes, client side, and mission of only data that has changed (e.g when saving)

sub-Flash has evolved into a true rich internet applicationarchitecture, meaning parts of the business logic canreside on the client while exchanging data only withthe server

Client-Server Communication

The API used to communicate between the Flash clientand the server application is generic so that the Flashclient could be swapped for any other client that cansend and retrieve data via HTTP and understands XML.How is this done? On the client side, we have creat-

ed a PHP page to which predefined Q e y t i g andg

F rm parameters can be sent to request certain types ofdata (e.g users filtered by a search parameter) in XMLformat The page can also receive data to be saved tothe database

For our Flash file, we have provided an external tings file which you can use to specify the exact URL forthe different calls By default we assume that the Flashfile resides in the same directory as the x l c e t r p p

set-page that processes the calls, but you could change theURL to whatever suits you The X L A I d c filec

describes the calls that can be made to the server Youcan try them out by simply entering the URLs into theaddress field of your browser

This document also describes the structure of theXML that is returned for each call The client is expect-

ed to populate an appropriate GUI with the submitteddata, and handle changes To submit changes to theserver, an XML string has to be sent as a form parame-ter to a PHP page that will handle the save request.Within this XML document are sections for changed,new and deleted data When notifying of new orchanged data, the whole object (e.g a user or groupdefinition) is sent, but in the case of a deletion, we sendonly the ID of the object in question This way you get

a very lightweight communication model for dataexchange, requiring only the minimum data to be sent

at a time

dynamic web pages - german php.node

news scripts tutorials downloads books installation hints

www.dynamicwebpages.de

sex could not be better |

Trang 33

Client Customizations

With the ss t i g ml file from which Flash reads the

URL definitions for the commands, you can also control

the appearance of the client (to some extent) Primarily,

you can cjamge all of the labels that appear in the GUI,

allowing you to change the language from English to

whatever you need There are also some CSS-like style

definitions for the graphical appearance that you could

change, and finally regular expression validations for

various field types For example, you might want to

change the input requirement for passwords from

“^[a-zA-Z0-9]+$” to something else

Conclusion

The presented library should suit many applications,

allowing an immediate and easy implementation via

the permissions API Authentication types are not

pre-defined and can be created as needed A flexible and

easily deployable Flash GUI is provided (in the code

archive) to administer the permissions library database,

using a generic XML “gateway” that could be used to

create other front ends if needed

F

FEEAATTUURREE

PHP Library for Permissions Management

To Discuss this article:

http://forums.phparch.com/231

Simone is about to start a PhD at Trinity College in Dublin on Model-Driven Architectures next Obtober Bernhard is a multimedia developer and general user interface specialist based in Dublin.

EDITOR’S NOTE: The code provided by the

authors, for this article, is very extensive, and the submission contains binary files (the Flash client, for example) As such, we have decided to refrain from printing the entire code, and have instead included it only in the code archive (zip file) that accompanies this article.

Trang 34

SITEWORX control panel

/mo SMALL BIZ $ 21 95

NODEWORX Reseller Access

All of our servers run our in-house developed PHP/MySQL

server control panel: INTERWORX-CP

INTERWORX-CP features include:

- Rigorous spam / virus filtering

- Detailed website usage stats (including realtime metrics)

- Superb file management; WYSIWYG HTML editor

INTERWORX-CP is also available for your dedicated server Just visit

http://interworx.info for more information and to place your order.

WHY NEXCESS.NET? WE ARE PHP/MYSQL DEVELOPERS

LIKE YOU AND UNDERSTAND YOUR SUPPORT NEEDS!

ORDER TODAY AND GET 10% OFF ANY WEB HOSTING PACKAGE

VISIT HTTP://NEXCESS.NET/PHPARCH FOR DETAILS

D e d i c a t e d & M a n a g e d D e d i c a t e d s e r v e r s o l u t i o n s a l s o a v a i l a b l e

/mo N EX R ESELL 2 $ 59 95

7500 MB Storage

100 GB Transfer Unlimited MySQL Databases Host Unlimited Domains PHP5 / MySQL 4.1.X NODEWORX Reseller Access

NEW! PHP 5 & MYSQL 4.1.X

PHP4 & MySQL 3.x/4.0.x options also available

We'll install any PHP extension you need! Just ask :)

MONEY BACK GUARANTEE

FREE DOMAIN NAME

WITH ANY ANNUAL SIGNUP

4.1.x

3.x/4.0.x

Ngày đăng: 24/01/2014, 14:20

TỪ KHÓA LIÊN QUAN