PHP

php.communityshirts.com?

I wonder how hard it would be to create a service, targeted at smaller groups (like the PHP Women) to make the distribution of their t-shirts easier.

I know there’s sites like CafePress and Zazzle out there that let you set up custom stores with custom shirts on them, but a more community-centric site might be nice too. The shirts could even be tagged with the conference they were given out at so people could “collect them all” if they wanted. php.communityshirts.com anyone?

Any comments/suggestions/flames on the topic? Would this even be something that would be used?

ZendCon07: The Story So Far

So it’s two days in to this year’s ZendCon and things are already better than ever. It just feels like there was that little bit of extra effort put into things this year and it shows. There’s tons of great talks and lots of cool people around to meet – but official (like those from Zend) and the more unofficial – like the members of the PHP Women group.

It’s day three now (I’ve been slacking on writing my posts this time) and I’ve already had more knowledge crammed into my head than I’ll ever remember, but I’m enjoying it. It’s nice to balance talks like “Extending PHP” talk from Sara/Wez/Marcus with things like Terry’s talk “The Internet is an Ogre: Finding Art in the Software Architecture”. Everything’s been good so far, and I’m looking forward to today’s talks. I’m planning on hitting up a few more than yesterday (sleep does wonders for the attention span), so we’ll see how things are at the end of today.

I know I mentioned in it a previous post, but one of the coolest things about coming to a conference like this – really any PHP conference that’s out there – is the chance to meet people. The trading cards this year are an effort to jump-start this kind of networking. Honestly, I can’t day I’ve seen a group of people at a table at lunch (or breakfast for that matter) just sitting around and not talking all that much. That is, of course, unless they’re laptops open and on IRC (*cough*). It’s wonderful to see this kind of participation – people talking about anything and everything: where they’re from, what they do, something fun their working on, etc. There’s even some out there arguing the finer parts of certain PHP-related projects.

It’s wonderful to see such a thriving, vibrant community surrounding this great “little” language of ours. It’s a great mix of both those experienced, beginner and everyone in between and it comes out the other side a nice, rounded whole.

So, if you’re here at the conference and you’ve been a little timid up until now, be bold – step out and meet people. Talk to anyone, pass out business cards or come grab a free t-shirt from the PHP Women. I’ll have my PHPDeveloper.org t-shirt on today and some extras floating around with me, so if you spot me and want a shirt, just let me know!

The Close-Knit PHP Community

One of the nice things about conferences is getting to meet people that you’ve only talked to online and meeting those you’ve never talked to before. No matter what, though – at a PHP conference – you’re just about guaranteed to meet someone you’ve heard of or read something online by.

A few of us were sitting around at the hotel bar tonight and the comment was thrown out (thanks Elizabeth) about how small the PHP community is. Not in the number of people in it, but in how it feels. Several other communities have their divisions and factions all around the world, but it seems like the PHP community has bridged those gaps and seen its way to making more of a unified whole. A little while back (on Ben Ramsey’s blog I think) there was a mention of another conference attendee that found it amazing that he was sitting at the same table with “the cool kids” of the PHP community and that they were just like any other developer.

In my opinion, it’s things like this that make the PHP community one of the best out there. It’s just as large as any of the other language groups on the web, but it still manages to keep that feeling of closeness that others have lost. The community pulls together to help with projects on the language (like the upcoming PHP 5.3) and with pushing their own applications to their limits. People offer help and, sure there are times of disagreement and code gets tossed out, but overall, the PHP community is a pretty friendly place.

It’s a place where the people you read about in daily blogs (like Chris Shiflett, Wez Furlong, Sara Golemon, etc) aren’t these “higher developers” off doing their own thing away from the rest of the community. They’re right there with the rest of us, hacking at code and fixing those bugs to help make PHP’s slice of the web an even happier place to be.

If you happen to be at this year’s ZendCon (going on now) don’t be afraid to jump right into the conversations. As the speakers questions – trust me, they love ’em – and get to know others in the group here for the week. Not only could you make connections with other developers that live all over the world, but you could make some good friends in the process.

Book Review: Packt’s “PHP Web 2.0 Mashup Projects”

I recently received a great little book from Packt Publishing that’s a bit out of the norm for some of the PHP-related books these days. A lot of them tends to rehash the same details over and over again or focus too tightly on one particular aspect of the language to get much value from a wide audience range. This new book (PHP Web 2.0 Mashup Projects), however, takes PHP and applies it to one of the more popular topics of the times – mashups – and, via five difference projects, shows how to make your code place nice with the outside world.

Shu-Wai Chow introduces mashups first by talking about the importance of the sharing of data on the web and some of the methods that they will use to create the mashups in the book. From there, it’s all about the examples and their technologies:

  • Buy it on Amazon – creating a simple application that uses Amazon’s API, XML-RPC, the REST protocol and the Internet UPC database’s API to find information and pricing for the items matching the user’s search term.
  • Make Your Own Search Engine – mixing together the MSN search API via SOAP requests and responses to get the information for a user’s search.
  • You own Video Jukebox (my personal favorite) – a mashup of the YouTube and Last.fm APIs to pull the song information and videos for the titles in the feed (in either XSPF, RSS or YouTube’s XML format).
  • Traffic Incidents Via SMS – Scraping the California Highway Patrol’s website, they combine this data with the interface from 411Sync.com to send SMS updates to users of the system when new accidents arise.
  • London Tube Photos – a huge chapter crammed full of information and different mashup components including Google Maps, Flickr, SPARQL, the RDF API for PHP, using the XMLHttpRequest object in Javascript (along with JSON) to create a system that allows the viewer to locate images of the London Tube based on a location on a map rather than just a description on the site.

My personal favorite of the mashups is (as mentioned) the Video Jukebox one – I just think it’s a cool idea to be able to bring those two things together pretty easily thanks to two of the most powerful APIs out there.

Even if you’re not into the mashup aspect of the book, but you are a budding SOAP developer looking for a few helpful hints when it comes to WSDL structure, you’d do well to pick up a copy too. In Chapter 3, he’s written up a great little primer to the structure of a WSDL document (types, message, portType, etc) and has made it simple enough for just about anyone to catch. I know when I was starting out with SOAP, this was the one thing that I could definitely have used. Plus, without a built-in method for PHP5’s SOAP extension to make the WSDL for you, this can help you bridge the gap.

Overall, it’s a great book – a definite purchase for anyone out there looking to see how to combine two or more web services into one seamless application. Plus it gives a great overview of a lot of handy web service type bits of functionality.

http://rcm.amazon.com/e/cm?t=phpdorg-20&o=1&p=8&l=as1&asins=184719088X&fc1=000000&IS2=1&lt1=_blank&lc1=27278D&bc1=FFFFFF&bg1=FFFFFF&f=ifr&nou=1

Gettin’ SOAPy with PHP5

Recently, with our company’s update to PHP5 (yeah yeah, I know) we were looking to replace the software we use on our web service to handle real-time payments and customer lookups. Since we’ve been running PHP4, our natural choice was the NuSOAP framework. It gave us a (relatively) simple way to create the service and was easy to use. Unfortunately, with the move to PHP5, we couldn’t really use it anymore – and yes, I’ve seen the “change this line to this” fix for it but that kind of stuff makes me nervous. So, I decided that using PHP5’s SOAP extension was the way to go. Thankfully, it’s been pretty smooth sailing so far, and I thought I’d share some of it to maybe help anyone else out there looking to do something similar.

First off, my goal for creating this new service was to make it as flexible as possible. I wanted to make the main server portion of it smart enough to call what was needed to make the request without having to load the functionality for everything into each server request. The general idea, then, is to have the main server assigned to the SOAP object that dynamically loads in a class for that type of request. Thankfully, PHP5 has some features that make this pretty simple.

Here’s some sample code for the server portion:

[php]
header(“Content-Type: text/xml”);

function __autoload($class){
$path=’/path/to/webservice/libs/’.$class;
if(is_file($path)){ include_once($path); }
}

class MyServer {

var $_valid = null;
var $_action = null;
var $_msg = null;
var $_pars = array();

function __construct($msg){
$this->_msg=$msg;
}
function __parse($msg,$args){
$dom = DOMDocument::loadXML($msg);
$xpath = new DOMXPath($dom);
$result = $xpath->query(“//SOAP-ENV:Envelope/SOAP-ENV:Body/*”);
foreach($result->item(0)->childNodes as $key => $value){
$this->_action = $value->parentNode->tagName;
$this->_pars[$value->tagName] = $args[$key];
}
unset($dom,$xpath,$result);
}
function __call($func,$args){
$obj = new $func($args,$this->_msg);
if(isset($obj->xsd_type)){
switch($obj->xsd_type){
case ‘array’: return new SoapVar($obj->data,SOAP_ENC_OBJECT,$obj->type); break;
case ‘string’: return new SoapVar($obj->data,XSD_STRING,$obj->type); break;
case ‘xml’: return new SoapVar($obj->data,XSD_ANYXML,$obj->type); break;
default:
return new SoapVar($obj->data,SOAP_ENC_OBJECT,$obj->type);
}
}else{ return new SoapVar($obj->data,SOAP_ENC_OBJECT,$obj->type); }
}

}

//Now we start up our server…
$input = file_get_contents(“php://input”);
$server = new SoapServer(‘http://www.example.com/my.wsdl’);
$server->setClass(“MyServer”,$input);
$server->handle($input);
[/php]

It’s not the simplest script, but I wanted to show you all of the parts first and then break it down into more manageable chunks. Let’s start where the flow starts – the bottom of the script. This chunk of code allows the script to intercept the incoming request and assigns the class to handle it. Our MyServer class is where the real fun starts.

Moving along the flow line, we hit the constructor of the class. The only thing we do here is assign the incoming message to the _msg property of the class. This is so that later, when we need to parse it, we can get at it. Some of the magic with the SOAP PHP functionality happens next – it tries to look for a function named the same as the request type (so if the SOAPAction is “getFoo” it looks for the “function getFoo()” in the class). I went a different route here, though – I didn’t define any of the methods it would need in the server class itself. Instead, I made use of the __call magic function to handle things.

When the __call catches the action, it gets the function name that was called and the arguments it was called with. Unfortunately, this argument array has numeric keys which made it hard for me to tell what the real order of the inputs was (they could have the “acct_num” in front of “last_name” in one request and after it in another). More on that later, though. Right inside the __call method, you’ll see the key to it all – the dynamic call to an object, based on the type of request, being created and called with the arguments and a copy of the message. Since the classes aren’t included yet – we only wanted what we needed – the __autoload kicks in and pulls in the file.

This brings us to one of our “action classes” – here’s an example:
[php]
class MyTestRequest extends MyServer {
function __construct($args=null,$msg){
parent::__parse($msg,$args);

$arr=array(‘testing’=>’1,2,3′);

$this->type=’Account’;
$this->data=$arr;
}
}
[/php]

This is the simplest kind of request we can have – it lives off in the directory (defined in the __autoload of the server) as a file called MyTestRequest.php. All of the action happens in the constructor and other functionality should probably be relegated to other methods on the class. Our server class calls this constructor with the two parameters which are then passed back to a function in the server class, __parse. This does something that’s a bit optional, but I wanted it to be sure I knew which parameter was which when they were passing it it. As it stood, I only had numeric indexes on the arguments array and was left to guess which order they were in (not good). To remedy the situation, I pass it off to this function for processing.

The __parse function loads the message into a DOM document and, using an XPath query, finds the node for the action inside the SOAP:BODY. Each of its child nodes are then pulled out and the tag names are assigned to the _pars array and the action to the _action property. With these set, we can come back and, instead of just assuming that $args[0] is the account number, we can know for a fact that $this->_pars[‘acct_num’] is the right information.

The $arr inside of the __construct in MyTestRequest is then passed back out to the script via the $this->data property (shared between the parent and child since it extends it) and the type for the response (from the WSDL) in $this->type.

Hopping back over to the MyServer class, we’re back inside the __call still and there’s just one last thing to do – echo out the response in a SOAP-friendly way. That’s what all of the SoapVar calls are for. The switch() call looks at an optional $this->type property and, of set, tries to match the output with the right data format. In our example, though, it just falls down to the “else” and calls it as an object.

And, voila – it’s done. The output is a formatted SOAP response!

Eclipse/Zend Launch PDT (PHP Development Tools) v 1.0

The Eclipse Foundation, in cooperation with Zend, have officially launched the first stable (1.0) version of a project that’s been in development for a few years now – the PDT (PHP Development Tools) project.

The PDT project is based around the already wildly popular Eclipse platform, making it not only one of the most powerful development platforms for PHP developers, but also one of the most flexible. If there’s something you see lacking in what PDT has to offer, fixing it is as simple as one of two steps – you can either go out to the wide repository of Eclipse projects out there and find the components you might need or step up to the plate and create your own component and share it with the rest of the community. With a list of around 1,400 Eclipse plugins, though, you probably won’t be hurting for any bit of functionality you might need.

I had a chance to talk on a conference call the other day to discuss the project and what sort of impact they (Eclipse and Zend) thought it would have on not just the PHP community but the entire Open Source community as whole. The reasoning is pretty simple – the PDT project was created with one goal in mind – to take the foundation that the Eclipse project already has and make it into something that PHP developers all over the world can look to as a strong, flexible IDE option wen they’re packing their editor of choice.

Even if you’ve already become set in your ways, you should definitely check out the features that this new version of PDT has to offer. It takes bits and pieces from other IDEs out there and packages them all together into an easy to use package including:

  • Handy code editing features like syntax highlighting, code folding (a personal favorite) and little hints to remind you the details of a function you’re adding
  • the addition of both a Project and PHP Explorer views that work with introspection to update dynamically as things are added to the project (add a class to your file and it’s reflexed in the Explorer)
  • Debugging support – this includes support for their debugger (Zend’s) and XDebug support
  • and, of course, the Eclipse framework itself allowing developers to make, well, whatever they want to sit on top of PDT

That’s where a lot of the real power of this project comes in – the extensibility. Other IDEs (with the exception of things like Komodo) don’t have much in the way of user-defined plugins, at least not to this level. The Eclipse platform was created to be as flexible as possible. As a result anything about the project can be changed, added, removed, duplicated…well, you get the idea.

According to their latest press release, the PDT project has already seen over 300,000 downloads – and that’s not counting what they’ll get when the announcement of this stable version hits the web.

Check it out and grab the download of this latest version. It might not be exactly what you’re looking for but that’s the beauty of it – you have the power to mold it into just the right tool for you.

ZendCon ’07 and the Revenge of the PHPDev T-Shirts

Just thought I’d drop a note to all that’ll be attending this year’s Zend/PHP Conference & Expo – the t-shirts that I made up last year (see here for what they look like) will be making an appearance this year as well.

I’m not sure exactly how many of the shirts I have left (I’ll update this post later on with the numbers) but I’ll be bringing them along and will have them with me during the conference. I think they’re mostly mediums and extra-larges.

So, if you’re attending and would like a free t-shirt (yes, that’s right – free! woo!) from PHPDeveloper.org, be sure to track me down and harass me. I’ll be wearing one the first day so I should be pretty easy to spot.

UPDATE: I checked out the t-shirt supply I have left – 8 mediums, 5 larges and 7 extra-larges. If you’d like me to save one (like Wez has already posted his preference) add a comment here and I’ll set one aside. It’ll be first come first serve after that, though – so if you’re wanting one, add a note or find me fast 🙂

Custom Form Helpers in Solar

Another thing that Solar makes easy is the creation of custom form helpers. These can be anything outside of the usual input types (like text, checkbox, textarea, etc) and can be used to make helpful, more complex inputs for your app.

In a previous post, I worked some with the Solar_Form class to create a login form. This just used simple input fields (text and password) to create the login form. I came to another part of my application where I needed a calendar helper to fill in some fields. I wanted to eliminate some of the user issues that could come with invalid dates being entered, so I opted to create a custom form field instead. The field is a normal text field, marked as READONLY with a link that launches a Javascript popup with the calendar picker.

First, we need a little structure – here’s how the application is structured (basically):

MyApp
 App
  Base
   Helper
    FormDate.php
   Layout
   Locale
   View
  Event
  Event.php
   Helper
   Layout
   Locale
   View
    index.php

There’s a few things involved here:

  • The form helper class – FormDate.php
  • The Event.php class (controller) where the form will be created
  • The View for the Event controller to output the form and some Javascript

We’ll start with building the form since that’s more familiar territory:

[php]
class MySite_App_Event extends MySite_App_Base {
protected $_action_default = ‘index’;
protected $_layout = ‘default’;
protected $_view =’index’;
public $forms;

public function actionIndex(){
$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘event_title’=>array(
‘type’=>’text’,
‘label’=>’Event Title’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter an event title!’)
)
),
‘event_start’=>array(
‘type’ =>’date’,
‘label’ =>’Start Date’,
‘require’=>true,
‘valid’ =>array(
array(‘notBlank’,’Please select a start date!’)
)
),
‘sub’=>array(
‘type’=>’submit’,
‘value’=>’create event’
)
));
$form->feedback=NULL;
$this->forms[‘create_form’]=$form;
}
}
[/php]

If you look close, you’ll spot something custom in there – on the event_start element, there’s a type of “date”. This how our special form helper is called. Solar does a little magic here – it looks at the types of each of the elements and looks in a few places for something that matches that type. Most of the elements are Solar’s default types so it falls back to the ones in the Solar directories. The “date” type, however, isn’t one of them and the app will break if you leave it like this.

So, what’s a developer to do? Well, create a custom form handler of course! This is where the FormDate.php file comes into play. Here’s what ours contains:

[php]
class MySite_App_Base_Helper_FormDate extends Solar_View_Helper_FormElement {

public function formDate($info){
$this->_prepare($info);
return ‘_view->escape($this->_name) . ‘”‘
. ‘ value=”‘ . $this->_view->escape($this->_value) . ‘”‘
. $this->_view->attribs($this->_attribs)
. ‘ READONLY/> _view->escape($this->_name).”)”>select‘;
}

}
[/php]

If you’ve been checking out the default Solar form fields, this should look familiar – it’s a ripoff of the default text field form helper that Solar comes with. The only addition is the Javascript-powered link there at the end that calls the date_picker application.

There’s a few things that need to be in place to get this to work. First off, the class name needs to be the right “path” to the file. So, for our class it corresponds to MySite/App/Base/Helper to tell Solar where the file exists. If this isn’t right, Solar won’t be able to find and use the file. Next thing to look out for is the last part of the class name – FormDate for us. The second part of this is what Solar uses when the class is called. So, for example, we use FormDate because we want the type to be “date”. If we wanted one that was some kind of special field that works with Google’s Maps, we could use FormGoogle and define our custom form field inside it. Speaking of inside, the method’s name has to match the class name – FormDate and formDate – and takes in the information passed to it (including the field name, the value to fill it with and attributes it might have).

Because this file exists in the Base controller’s Helper directory and our Event class extends the Base, we can use it. Plus, by putting it up in the Base Helper directory, we can use it in other places in the site that extend Base.

Now we’ll move on to the last part of the equation – the View for the Event controller:

[php]

function date_picker(fname){
elem=document.getElementById(fname);
elem.value=’08/14/1977′;
}

form($this->forms[‘create_form’]);
?>
[/php]

In the View above (our index.php file), we define the Javascript function our custom helper will use – date_picker – that takes in the element name. In a real application, this would be the place to interface with another page (or maybe even some sort of Ajax request) to let the user pick the date. As it stands, though, we’re just putting our predefined date in the field. The PHP part is simple, just an execution of the form.

Ideally, you’d put any and all Javascript in a few files out in the public directory of your application rather than in the view itself, but since we’re going for simplicity here I’ve just put it in the page itself.

So, there we go – a simple method to make a custom form handler that you can use anywhere in your application. It’s pretty easy to see how you can expand upon this to make just about any kind of custom form element that you might want…

Solar Form Validation Types

This is partially for my reference and partially for anyone looking at validating in their Solar_Form forms – here’s the validation methods (as defined in /Solar/Filter.php):

Each of these can be used when defining the form, commonly in the setElements structure like so:

[php]
$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘password’=>array(
‘type’=>’password’,
‘label’=>’password’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Enter a password!’)
)
)
));
[/php]

#reftable { border-collapse: collapse; }
#reftable td { padding: 3px; border: 1px solid #C0D0D9 }
#reftable td.header { background-color: #C0D0D9 }

Type Details
alnum Validate that valid is only alphabetic and numeric characters
alpha Validate that value is only alphabetic
blank Validate that there’s nothing in the field, it’s blank
callback Validate against a callback function – call is given the value and callback function name
ctype Checks the value with the ctype_* function built into PHP
email Validates as a valid email address
feedback Validates and only returns a message on failure, returns feedback as a string
inKeys Validate that the value is one of the keys of the given array
inList Validates that the entered value is in a given array (as value, not key)
integer Checks to ensure that the value is an integer (contains + or – and numbers, no decimals)
ipv4 Validates to check for a correct ipv4 address
isoDate Ensures that value is a correctly formatted ISO 8601 date (yyyy-mm-dd)
isoTime Validates that value is a correct ISO 8601 time format (HH:MM:SS)
isoTimestamp Validates that value matches the full ISO 8601 timestamp format (yyyy-mm-ddThh:ii:ss)
localeCode Checks to see if the value is a valid locale code (two a-z letters, an underscore and two A-Z letters)
max Checks to see if the given value is greater than or equal to the ‘max’ given
maxLength Checks the value to ensure that it’s less than or equal to the maximum length given
mimeType Checks to see if the value is a valid mime type (follows the regular expression: [a-zA-Z][-.a-zA-Z0-9+]*)
min Checks to see if the value given is less than or equal to a minimum
minLength Checks the value to be sure it’s at least a minimum length
multiple Allows you to perform multiple validations on the same value
notZero Ensures that the value does not exactly equal zero
notBlank Ensure that a string, when trimmed, is not empty
range Ensure that the value given is in a certain range
rangeLength Validate that the length of the given value is within a certain range
regex Match the value against a given regular expression
scope Checks to be sure that the given value only has a certain number of digits and decimals
sepWords Validate that the value is made up of separate words
uri Validate that the input is a valid URI
word Ensure that the value is made up of only “word” characters

Some Solar Form Fun

So, after getting started with the Solar framework, I figured that I’d keep going and try to really work up an application with it and get familiar with the framework. A next obvious step (well, to me it’s obvious) is to dive into using the form functionality that comes with it. I started small, but eventually worked into a standard part of just about any application these days.

Like learning anything, there were some growing pains as I figured out how to work with it (many thanks to the guys in #solarphp on Freenode) and how to get the following code up and working. The Solar_Auth component makes it simple to drop on top of whatever kind of authentication system (LDAP, ini files, htpasswd) but the method I chose is one of the most common I’ve seen – authentication from a database table. The Solar_Auth_Adapter_Sql handles most of the work and makes defining the table a snap.

Let’s start with the entire code for the controller, User.php:

[php]

class MySite_App_User extends MySite_App_Base {

protected $_layout = ‘default’;
protected $_action_default = ‘index’;
protected $_view=”;

public function actionIndex(){ }
public function actionLogin(){

$sql=Solar::factory(‘Solar_Sql’);
$config=array(
‘adapter’=>’Solar_Auth_Adapter_Sql’,
‘config’=>array(
‘sql’ =>$sql,
‘table’ =>’users’,
‘handle_col’=>’username’,
‘passwd_col’=>’password’,
‘uid_col’ =>’ID’,
‘process_login’=>’submit login’
)
);
$auth = Solar::factory(‘Solar_Auth’,$config);
$auth->start();

$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘handle’=>array(
‘type’=>’text’,
‘label’=>’username:’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter a username!’)
)
),
‘passwd’=>array(
‘type’=>’password’,
‘label’=>’password:’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter a password!’)
)
),
‘process’=>array(
‘type’=>’submit’,
‘value’=>’submit login’
)
));
$request = Solar::factory(‘Solar_Request’);
$process = $request->post(‘process’);
if($process==’submit login’){
$auth->processLogin();
$form->populate();
if($form->validate() && $auth->isValid()){
$this->output.=’logging in…’;
}else{
$this->output.=’Invalid login!’;
}
}
$form->feedback=NULL;
$this->forms[‘test_form’]=$form;
}
}

[/php]

Now, let’s go through this piece by piece and make it a bit more clear for the non-Solar using crowd (of which I used to belong to).

We’ve defined the controller’s class as extending the MySite_App_Base (see the previous article as to how this is for templating the site) and define some basic properties for the layout/template to use, the default action, and the view to use by default. Below that, there’s two other properties – forms and output. The second is just a general output value that’s used in the /User/View/login.php file as a message. The first, however, is a special container for our form. Later on, you’ll see where the Solar_Form instance is appended to this property and how it’s executed in the view.

Since we’re only really worried about the login form, it’s the only action that’s built out. The function starts by defining the configuration for the Solar_Auth object we’re going to create. The “adapter” setting tells it we want to use the SQL functionality and the “config” array gives the details. The only tricky parts about these values is in the process_login settings. This will need to correspond to the value of your submit button to make things work correctly.

The next two big parts of the action are the creation of the Solar_Auth object (with our $config options) and the Solar_Form object. The first is what handles all of the validation and authentication functionality and the second is the object around which we build our form. That’s what the setElements function is for…

The setElements function is flexible, but I used it to contain a series of arrays that each represent an element in the form. The keys are the element names – “handle”, “passwd” and “process” – and each is a subarray with several settings defined inside. Things like the type of element, the text to have before it (Solar_Form does a basic layout), if the field is required, and how to validate it. On both the username (handle) and password (passwd) fields, I added a simple notBlank with a message to ensure that there’s something in the field. The last item, “process”, is the simplest.

Now the real fun begins – we have our form defined and the $auth object made so we can validate the username and password that’s entered, now we just need to grab the results of the form’s submission and perform the check. We can do this by creating a Solar_Request instance with direct access to the HTTP request. The value we need to watch for on the submit (the value of the “process” form element) is pulled into the $process variable via a call to post() on the request object. The “if” statement then checks for the value of it and, if it’s set, tries to perform the validation.

The processLogin() method called on the $auth object is what does the work here. It runs the check and then, if everything’s okay, sets the status property of the $auth object to “VALID”. The populate() function just repopulates the form’s values back into it (just in case it fails) and the validate() that’s called checked our form’s validation (like the notBlanks we added earlier). The isValid method called on the $auth object checks to see if the status property has been set to “VALID” indicating that the authentication was a success.

The next part is simple – if it’s a success, it outputs a success message and if not, tells the user that it was an “invalid login”. Right below the if statement is a handy little setting that I like because I want to control things in my form – the feedback setting. If set to false, it can silence the feedback that Solar automatically gives.

Remember how I said that the $forms property would come in handy later on? Well, the last part of this script is where it’s at. The Solar_Form object is appended to the $forms array, a value passed out into the view.

Speaking of the view, let’s see how this is all outputted:

[php]

echo $this->escape($this->output);
echo $this->form($this->forms[‘test_form’]);

[/php]

Is this a great framework or what? That’s all it takes to fire off the form in your View and the rest is handled behind the scenes in the controller. There was also someone mentioning the other day (in #solarphp on Freenode – I just can’t promote them enough!) that was talking about using the Solar_User class to do much of the same thing. I opted for Solar_Auth mainly because there were just more docs for it on the Solar website, making it easier to get into. Might have to try that one next though….