Solar

PHP is the Future

Catchy title, eh? I have to admit, I used a bit of an inflammatory title to pull you into the rest of the post, but I think you’ll like what I have to say. The title is true, but probably not in the way you think. No, PHP is not going to be the language that comes out on top, not the “one language to rule them all” sort of thing. Instead, I’m proposing that PHP, the flexible and powerful language that it is, has a very large roll to fill in the future of the web.

There’s lots of little things that the language has done along its life to help make the world wide web a better place to live. Most importantly it’s given the world an Open Source alternative to some of the other closed languages that some of the major companies of the world offer (okay, so I’m pretty transparent). PHP packs a lot of power in a little package, and the general developer community has definitely taken notice. This plucky little language that started as a handy tool for Rasmus to keep track of things in his personal pages has evolved into something that major companies around the world are implementing into their core software. Hear that? *Core* software. PHP isn’t some fly-by-night language that’s the latest fad being passed around like so many YouTube videos. PHP is strong, its powerful and it is most definitely here to stay.

But I digress…let’s get back to the point that the title of this post was trying to make. PHP is the future. No really, it is – trust me on this. Of course, there’s a difference between being the only path to the future and one of many means to getting there, but we’ll toss that aside for now. We want to focus on PHP and what it can do to make all three Ws in the WWW a better place to develop.

So, lets talk a little bit about what PHP has to offer to the world at large.

From its humblest of beginnings, one of the core values of the PHP project has been to provide the most power in the best code possible. Sure, it has its quirks and it can be a little rough around the edges, but line of code for code, PHP packs some serious features into a neat little package. There’s even the extension system that makes it super easy to add in new bits of functionality without even having to recompile the main engine. Oh, and did I mention it’s free? Open Source, well supported and very very popular among both the usual Open Source crowd and among other certain large entities (even those that might live in Redmond)

Every time I look the future of the web (linking services, making things seamless, integrating technologies), I can see PHP at every major crossroads. Its the flexibility of the language that does it. Sure, there’s still a bit of a niche that PHP fits into, but once you take a step out of that safe little shell, you really start to realize what the language has to offer and where it fits in the world. PHP has the potential for being the glue that binds the web together. There’ll always be other languages out there – to dismiss them would just be silly – but PHP, with its flexibility and power really has the feature set to help propel Open Source web development into the spotlight and shine for what it is.

The web needs a language that’s quick to adapt, easy to configure, comes in at a low cost and is popular enough to find good, talented developers for (yup, that’s a big point too). If you ask me, PHP fits all the above and more.

I believe that PHP can be the future of the web and be a key player in the web applications to come.

Advertisement

Subdomain Setup with Solar

So here was my situation – I wanted to have a subdomain off of my main site, but I didn’t want to have to create a whole new docroot with an entire new Solar framework application in it. Besides being “yet another install” of the same sort of thing, it would also be a pain to keep up more than one codebase that does a lot of the same things.

This got me to thinking that there had to be a way to convince Solar that it could use the same code with the subdomain without issue. Sure enough, it could – and it was actually really easy. Here’s my situation:

I wanted to have the main domain’s stuff still work (www.mydomain.com) just like it always has but I wanted the subdomain to point to one controller out of the main application (in this case, the Solar_App_Foo controller) when the subdomain was called (foo.mydomain.com). Solar makes it dead simple – it’s just a change in your config file.

Since it’s PHP driven, you can do fun things like checking to see what the value of $_SERVER[‘HTTP_HOST’] is right there in the definition:

$act=($_SERVER['HTTP_HOST']=='foo.mydomain.com') ? 'foo' : 'index';
$config['Solar_Controller_Front']['default']=$act

That’s all there is to it – the ternary check looks for the subdomain and sets the default controller to our Solar_App_Foo instead of the Index the rest of the site calls. And, since it’s just part of the same site, all of the links and other functionality work just fine. Plus no extra code to maintain!

Hope this helps to anyone else out there trying to work with subdomains with Solar. Thanks to the crew in #solarphp on Freenode for the help!

Save your Site, Cache that Data!

One of the things that I’ve noticed in running PHPDeveloper.org is that the highest traffic (most of the traffic for the site, actually) is going to the RSS feed giving the latest news I’ve posted. When I first relaunched the site with Solar, things were fine – but only for about ten minutes. As soon as everyone’s aggregators came back on and started pulling the feed, the load on my server shot straight up. Thankfully I was able to get it back down to a more manageable level with a static version before the box took a nosedive. I had to do something about it and I figured that caching the feed’s information was definitely a start.

I’d never really used the Solar_Cache stuff before, but thankfully – it’s super easy. I figured that the biggest bottleneck in making the feed was pulling the data from the database each time. I opened up the controller for my feed (Feed.php – I know, very creative) and added a Solar_Cache object.

You can set this stuff up in your configuration file too, but I dropped it into my controller as a quick solution.

In my _setup() call:

$config=array(
    'adapter'=> 'Solar_Cache_Adapter_File',
    'path'=> '/tmp',
    'life'=> 200
);
$this->cache = Solar::factory('Solar_Cache', $config);

This creates a cache object in $this->cache that I can use for whatever I want. It’s file caching and the results will get put in /tmp. That “200” for the life is in seconds, so it’s at about three minutes right now. There’s lots more options for caching besides files already built into the framework too like APC, eAccelerator, variables and XCache.

With our object made, we apply it down in our default actionIndex() wrapped around our database fetch:

$ret=$this->cache->fetch('feed_data');
if(!$ret){
   $news=$this->news->fetchNews();
   $this->cache->save('feed_data',$news);
   $ret=$news;
}
$this->news_items=$ret;

Pretty simple, really – the cache object checks to see if the data already exists and, if it does, just passes it on through to our view. If it doesn’t (either that it’s the first time it’s being made or it has expired) it will pull the new news and push it out to the cache. The view then takes this array of values and makes a basic RSS feed out of it for all the world to see.

You wouldn’t believe how much something simple like caching your feed can help on even a moderately popular site. Check out the class list for details on the other caching options.

PHPDeveloper.org Sees the Light – The Move to Solar

So I’ve been asked several times about the move I made for PHPDeveloper.org from the Zend Framework over to Solar with the main question being “why?”

Well, I hate to break it to any of the framework zealots out there but the only real reason I had for doing it was the old “try something new” idea that floats around every so often. Yes, I know the site was working just fine under the old Zend Framework code (and yes, I do mean old – I think it was a few versions before 1.0 even) but I get the itch to do something new every once and a while. Some people redesign – I’ve done that too – and others rewrite things from scratch.

I took the opportunity to really look at the core of the site, stripping out all of the extra little “goodies” that I’d hacked in to the ZF version to get various things working. I came back to the primary focus of the site – to provide the latest news information quickly and easily – and made sure that all new code pointed toward that goal. The overall concept is a simple one really: it’s essentailly a blog whos topic just happens to be the goings-on of the PHP community as a whole. All it really needed to do was show the news items, serve up a feed and provide an administrative way for me to add new posts to the system.

I developed the Zend Framework version many moons ago and I almost don’t remember how it was all set up. It took me a bit to get back into it to see how things were structured, but in the end, most of that was tossed and replaced wth some sleek Solar code.

One of the biggest things that I was happy with in the new rewrite was the way that the news information is fetched from a the database. There’s no longer function calls like “getMainNews()” or “getNewsDetail()”. Instead they were replaced by a fetch function that takes in parameters on the object (sort of like the Command design pattern) and applies them to the current query.

For example, I make a call to the “setProperties” function of the NewsAPI object to tell it that I want a type of “where” with a value of “ID=1234”. The fetch function then looks through the properties and applies the operation to the query. The result is a function that can be called the same way every time with the same sort of output. The only difference is in how much/what kind of output there is.

I was concerned about some of the performance issues I was seeing on my server when I made the switch. Some of it was my own fault – forgetting to cache the feed instead of geenrating it, not adding the spam/IP filtering to ward off some of the spammers – but there was still a slow down when the load started to get high. I knew Solar could handle it (it had done it wonderfully on the dev server) so it had to be something else. The dedicated machine I’d been using was nice, but was showing some of its age. I decided to buy a slice from Slicehost and set up shop over there with only PHPDev running on it. Turns out that it wasn’t the new Solar version that was the issue, it was the server. In fact, I’d almost be willing to not cache the feed anymore – the performance is that good.

My last little part of the transition is writing the backend command-line scripts that I use to do some automatic things and the site will be back and complete and 100% Solar-ized.

I know there’s some things I didn’t cover here, so if you have any questions, leave a comment or drop me a line: enygma at phpdeveloper dot org. I’m more than happy to talk Solar with you. And if you’re interested and want to chat with other Solar folks (including some of the main developers behind it), come over to the freenode network – irc.freenode.net – and pop in to #solarphp and say “hi”.

SolarPHP.com

Some “Why Won’t Solar Work” Tips

With more and more people installing and using Solar all the time, theres some questions that get asked quite a bit. I wanted to help with some of those questions by providing some simple answers here. Here we go…

  • Tip #1 – Be sure that you have your App directory correctly set in the configuration file. If you don’t add it to your front controller Classes setting, Solar has no idea where to find it.
  • Tip #2 – Class names on the controllers are important! Be sure it follows the directory tree like Project_App_Controller. Also be sure you’re extending the right thing. I usually use a Base controller/setup to provide an overarching “global” place to put things (like a layout) and extend that, so it’s usually “extends Project_App_Base”
  • Tip #3 – You can change the values that the Solar_Form login functionality uses to trigger the automagic login process by setting it in the adapter for your authentication object (like a Solar_Auth_Adapter_Sql) via the process_login and process_logout values.
  • Tip #4 – Be sure to include everything you need to get to “magically” through Solar in the set_include_path in the front controller. For example, you can add in another directory with external libraries so that in your application, you can just call it and let the __autoload handle it.
  • Tip #5 – You might get some complaints from Solar about not having a “sql” object it can work with. I good way to handle this is to check in your _setup function of your controllers to see if there’s one registered. If not, make one with a factory call and register it for the framework’s use: Solar_Registry::set(‘sql’, Solar::factory(‘Solar_Sql’));

Solar Makes Its Move – The Path to 1.0

In case you’ve missed it, big things are happening over at the Solar camp. Paul and the crew are getting close to the big stable release that’s been a long time coming for one of the best PHP5 frameworks out there. I picked up on Solar a while back and didn’t find it fitting my needs at the time. I came back, though, when looking for something besides CakePHP and the Zend Framework and am quite happy I did.

Solar is a great, full-featured framework and, according to the modest Paul Jones, has “at least 80% of everything you would need to build a web-based and cli-based application” in PHP. Personally, I haven’t found very much (small things really) that I needed that weren’t in the framework. Even better is that a lot of these have been added in preparation for the upcoming 1.0 release – things like the Model functinoality and updates to the Solar_Sql package to make lots of lives easier. There’s all sorts of fun things with the new models (check out the wiki for tips on its use) including magic things like: “fetchAllByStatus(1, $params) -> in this case, ‘fetchAllByStatus’ doesn’t exist, and the model will return all records with status 1” (as per moraes).

If you’re looking around for a framework to try out, head over and give Solar a look – there’s never been a better time to get started with it. Nothing like a 1.0 to get people excited!

Many thanks to Paul and his fellow framework developers for putting together one of the best systems out there.

Let the countdown to 1.0 begin…

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….

Starting Simply with Solar

In an effort to get to know as much of the technology out there, I wanted to branch out in my framework knowledge and try something I hadn’t looked much into yet – the Solar framework (PHP5). I’ve worked with both the Zend Framework and CakePHP on previous sites, so I wanted to see how they compared. The Solar framework, worked up by Paul Jones and team, provides much of the same functionality as the other two frameworks and is even based around the same structure – Model/View/Controller – to get the job done.

Since there’s no time like the present and no better way to learn how to use a tool than to just jump right in and get started, I looked up the great Getting Started section of the Solar manual to get on my way. It’s a great little section jam-packed with all the info that you’ll need to get started. I do want to, however, go back over my experience with it all as another example of how I set it up and got it working for my little application.

First of, obviously, you’ll need the latest version of the framework on your machine to get started. Unzip it in a place outside of the document root for where you’ll be building your application. This makes it easier if there’s others developers on the box that want to use it later on. Then, when you update the library, you don’t have to do it in ten different locations.

First off, you’ll need to set up your configuration file – you can put this just about anywhere really, but outside the document root is suggested since it could contain username/password information for your application. My document root is: /home/website_htdocs/sampleApp and my config file, Solar.config.php is located in /home/website_htdocs. Here’s the contents:

[php]
$config=array();

//Base action href
$config[‘Solar_Uri_Action’][‘path’]=’/’;

//Base public directory href
$config[‘Solar_Uri_Public’][‘path’]=’/public’;
$config[‘Solar_Controller_Front’][‘default’]=’index’;
$config[‘Solar_Controller_Front’][‘classes’]=array(
‘Solar_App’,
‘SampleApp_App’
);
$config[‘Solar_Sql’]=array(
‘adapter’ => ‘Solar_Sql_Adapter_Mysql’,
‘host’ => ‘localhost’,
‘user’ => ‘dbuser’,
‘pass’ => ‘dbpass’,
‘name’ => ‘sampleDB’
);

//Done!
return $config;
[/php]

The file is made up of the $config array with various values – among them the Solar_Uri_Action (the base action location) and the Solar_Uri_Public (the base for the public directory). That first option (Uri_Action) can be thought of the more “external” of the two. It tells the framework which URL the site will be using as a base. In my examples, I’m using mod_rewrite to handle the redirect of everything back down to the Front Controller (an index.php file that handles the routing), so I have it set to the root or “/”. Now, the Uri_Public setting is a little different story. This one is more “internal”, a setting that’s used to point the framework at the location of a public directory it can use to store things like CSS or Javascript files (and where anyone using Solar on the site) can use it too. I have it set to “/public” to point to a symlink that’s in my document root. Since Solar is installed to /home/website_htdocs/Solar, I made the link like this:

[php]
ln -s /home/website_htdocs/Solar/Solar/App/Public public
[/php]

This points a symlink of “public” to the Public directory over in the Solar installation. This is handy for working with shared files and provides us a location so we’re not polluting the views and all with unneeded code.

With the config file and symlink in place, the next step is the Front Controller. This is a PHP file that Solar uses to define a few more things and start up the framework to handle the requests coming in. Here’s what mine looks like:

[php]
set_include_path(‘/home/website_htdocs/Solar:/home/website_htdocs/SampleApp’);

require_once(‘Solar.php’);
Solar::start(‘/home/website_htdocs/Solar.config.php’);

$front=Solar::factory(‘Solar_Controller_Front’);
$front->display();

Solar::stop();
[/php]

There’s two main things set here – the include path (to define where our Solar and application directories are) and the start() call with the path to the config file created earlier.

You notice the “sampleApp” in the examples above – that’s the name of the example application I’ve worked up. It’s nothing special, but it does follow with the structure they suggest for using Solar. To contain all of the files, we’ll make a SampleApp directory in the document root of our site with a few files and directories under it:

App
  /Base
  /Base.php
  /Base/Helper
  /Base/Layout
  /Base/Locale
  /Base/Model
  /Base/View
  /Index
  /Index.php
  /Index/Helper
  /Index/Layout
  /Index/Locale
  /Index/Model
  /Index/View

I know that looks like a lot of stuff, but most of those directories won’t even be touched. We’re only really worried about a few things. First off, let’s look what this all means. Each of the controllers have a PHP file in the App directory. In our case, we have a Base.php and Index.php file for those two controllers. Base is a special example that allows for cross-controller file use and communication. So for our example, the only thing in here is:

[php]
class SampleApp_App_Base extends Solar_Controller_Page {
// nothing really needed here, unless you want
// shared methods and properties too
}
[/php]

This just makes the controller and extends the regular Solar controller. We’ll come back to the Base stuff in a second – for now, lets talk about the Index.php file:

[php]
Solar::loadClass(‘Solar_Controller_Page’);
class MySite_App_Index extends SampleApp_App_Base {

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

public $output = ”;

function _setup(){
Solar::register(‘sql’, ‘Solar_Sql’);
}

public function actionIndex() {
$select=Solar::factory(‘Solar_Sql_Select’);
$select->from(‘test_tbl’,array(‘*’));
$res=$select->fetch(‘all’);
$this->res=$res;
$this->output = ‘this isdsds my example’;
}

}
[/php]

This is where the action happens in our little application. The best part of it all is that, way back in the configuration file (remember Solar.config.php?) we set up a default controller to run when one’s not specified – “index”. That means that, when people just hit the domain (like http://www.foo.com versus http://www.foo.com/pageName) they’ll get what’s in our Index controller.

So, what is in there? Well, lets look at the different parts. Our class extends the Base class instead of the normal Solar_Controller_Page so that we can use the things in the Base directories without any other special code. Because of this, we can use the layout defined in $_layout. Layouts allow for things like site templates without having to add the header/footer to each of the views for all of the controllers. The value, “default” corresponds to a PHP file, default.php, that’s located in /App/Base/Layout. Here’s what it contains:

[php]

imsothere.net
script(‘scripts/jquery/jquery.js’); ?>

layout_content;
?>

$(‘#mine’).append(‘

test

‘);

[/php]

This is pulled almost directly from their example with a few slight adjustments. One of the things that I wanted to do with my application was to use jQuery to handle some of the advanced Javascript. Because of this, I needed to include it in all of my pages. Naturally, in the layout is the perfect place. So I went to the jQuery site and grabbed the latest copy of their library. Now, remember that symlink we made a little while back – well, we’re going to go into that directory (you should see other directories inside it like scripts, images and styles) and inside of the scripts directory, make a jquery directory and put the file in there. That’ll match up with our example HTML, but you can always move it around to fit your needs. In our layout file above, you can see where it’s calling the script() function to grab that library and output an HTML tag for it.

The other missing piece to this puzzle is the view for the Index controller itself. The framework knows enough to apply the default template because of the value in $_layout, but it sill needs the value for layout_content to put in there. That’s why we need to make a view in /App/Index/View called index.php with the following content:

[php]
echo $this->escape($this->output);
echo “

"; print_r($this->res); echo "

“;
[/php]

You can match up the “output” and “res” properties from our actionIndex in the controller above. This is all packaged up and pushed into the layout and outputted. The script block at the bottom of the layout is just some Javascript using jQuery that adds a row to the table above it (I wanted a simple test to check if it was included and working correctly).

Finally, we get to the last piece of this mini application – the database connection. Now, you’ll remember way back in the config file, we defined some parameters:

[php]
$config[‘Solar_Sql’]=array(
‘adapter’ => ‘Solar_Sql_Adapter_Mysql’,
‘host’ => ‘localhost’,
‘user’ => ‘dbuser’,
‘pass’ => ‘dbpass’,
‘name’ => ‘sampleDB’
);
[/php]

Aren’t you glad that this isn’t in the document root? So, these set the different values your script will need to access your database – in this case, a local MySQL one. Setting all of this up here frees you up to only have to work with the objects in your controller:

[php]
$select=Solar::factory(‘Solar_Sql_Select’);
$select->from(‘test_tbl’,array(‘*’));
$res=$select->fetch(‘all’);
$this->res=$res;
[/php]

This example pulls the data from a test table named, creatively, test_tbl and pulls it into an array. This array is then pulled into the “res” property and added to the output of the view (as located in the View for Index).

So, there it is – that’s my experience so far with the Solar framework. It’s a little different than the other two frameworks, but I think so far, I like it a little more. It has a little lighter feel to it and doesn’t seem so much like someone dumped a toolbox over your head and told you to make sense of it all. Unfortunately, there’s still some of a learning curve to Solar. Once you get outside of the API docs on the site, there’s not a whole lot in the way of documentation. Thankfully, there’s always the guys in #solarphp on the Freenode IRC network to run to with questions.

Oh, and did I mention that the time from downloading the framework and getting all of this up and working was about 4-5 hours? Definitely works for me 🙂