Here are the slides to the talk “PHP Development with Oracle” I presented at PHP|Works in Toronto on Friday, September 24th, 2004. The presentation is in Microsoft Power Point Slide show format.
PHP Archive
PHP Development with Oracle
Posted 9/24/2004 By JasonDocumenting PHP Applications
Posted 9/24/2004 By Jasonphp|works has arrived!
Posted 9/22/2004 By JasonThe php|works conference in Toronto is officially underway. They have WIFI access from the atrium (and from my room, since if faces into the hotel ). Tested it out from the conference rooms as well, so all is good with internet connectivity.
Looks like a very good line up of speakers. Went out to dinner with a few of the other speakers last night and had a number of engaging conversations ranging from trends in rich client-side applications to baby care techniques (seems like there are quite a few new PHP fathers, and I abandon my wife at home with a two year old with 103 degree temp ).
My presentations are tomorrow at 2:00—Documenting Source Code—and Friday at 9:45—PHP and Oracle. Both of them are of course biased towards my perspective of using PHP in an enterprise development environment.
Hope to see you there. Drop by and see me if you are here.
Marcus Blogs!
Posted 9/1/2004 By JasonMarcus Baker (author of SimpleTest php unit testing software) now has a blog at http://www.lastcraft.com/blog. Right out of the gate he has several thoughtful and insightful essays reminiscent of his many similar posts in the Advanced PHP Programming forum on SitePoint.
His post Design Drool brings up some of what I have only been vaguely hinting at in some of my posts, the mindset of a good programmer. Marcus does a great job of summarizing our own internal hidden agenda…and he was spot on with that old sprite based spaces invaders game . Even brought up the memories of the first program I was paid to write: a scheduling program for a machine shop. Boy was that ever a nightmare to try to cram both the BASIC source code and the data into 64k 😯 !
js does xmlrpc
Posted 8/29/2004 By JasonToday I explored some new (to me) technologies to support a feature I was playing with. On a complex form representing a row being edited in a database, I had several 1-to-many relationships that I wanted to edit (i.e. make additions to) without submitting the main form. It is an intranet application, so I have the ability to rely on the fact that users will be using IE, and js will be enabled.
From the usual bag of tricks, my initial thought was you could have javascript submit a hidden form in a non-visible frame, and have the results come back with some onLoad() js that would update the main form (even did a little flow diagram, will attach at the end of the post). But I remembered Harry mentioning using js and php to communicate by serializing data in mutually compatible formats. This is the scriptserver project which he blogged about a while back. Harry also sent me a link to this js library to implement xmlrpc.
I have to admit that I have not played around with xmlrpc to date (at least in terms of actually doing anything with the technology, I have read enough to have the gist of xmlrpc and SOAP). This is mainly because I kept asking my Unix admin at work to compile php with the xmlrpc extension, and he always complained that he could not get the extension to compiled on HP-UX. I have finally started to push for some Linux web servers at work, so that will not persist as an issue in the future. Anyway, I decided to play around with this javascript xmlrpc library and see what I could come up with.
Read the remainder of this entry »
Creative use of Data:Table
Posted 8/22/2004 By JasonHarry recently blogged about the Data:Table component I wrote for WACT. His post talked about the common method of using the data:table tag, i.e. feed it a data set and have it generate a table, perhaps using some declarative markup in the template to modify the results. Used in this context, you can output nicely formatted HTML tables with minimal amounts of code.
I had an interesting problem recently that challenged the way I used the data:table component. I needed to display 18 months of data in a table. Each row represented a different item, and the months were to be laid out in the columns of the table.
When I started to work with the table, I initially started with the traditional style of putting all of the tags specifying the layout in the template. With just two months of data, it might have looked something like this:
<data:table from="tableData" autogen="n"> <data:column name="itemdesc"> <data:header>Description</data:header> </data:column> <data:group> <data:header>{$m1label}</data:header> <data:column name="m1val"> <data:header>Value</data:header> <data:cell>{$m1val|number}</data:cell> </data:column> <data:column name="m1val2"> <data:header>Input</data:header> <data:cell><input type="text" name="{$m1key}" value="{$m1val2|number}"></data:cell> </data:column> </data:group> <data:group> <data:header>{$m2label}</data:header> <data:column name="m2val"> <data:header>Value</data:header> <data:cell>{$m2val|number}</data:cell> </data:column> <data:column name="m2val2"> <data:header>Input</data:header> <data:cell><input type="text" name="{$m2key}" value="{$m2val2|number}"></data:cell> </data:column> </data:group> </data:table>
You can see where the group of columns for month two is just a cut and paste with minor tweaks to the variables. While this worked fine, I knew this was not what I wanted to maintain for the long run. Ideally I could use a loop to specify the templates for a single month once and have it increment through the values, but the data:table component does not support other WACT looping structures inside of it (a list component), and WACT templates do not support variable variables that would be required to iterate over the months.
Read the remainder of this entry »
Stealth PHP Singletons
Posted 8/18/2004 By JasonI explained a bit of my code in a post up on SitePoint that reminded me of one of my favorite bag of php tricks: associating a superglobal key reference with a class variable.
<?php
$this->_stack =& $_SESSION[NOTIFY_SESSION_KEY];
?>
This has the effect of making a “stealth” static member, as well as effectively making the class a singleton (i.e. every instance of the class will access and manipulate the same data, and is therefore equivalent).
The context of my post was explaining a session based user notification queue. I have been using WACT recently, so I included a helper method to return the queue as an ArrayDataSet.
So without further ado, here is the test case and code.
Read the remainder of this entry »
Not the last lastcraft
Posted 7/31/2004 By JasonMarcus Baker, author of SimpleTest and oop/pattern guru extraordinaire at the SitePoint Advanced PHP forum has just had release 1.0 of Bryn Reuben Baker, a strapping young man of 8 lbs. 4 oz. born at 1:48AM July 30th, 2004.
Congratulations Marcus! May Bryn’s tests of you always result in a green bar
Testing MVC Actions classes
Posted 7/29/2004 By JasonIn developing web applications with a Model-View-Controller “flavor”, I find that in the Controller portion of the architecture I invariably end up with “Action” classes. These are implemented as a Strategy pattern (i.e. a family of algorithms, encapsulated as classes with the same method signature, making them interchangeable). In my code, I end up with something like:
<?php
class Action {
function Action() {}
function Perform() {}
}
?>
And there might be some kind of an application controller, e.g.:
<?php
switch (strtolower($_REQUEST['action'])) {
case 'dosomething':
$action = 'DoSomething'; break;
default:
$action = 'DefaultAction';
}
if (!class_exists($action)) {
require_once ACTION_INCLUDE_DIR.$action.'.php';
}
$action_instance =& new $action;
$action_instance->perform();
?>
Now inside these classes they usually need to access various model classes which in the past I had done by simply creating an instance of the desired model as a local variable in the Perform() method. This however, makes the code very hard to unit test.
Read the remainder of this entry »
New Data Mining Article Published
Posted 7/21/2004 By Jasonphp|architect’s July issue contains my latest article on the topic of Data Mining with PHP.
The article shows examples of several graph styles (including the rarely seen radar chart!), and uses the PHP bug database as a data set to mine.
Because php|a chose to make this the sample article for the month, it is available for download as a pdf file here.
<soapbox>
The data set is a little old (December 2002 timeframe) because this was actually written as part of the PHP Graphics Handbook, a book I co-wrote for Wrox, approximately one month before they went bankrupt :evil:. But, as a bonus, it is available for you to peruse now :)! Wrox decided I wrote too much and edited out 1/3 of my original content before publication, and this case study represents about half of what was cut.
</soapbox>
Aaaarrrgh! Hard to trace programming errors.
Posted 7/20/2004 By JasonI just spent an hour debugging the old “never forget to exit after sending your header redirect” error.
PEBKAC (my chair and my keyboard )…
SAFETY TIP:
Whenever you have code that looks like this:
<?php
header('Location: '.phpself());
?>
it must be followed by
<?php
exit;
?>
to prevent hard to track down unexpected results.
Introducing the RUHA Lib
Posted 7/15/2004 By JasonBy popular request—or at least by Harry’s request—the Really Ugly Hack Authentication Library.
First a little preface:
This library was designed a couple of years ago to make up for the lack of NTLM authentication for apache. We—my system administrator and myself—tried several flavors of “mod_ntlm” projects for apache. We were not able to successfully compile any of these against Linux (let alone the HP-UX 10.20 production environment ). We tried to contact several of the maintainers without success, and so gave up the quest. This solution probably does not have very wide applicability, but we already had both Unix/Apache and Windows/IIS servers up and running, plus our staging process required users to have IE which supports NTLM authentication out of the box (as does Mozilla and Firefox now) so it did suit my needs.
BTW, if anyone knows of a working mod_ntlm module for apache now, please comment :).
My early background in web programming (prior to PHP enlightenment) was in ASP on IIS. Under this scenario, turning on security on the directory allowed you to pull the NT user name from the server variable…very handy :). Knowing this was possible, I devised a scheme were a PHP script on Apache would redirect to an ASP script on another IIS server in a NTLM protected directory, which would return the user id encrypted for the PHP script to decrypt. This scenario worked for the most part, but occasionally the user name got garbled in decryption, so I resolved to try this trick multiple times, and if I got the same result back twice in a row, I considered it golden.
Visually, this is how it looks:
Read the remainder of this entry »
Happy Birthday PHP5
Posted 7/14/2004 By JasonAutomating Testing of NTLM Secured Sites
Posted 7/13/2004 By JasonI have a security mechanism that I coded up several years ago. It relies on NTLM Authentication (on a remote IIS server via redirects) and can be implemented in any php script on my Unix/Apache box using three lines of code:
<?php
require_once 'the_lib.php';
session_start();
use_scrty('Application Identifier');
?>
It checks the NTLM authorized user against a database of user id’s that are authorized to access applications, and what access levels they have. If the user is not authorized, it will show an error message and exit. This scheme has worked great for me for ages.
Recently I have been doing Test Driven Development (TDD), and my favorite PHP unit testing library—SimpleTest—does not support NTLM Authentication (nor would I want to ask Marcus to implement this mess). Plus, I am not particularly interested in hard coding my NT Domain user name and password into testing scripts.
So what is left to do? Add a back door to bypass security for the test script. In doing this, I would like it to be as secure as possible while breaking security ;). What I have done is allow an additional url parameter that if present, is tested to see if it matches a md5 hash of the current unix timestamp, salted by the mtime for the directory in which the application lives. When I find a match, I insert enough data into the session to appear to have already passed the authentication. This parameter ought to be random and unguessable by my reckoning (at least by any user who does not have access to the web servers file system, for which you have other bigger problems already). Any holes in this scheme? Are there better alternatives available?
<?php
/**
* check for test user authentication and require security
* @return void
*/
function check_auth_user() {
//if testauth is a md5 hash of the current unix timestamp within the past 2 seconds
$mtime = filemtime('.');
$now = mktime();
if (array_key_exists('testauth', $_GET)
&& ($_GET['testauth'] == md5($now.$mtime)
|| $_GET['testauth'] == md5(($now-1).$mtime)
|| $_GET['testauth'] == md5(($now-2).$mtime)
)
) {
$_SESSION['scrty_data']['scrty_appl'] = APPL;
$_SESSION['scrty']['valid_login'] = true;
$_SESSION['scrty']['appl_acss'] = true;
$_SESSION['scrty']['info'] = array(
'NAME_FIRST' => 'Anonymous'
,'NAME_LAST' => 'User'
,'ACSS_LEVEL' => 'GENERAL'
,'LOGIN_IDFTN' => 'TESTUSER'
);
}
use_scrty(APPL);
}
?>
User Input Validation
Posted 7/6/2004 By JasonI will admit that I am a bit lazy about user input validation. This stems from the fact that:
- Most of my development is for intranet use
- I generally use Oracle for a back end, and tend to pass parameters as bind variables
The intranet development means that my users are more interested in using the web page to get their job accomplished than they are in hacking the page. A PHP Fatal error message is more likly to result in a support call than in lost business. Also, it is much easier to track down who is causing problems on a corporate network than on the internet, and probably the repercusions would be stronger as well.
True database bind variables also protect you from SQL injection. The problem I have is that perhaps I rely on this feature a bit too much, as it creeps into my writing of articles, where I use MySQL or Postgres, and the ADOdb library is just emulating bind variables with string substitution.
Which leads me to the gist of this post: easy data scrubbing with type casting. Here is some example code from an article I am writing, where I am able to assume the bug_id will be an integer.
<?php
/**
* validate a user passed parameter is an actual bug id
* @param string $parm the index of the $_GET request array to check
* @return mixed the integer bug_id if found, otherwise false
*/
function check_passed_bug( $parm ) {
global $conn;
//not indented because the end of the heredoc must be the first char
$sql = < <<EOS
SELECT COUNT( 1 ) AS cnt,
`id`
FROM `bugdb`
WHERE `id` = ?
GROUP BY `id`
EOS;
if (array_key_exists($parm, $_GET)) {
//here is the type cast on the input
$bug_id = (int)$_GET[$parm];
$rs = $conn->Execute($sql, array($bug_id));
if ($rs && !$rs->EOF) {
$row = $rs->fetchRow();
if (1 == $row['cnt']) {
//if found return the id
return (int)$row['id'];
}
}
}
//otherwise return false
return false;
}</>
?>
The type cast certainly is much less expensive than something like regex based validation. So what is the verdict–Elegant solution or cheap hack, frought with SQL injection danger?
php|works
Posted 7/5/2004 By JasonI am going to be a speaker at the php|works conference in Torono this September.
The two topics I am presenting on are: Developing in PHP using Oracle, and PHP Documentor.