I’ve just uploaded the slides from my confoo.ca talk “Making software management tools work for you”. You can download the slides from here.
Thanks again to everyone who attended! Please give me feedback on joind.in.
In a recent (quick) post to the php|architect site Koen Van Urk reminds us that it's not all about the code, there's planning to consider too.
Sure, it is important to have your code as bug free as possible, well documented and as optimized as possible. It is, however, impossible to achieve this all without prior planning. Good project coordination.He suggests one of the most useful and reliable forms of planning and defining the requirements for an application - writing them down on a normal piece of paper. Then from there let the ideas flow with things like look and feel, mapping out page structure, etc. Website planning tools are good, but when it comes down to basic prototyping, sometimes there's just nothing better than a pencil and a few sheets of plain white paper.
PEAR consists of literally hundreds of packages (libraries) that help you to build your PHP applications faster, less error-prone and more secure. Millions of web applications use and rely on the proper functioning of PEAR packages.
To ensure constant quality, many packages utilize phpt or PHPUnit tests that are run during development and before each release. They help us making sure new features or bug fixes do not break existing functionality.
One of hard to solve challenges is ensuring that a package's unit tests do not only run on the specific PHP version the developers have installed on their machines (which often is the latest and greatest, maybe not even released version from SVN), but to cover the whole range of supported PHP versions. This goal can be achieved in several ways:
Solution number 1 requires either much hardware or at least quite some setup time for virtual machines. Besides that, running tests regularly on many different machines needs automated deployment tools - you won't ssh into the 15th machine manually, let alone setting up database servers and other software that might be required.
There is no single Linux distribution I know of that supports installing multiple versions of PHP beside each other - making solution number 2 similar daunting to setup and running as #1. The benefits above #1 are obvious: All software on one machine means easier deployment because the software to test needs to be setup only once. Software dependencies need to be installed only once. Executing the tests is easier if all versions of PHP are on this single machine, which means that the cross-version tests can be automated really easily.
A tool to solve all problems with the multiple-php-versions-on-one-machine solution is phpfarm. The best way to demonstrate its easiness is probably a shellshot:
$ svn co http://svn.php.net/repository/pear/ci/phpfarm/trunk/ phpfarm $ cd phpfarm/src $ ./compile 5.3.2 ... fetching sources from php.net ... configuring ... compiling ... installing ... fetching and setting up pyrus $ php-5.3.2 --version PHP 5.3.2 (cli) (built: Mar 10 2010 18:08:27) (DEBUG) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies $ pyrus-5.3.2 --version Pyrus version 2.0.0a1 SHA-1: 2FDFB5E00A6D707437DBC047AAF9D115C6484D90 Using PEAR installation found at /home/cweiske/Dev/cvs/pear/phpfarm/inst/php-5.3.2/pear php pyrus.phar version 2.0.0a1.That's it. With one single command, you can install each version of PHP you like, and you get pyrus, the next-generation PEAR installer for free! Let's try it:
$ pyrus-5.3.2 channel-discover pear.phpunit.de Discovery of channel pear.phpunit.de successful $ pyrus-5.3.2 install phpunit/phpunit ... Installed pear.phpunit.de/PHPUnit-3.4.11 $ pyrus-5.3.2 list-packages Listing installed packages [/home/cweiske/Dev/cvs/pear/phpfarm/inst/php-5.3.2/pear]: [channel pear.phpunit.de]: PHPUnitphpfarm automatically sets up your php.ini with the values you desire. It sets your include_path. It lets you specify custom configuration options, per patch, minor or major PHP version - just have a look at the README.
Now everything is ready for you (and us PEAR developers!) to let the unit tests run on all the little PHP versions we want to. Did I tell you that phpfarm also installs php-cgi versions? My next blog entry will show you how to run dozens of php versions simultaneously in apache.
If you have questions or suggestions about phpfarm, don't hesitate to ask on the pear-general mailing list (subscription info) or on the #pear IRC channel.
Happy testing!
In a new post to his blog Brian Swan compares the database drivers for MSSQL and SQLSRV by what they have to offer and what the real differences are to your applications.
In this post I want to begin looking at some of the differences between the two drivers and perhaps gain an understanding of why the mssql driver continues to be used (although I have some good guesses). There are lots of comparison points between the mssql and sqlsrv drivers. I'll break my comparison into two posts, focusing on high-level differences in this post and then dive into an API comparison in the next post.This first of the two parts looks at some of the differences between the two - the Microsoft support for the sqlsrv driver vs community-driven mssql and the fact that they're very different "under the hood" (see this diagram).
Joseph Crawford has a new post to his blog today with a look at his use of the Zend_Rest_Controller and Zend_Rest_Route components of the Zend Framework to create a simple REST service.
You might be asking yourself why do I have to use both components, why is it not rolled into one nice component. The answer is really basic and if you look at the source code for the Zend_Rest_Controller you will see that it is solely an abstract class that defines the methods required for use with the Zend_Rest_Route.He includes the code to add to your bootstrap file to get the routing working and a sample controller (MyController) that extends the Zend_Rest_Controller and sets up some basic actions - get, put, post and delete. He does mention one issue he's coming across in a feature he's wanting to add - putting the version number of the API in the URL for easier separation.
I’ve been working hard on Goodsie.com lately trying to bring it to launch. It’s been great being in on a new PHP project from (near) the beginning, as it frees up a number of things.
One of those, is the fact that I can be using PHP 5.3 and all the new features that come with PHP 5.3. While I’ve used my fair share of the short-cut ternary already (?:), the bigger win for me, are the Lambda functions with scoping (anonymous functions).
I found a very specific use out of the blue of Lambda functions that I have now used and I see as a great use-case. Which is specifically passing functions/logic from your Controller to your View.
In the case of Goodsie, I’m using PHP for my templating language and as usual I’m trying to remove as much logic from my View as possible, while still allowing the view to be malleable.
The specific case I had, was a subview that was generating some pagination code for me. You know, the standard ‘previous, page 1, page 1, next’ section of links. The basic html template I had, looked looked similar to:
<div class="pagination"> <a href="<?= $baseurl . '/page:' . ($page - 1) ?>">← Previous</a> Page <?= $page ?> of <?= $total ?> <a href="<?= $baseurl . '/page:' . ($page + 1) ?>">Next →</a> </div>Rather straight forward, but I quickly ran into a problem. The way it worked, as you see, is that you passed in a base URL, and the page number you are currently on, and it generated appropriate forward/back links. (Ok, there was also some other logic where it determined if you needed the prev/next links at all, but I’ve removed that for clarity)
But I then had a case, where I wanted to reuse this subview in an ajax situation. Where instead of straight URL’s being passed in, I might want to pass in a javascript function, and have that function be called with the page number as a parameter. That would be nice as I could use it in both situations. What pagination looked like, could completely change, and still work on both cases. Perhaps we’d want to give a full list of all possible pages. Or show a couple forward/back, etc. The view could handle all of that without a change to the controller.
But therein lied the problem. When using a URL based pagination, I wanted to concat the page number onto the end of the URL. But when using javascript, it wasn’t pure concatenation, it instead needed to wrap the page number with the function call. Oh the pain a simple ) could cause me.
I started writing code, where I ended up with tons of switch statements and logic inside of the view. I’d have to pass in two different possible values, a URL or a javascript function. The view at every point where it would output a link, would need to see which version was being used, and from that decide what type of output to create. In short, it was a mess.
But then the solution dawned upon me. A lambda function would work admirably here. So what I did, is inside of my controller I created a function on the fly, that would generate the appropriate type of link that I was wanting. It looks something like:
if ($jsfunc) { $url = function ($p) use ($jsfunc) { return "javascript:{$jsfunc}({$p})"; }; } elseif ($baseurl) { $url = function ($p) use ($baseurl) { return "{$baseurl}/page:{$p}"; }; }Now I could simply rewrite my original template, to use this lambda function $url to generate it’s URLs.
<div class="pagination"> <a href="<?= $url($page - 1) ?>">← Previous</a> Page <?= $page ?> of <?= $total ?> <a href="<?= $url($page - 1) ?>">Next →</a> </div>Now not only would this work for my specific situation, but ANY controller could reuse this pagination subview and define exactly how it wanted it’s URLs to be formed. Now, the view could completely change around how the pagination section is displayed, show as many, or as few pages as it wants to, and all that without ever touching the controller.
This is one simple example, but I’ve become enamored of this approach. Using lambda functions in this way, you are able to have complicated logic represented inside of your view, but encapsulated/created by the controller. Also of note is the fact that the view is managing to use the $jsfunc and $baseurl values, but without actually having to be granted access to them. This allows for another level of encapsulation, as I exposed one function,
Truncated by Planet PHP, read more at the original (another 1389 bytes)
Qaiku, the conversational microblogging service that launched a year ago had a refresh that launched today. While it hasn't yet convinced the twittering masses, it has already proven itself as a lot more thoughtful platform for the Finnish online community, and as a valuable workstreaming tool.
The new version looks quite nice and fresh. Notice the privacy information on the right-hand side, which is relevant as Qaiku allows channels and profiles that are private or invitation-only:
Technically the new version is also remarkable as it is the first major website to run fully on top of the legacy-free Midgard2 platform. So yes, every entry you see there is a GObject. And D-Bus signals fly when you post.
On to the challenge, thenTo highlight Qaiku's threading, conversational nature I started a new "On my travels, I have" thread for sharing your most extraordinary travel experiences. This is not on Twitter or Buzz as with Qaiku it is so easy to keep the conversation together and accessible for the future as well.
To contribute, sign up on Qaiku, go to the thread and add your experiences as a comment. If you have a link or picture to include, you can also do so. My first entry was:
seen ice descend from the heavens and provide us with cold beer on a hot day in LesothoWill be interesting to see what comes out of this :-)
From CMStr.com there's a new tutorial showing you how to set up Joomla manually just in case something happens with the install and you need to change things yourself.
Why would I want to do a manual install when my web host has this Fantastico thingy that will install Joomla for me? Good question. [...] If you are building websites for a living, and or plan on using Joomla a lot, then you really need to start doing your own installs. [...] If you are an experienced parachute jumper, you would pack your own chute right? This is no different.Screenshots are included to help make the process easier as they walk you through setting up the basics like language settings and database information. They also touch on the FTP setting (off for security) and removing the admin user's information to help make things a bit more secure. It's not a comprehensive list of the things you'd need to do to get it 100% configured for just what you need, but it's a start.
On Kavoir.com there's a new post that reminds you that hashing isn't enough anymore to protect your users and their passwords. They offer a suggestion or two of what you can do to help lock things down a bit more.
The common practice is to hash the user password and store the hash string of the password in the database. When the user tries to log in and supplies his password, it is used to generate a hash string to be compared to the one stored in the database. [...] This approach may be secure in the 70s of the last century, but barely any more.Computing has evolved enough to where hashed can be matched, sometimes in less than two or three minutes. Their answer to the problem? Generate a random salt each time you create the hash with a constant being used as a base. A code snippet calling a user-defined function and the sha1 function are included.
Brandon Savage has posted his own response to the "don't be afraid of the upgrade" thread that's been going around concerning updating to PHP 5.3. He takes a different approach to the matter, though - one of a bit more caution.
When it comes to open source projects endorsing PHP 5.3 as their one and only PHP platform, I encourage caution. When it comes to open source projects that use PHP, there are three main issues that I believe should be considered before making the leap to PHP 5.3 (or any new release of any new software).He sees three considerations projects and companies should consider before making the upgrade on their servers - the amount of control you have over the environment, deciding if the upgrade is worth possible backwards compatibility breaks and how much support you want to still provide for the pre-5.3 version(s).
New on the PHPClasses.org blog there's an article on neural networks written up by Louis Stowasser looking specifically at creating a neural mesh with PHP.
Neural networks are a relatively new technology that aims to reverse engineer the functionality of the brain within a mathematics model. This may sound daunting and complex but the underlying concepts are very simple and Neural Mesh does the hard work for you. In a Web environment NNs (neural networks) are considered too slow and complex to warrant effort on what might even be a trivial task. To solve this, Neural Mesh has been heavily optimized. It uses caching to speed up running and training of networks.He explains what a neural network is on a base level and talks about it's ability to learn from the training its given (supervised or unsupervised). He also talks about how the networks can be useful and how to use the framework (found here) to create a simple network.
A new tutorial has been posted to the Zend Developer Zone today looking at making scalable vector graphics with PHP and the hep of one of two charting packages - ezcGraph or SVGGraph (examples are provided for both).
Programmatically generating graphs and charts using SVG requires a deep understanding of the SVG specification and the various SVG primitives, as well as a fair amount of time for research, experimentation and debugging. Or, in other words, that's your entire weekend shot! Fortunately, help is at hand. There are a number of open-source PHP libraries that support SVG chart generation, and using them can significantly reduce the amount of work involved in adding this feature to a Web application.He shows how to create simple images like bar, line and pie charts as well as adding in other things like a legend, custom titles and a sample where the user can define the sizes of a pie chart via some form input fields. Screenshots are included for all code examples to give you a better idea of the end result.
I'm doing a talk today in the Bossa Conference about using Midgard as a content repository for mobile applications. As part of my presentation I wrote some simple example code for using the Midgard APIs in Python, and thought they would be good to share to those not attending the event as well.
The idea of a content repository is that instead of coming up with new, isolated file formats or database setups for your application you can just work with objects and signals, and let Midgard handle the rest. This is something that lots of people are doing with CouchDB as well, but we feel Midgard, with its light footprint and native APIs for languages like Python, C, Vala and PHP fits better in the mobile applications context.
Installing MidgardMidgard packages are available for many different Linux distributions through the OpenSuse Build Service. To find the right repository for your setup, go to the OBS project page. For example, on my Ubuntu Karmic netbook the URL to add to apt sources.list is deb http://download.opensuse.org/repositories/home:/midgardproject:/mjolnir/xUbuntu_9.10/ ./. Then I just:
sudo apt-get update sudo apt-get install python-midgard2Midgard is also available in Maemo extras and for OS X on MacPorts.
Defining a schemaThe first thing when developing a Midgard application is to define your storage objects. This is done using the MgdSchema XML format. In this case we're doing a simple "attendee" object that amends Midgard's built-in person record with information related to the conference:
<?xml version="1.0" encoding="UTF-8"?> <Schema xmlns="http://www.midgard-project.org/repligard/1.4"> <type name="openbossa_attendee" table="openbossa_attendee"> <property name="id" type="unsigned integer" primaryfield="id"> <description>Local non-replication-safe database identifier</description> </property> <property name="person" type="unsigned integer" link="midgard_person:id"> <description>Person attending the event</description> </property> <property name="registration" type="datetime"> <description>Registration date of the attendee</description> </property> <property name="likesbeer" type="boolean"> <description>Whether the attendee likes beer</description> </property> </type> </Schema>Then we just save this XML file into /usr/share/midgard2/schema/ so that Midgard will find it.
Initiating the repository connectionOnce the MgdSchema is in place it is time to import antigravity and start hacking in Python. The code works pretty much in the same way in other languages Midgard is available for, but Python is used here for the sake of simplicity. First we load the Midgard extension:
import _midgard as midgardThen we setup the repository connection. With these settings we will store our content into an SQLite database located in ~/.midgard2/data/midgardexample.db:
configuration = midgard.config() configuration.dbtype = 'SQLite' configuration.database = 'midgardexample' # Open a Midgard repository connection with our config connection = midgard.connection() connection.open_config(configuration)As this is the first time we're interacting with the repository we need to tell Midgard to prepare the storage for itself and also for our new openbossa_attendee class:
midgard.storage.create_base_storage() midgard.storage.create_class_storage('midgard_person') midgard.storage.create_class_storage('midgard_parameter') midgard.storage.create_class_sTruncated by Planet PHP, read more at the original (another 2314 bytes)
On the php|architect site there's a recent post that splits apart the singletons versus static methods debate that seems to com up every once and a while with a better suggestion - dependency injection.
Much more important than performance is the fact that both static methods and singletons suffer from major drawbacks. When it comes to deciding between the two, you might forgo the benchmark comparison and choose the third-party candidate: dependency injection.He mentions the "dark side" of both static methods and singletons and how dependency injection can help rid your code of both. Instead of focusing just on the benchmark numbers, DI helps you keep your code more well-structured and "smarter" by scoping things to where they need to be and making them easier to test.