Archive for the ‘php’ Category

The Symfony community is small

Sunday, April 11th, 2010

Some of the more interesting things I write nowadays seem to get posted in discussions on LinkedIn. I repost here what I wrote in response to someone who wanted to know how big the Symfony community is.

Everything I’ve seen and heard suggests to me that the Symfony community is small and stagnant. Consider this graph.

Drupal and WordPress are both much, much larger than Symfony. More so, according to that graph, Symfony’s growth is limited compared to WordPress.

If you remove Drupal and WordPress, then it appears that Symfony is roughly the same size as Zend and CodeIgniter, and all of them have relatively flat growth. Consider this graph.

Of course, Google Trends is only one source of information, and only offers a rough approximation. It is important to check other data sources. So, for instance, we can double check the trend by looking at Indeed: consider this graph.

Here we see that the trend to Drupal is both much greater than Symfony, and also growing at a much faster rate.

This also interesting, comparing Symfony, Zend, Cake and CodeIgniter: consider this graph.

In this, the big winner is Cake, with Symfony coming in 2nd.

There is also the experience that Darren Hoyt and I have had trying to launch our 2 sites. Consider the high levels of activity on our WordPress site compared to the low levels of activity on our Symfony site:

http://www.wpquestions.com/

http://www.symfonyexperts.com/

Symfony Experts is newer, but we put far more effort and money into marketing it than we did with the WordPress site. Yet it still lags.

Also, consider that Symfonians.net is basically the official membership site for Symfony, yet it has less than 3,000 members:

http://symfonians.net/

It is like a rounding error when compared to Drupal.

Finally, there is my own experience on LinkedIn – I constantly get calls from headhunters who call me because I know Symfony, and always they say the same thing – “There are not many of you Symfony programmers, I’ve had a hard time finding people for the job I’m trying to fill.”

No matter what data source you consult, the conclusion is unmistakable: Symfony is a small community, and its rate of growth is slow.

Why is this? My own theory is that Symfony brings to PHP something that PHP has long been missing: a truly professional, industrial strength, object oriented architecture that allows PHP to be taken seriously in the enterprise. However, all of the people who would be truly interested in such a framework have long ago found a home using Ruby, Java or Python. In short, the kinds of people who gravitate to PHP are exactly the kind of people who are unwilling or unable to appreciate the beautiful elegance and power of a system like Symfony. The people who need something like Symfony gravitate to other languages.

Whatever happened to PHP6?

Tuesday, March 30th, 2010

Apparently PHP6 ran ashore on the shoals of Unicode:

Things came to a head on March 11, when Jani Taskinen, fed up with being unable to push things forward, (1) committed some disruptive changes to the stable 5.3 branch, and (2) created a new PHP_5_4 branch which looked like it was meant to be a new development tree. That is when Rasmus stepped in:

The real decision is not whether to have a version 5.4 or not, it is all about solving the Unicode problem. The current effort has obviously stalled. We need to figure out how to get development back on track in a way that people can get on board. We knew the Unicode effort was hugely ambitious the way we approached it. There are other ways.

So I think Lukas and others are right, let’s move the PHP 6 trunk to a branch since we are still going to need a bunch of code from it and move development to trunk and start exploring lighter and more approachable ways to attack Unicode.

And that is where it stands. The whole development series which was meant to be PHP 6 has been pushed aside to a branch, and development is starting anew based on the 5.3 release. Anything of value in the old PHP 6 branch can be cherry-picked from there as need be, but the process of what is going into the next release is beginning from scratch, and one assumes that proposals will be looked at closely. There are no timelines or plans for the next release at this point; as Rasmus explains, that’s not what the project needs now:

We don’t need timelines right now. What we need is some hacking time and to bring some fun back into PHP development. It hasn’t been fun for quite a while. Once we have a body of new interesting stuff, we can start pondering releases…

So timing and features for the next PHP release are completely unknown at this point. Even the name is unknown; Jani’s 5.4 branch has been renamed to THE_5_4_THAT_ISNT_5_4. There has been some concern about all of those PHP 6 books out there; it has been suggested that a release which doesn’t conform to expectations for PHP 6 should be called something else – PHP7, even. There’s little sympathy for the authors and publishers of those books, but those who bought them may merit a little more care. But that will be a discussion for another day. Meanwhile, the PHP hackers are refocusing on getting things done and having some fun too.

Brandon Savage: learning the Zend framework

Thursday, March 18th, 2010

Brandon Savage has some advice for anyone learning the Zend framework:

Various frameworks out there have varying degrees of integration with one another. While an argument can be made as to whether or not tightly integrated frameworks are better or worse than loosely integrated frameworks, when starting a new framework it’s best to accept it lock, stock and barrel (in other words, accept it completely).

This isn’t always easy for developers. They have a particular problem they want to solve and often times solving it with a framework they haven’t used requires a lot of setup, a lot of learning, and a lot of banging their heads against a wall. I know for me this is true whenever I start working on a new framework or product. But this is an important component of using the framework. When we try and go around the framework, when we fight the framework, we ultimately end up doing a lot of the things that the framework is aimed at keeping us from having to do.

Embrace the framework. Once you’ve learned it and mastered it, you can go around it, fight it, and ignore it if you want. But until that point, ignoring it will only lead to more headache and frustration – especially when you discover the framework was doing something you were trying to do all along.
….

Learning a framework is much like learning a new language. Have patience for it. The reward is great – framework knowledge can be reused over and over again. Being patient and taking the time to learn means that the knowledge will be valuable, rather than being bits and pieces of a hurried experience (which is far less valuable). A holistic understanding of the framework will serve you well, as a developer.

Is Apostrophe the best CMS written in PHP?

Thursday, March 18th, 2010

Robert Speer has a great write up of Apostrophe:

Apostrophe is the easiest to use content management system (CMS) available to the open source community. An easy CMS means that content managers are more likely to use it, which means consumers will get better information and be more likely to follow the sites profit funnel.

For web solutions providers Apostrophe is a CMS solution that bypasses the commodity hell of Wordpress, Drupal, and Joomla by providing a unique value differentiation. Apostrophe also has the advantage of being built on an enterprise grade web framework used by sites like Delicious, Dailymotion, Yahoo! Answers, and Yahoo! Bookmarks. Symfony provides a consistent structure that encourages collaboration, and the large community of developers already familiar with Symfony mean help is available.

Eli White on using lambda functions in PHP

Friday, March 12th, 2010

Eli White offers a very smart use of lambda functions in PHP.

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, instead of 2 separate variables. In the future if other data points start being needed to determine what a URL should be, the view never needs know that, as the controller will continue to update the function on it’s behalf.

Eli White responds to Fabien Potencier regarding template engines

Sunday, February 21st, 2010

Over on Symfony Nerds, I wrote about Potencier’s ideas about a template engine. I just noticed that Eli White had also written an intelligent reply, well worth reading.

RESTful architectures and Symfony: how big should modules be?

Saturday, February 20th, 2010

I’ve a new post up at Symfony Nerds. In it, I look at the implications of a RESTful architecture for Symfony. Should every module just have 4 actions, read, write, update and delete?

PHP is a sloppy language

Saturday, January 9th, 2010

All programmers should read PHP Must Die. PHP is a sloppy language, with a lot of subtle bugs.

Netbeans is a good IDE for Symfony

Wednesday, January 6th, 2010

I agree with this: Netbeans is a good IDE for Symfony development. I think this is especially true if you, like me, also develop with JVM languages. This last year I was doing some Java/Swing and Groovy projects, so I started using NetBeans again. It has a plugin for doing Symfony work – very handy.

Groovy is an easy step into the JVM world for PHP developers

Saturday, January 2nd, 2010

A script written in Groovy that finds and deletes files that match some given pattern. The syntax of Groovy is wonderfully clean, and not especially foreign to PHP developers. I’d think that if a PHP developer wanted to dive into the world of the JVM, Groovy would make an easy first stop.

The endless quest for the right tools for large scale software

Thursday, December 31st, 2009

Colin Steele writes about the challenges that he and his team are facing at Hotelicopter:

We’ve officially run headlong into one of Ruby on Rails’ deficiencies: programming in the large. We’re not interested in computer science-y solutions, only pragmatic ones.

I’m curious what is excluded by the phrase “computer science-y solutions”? I would normally interpret that to mean “we are looking for well tested solutions with wide deployment” but elsewhere he writes:

We’re currently investigating a spectrum of new technologies in the NoSQL realm, including Tokyo Tyrant, MongoDB, Amazon’s SDB, CouchDB, Voldemort, and more. Tis’ a dizzying mix, and things are popping in the space.

So clearly they are looking at some cutting edge technologies. Colin links to an essay about Programming in the large which includes this:

Maintenance and locality are strong arguments in favor of immutability. The less aspects of an object can be changed, the less you have to worry about the execution history. If an object has a two-phase initialization sequence (e.g. this is so in C++ if you need a virtual function during initialization), you have to make sure that the objects are properly initialized; code that gets handed over such an object will have to check that it’s initialized (if only in an assert()). This all vanishes if the language makes sure that no object remains uninitialized, and doesn’t force a two-phase initialization on programmers like C++. (In C++, the “wrong” design decision was that objects mutate from the base type to the subtype when the various constructors are run. It’s this kind of far-reaching consequences (IOW non-locality) that makes language design an art.) If you take immutability to its extremes, nothing can ever be changed. If you wish to change the world, you write a function that returns a list of changes and let the run-time system inspect that list and execute the proper actions. If you have an interactive program, you emit a list that has a function pointer at its end; the function gets fed the next input and is expected to generation another action list.

In the last few years, many programmers have pointed to mutability as one of main problems they face when they build larger systems. Chas Emerick does a good job of highlighting the problem in his post “All my methods take 316 arguments, and I like it that way

316 arguments to a method (which I don’t think is actually possible in the jvm, but bear with me)? “That’s absurd!”, you’d say. The problem, of course, is that the 3-arg doSomething actually has far more arguments than its signature implies:

The behaviour of every function in a mutable, imperative environment is dependent upon the state of all of the other (variables|attributes|bindings|whatever) in your program at the time the function is invoked.

So, if you have 313 other variables in your program, that 3-arg doSomething is functionally (ha!) operating over 316 arguments.

Would you ever intentionally write a method signature that takes 316 arguments? Would you use any library that contained such a function signature? No? Then why are you using tools that force such craziness upon you?

Chas says “The languages are ready” and he links to some of the major functional languages: Erlang, Clojure, F#, and Fantom. In comments, his readers add in their favorite functional languages: OCaml, Haskell, etc.

One of his readers challenges the idea that functional languages are safer than imperative languages by offering this:

Regarding functions changing state, what about things like this in clojure, Isn’t it like global variables in imperative lang?

(def state (ref #{}))

(defn function that updates state)

(defn another function that updates state)

Chas responds:

You bet. Clojure is not a purely functional programming language, so you can have as much shared state as you want – but the language is going to make you work for those bits of shared state, so you have to “pay” for them. Conversely, imperative languages like Java et al. make you work to achieve immutability, and provide nothing in the way of enabling persistent data structures, etc.

The point is that defaults matter, a lot.

I like the word “default” in this context. In his 2001 book, Effective Java, Joshua Bloch wrote “Favor immutable objects over mutable.” When writing a big system in Java, you work to make your system immutable. In a language like Clojure, the default is just the opposite – you work to make parts of your system mutable.

I have very little experience with functional programming. I am just learning Clojure now (Lisp redone for the JVM). I can not say what benefits its brings. I’m looking forward to learning more in this area. It’ll be interesting to see where functional programming comes to be regarded as a “best practice”. Certainly, it will be interesting to see if CTO’s start using these languages at startups, or whether they will be regarded as “computer science-y solutions”.

I’ve somewhat more experience with the web app frameworks that have emerged since 2004. I’m interested in what Colin wrote here:

I suspect as we muddle along we’ll develop a component-level (service level if you prefer) version of the Law of Demeter, which will drive us to make the right decisions for decoupling. I’m not too worried about that. However, we definitely have issues with reuse. Currently the Ruby on Rails state of the art solution for reuse is the gem. Which, let’s face it, is a pathetic solution.

Some of the frameworks seem to encourage bad habits. I’ve already written of Symfony’s weaknesses in Symfony versus The Law Of Demeter: does Symfony promote bad habits?.

When Ruby on Rails first emerged it was targeting web apps, not web services. Rails has a lot of imitators: Groovy/Grails, PHP/Symfony, etc. These all help create web sites, but not necessarily web services. I suspect a new generation of frameworks will be needed to make this kind of work easier:

The place we’re aiming for is a highly decoupled (and scalable), cohesive set of services, joined through REST APIs and/or fully reused common business models.

In their book Restful Web Services the authors Leonard Richardson and Sam Ruby talk about “the human web” and the “programmable web”. This is from page 2:

The Web you use is full of data: book information, opinions, prices, arrival times, messages, photographs, and miscellaneous junk. It’s full of services: search engines, online stores, weblogs, wikis, calculators, and games. Rather than installing all this data and all these programs on your own computer, you install one program – a web browser – and access the data and services through it.

The programmable web is just the same. The main difference is that instead of arranging its data in attractive HTML pages with banner ads and cute pastel logos, the programmable web usually serves stark, brutal XML documents. The programmable web is not necessarily for human consumption. Its data is intended as input to a software program that does something amazing.

Originally, frameworks like Rails were created to help speed the production of sites for the human web. They have evolved since then, Rails in particular. In fact, Richardson and Ruby use Rails for many of the examples they offer in the book, about how to correctly build a RESTful web service. And yet, the scaffolding systems in these frameworks still tend to automate the production of CRUD web pages, rather than PGPD services. (I do not know the state-of-the-art with Rails, so someone can tell me if I’m wrong about its scaffolding.)

Richardson and Ruby suggest that every module (resource) in a RESTful web service should expose just 4 actions:

POST
GET
PUT
DELETE

These are the HTTP verbs, and they roughly correspond to the standard CRUD actions, except that POST is used for both Create and Update, and PUT is used for uploading files:

Create/Update
Read
Upload
Delete

I suspect we need a new generation of frameworks, or at least new scaffolding systems for the existing frameworks, that automate the setup of PGPD services. That seems like the next obvious step forward.

A new post up at Symfony Nerds

Tuesday, December 22nd, 2009

I’ve a new post up at Symfony Nerds. This looks at the evil of utility classes full of static methods, a vice that I’m guilty of on every project. I examine possible ways to refactor the code to get a healthier overall architecture.

Symfony-Check.org: a useful Symfony checklist

Saturday, November 28th, 2009

Just saw this site referenced on the user mailist. Symfony-Check.org is a useful list of things to check when building a Symfony-backed website.

Drupal’s prominence is hurting the PHP frameworks, such as Symfony

Sunday, November 15th, 2009

I’ve a new post up at Symfony Nerds, this one about the extent to which Drupal’s prominence limits the growth of PHP frameworks. I’ve seen a number of Django versus Drupal comparisons, which are a bit unfair, since they compare a framework to a CMS.

Does Symfony promote bad coding habits?

Monday, November 9th, 2009

I’ve a new post up at Symfony Nerds, which looks at some of the bad coding practices which are common on some of the Symfony projects that I’ve worked on.

What would the ideal template system be for Symfony?

Wednesday, October 28th, 2009

I’ve a new post up at Symfony Nerds. Fabien Potencier, the lead developer on Symfony, has recently introduced 2 new components related to templates in Symfony, including Twig, a template engine that will be introduced in Symfony 2.0. I try to offer an overview of the whole debate around these developments.

Traits will bring something like mixins to PHP

Saturday, October 24th, 2009

I’ve a new post up over at Symfony Nerds. It is all about how ‘traits’ will bring something like Mixins to PHP.

A Symfony utility for cleaning up the HTML that users submit

Wednesday, September 16th, 2009

Tom Boutell explains some features that are hidden in his pkToolkitPlugin plugin for Symfony:

* The pkHtml class. Many projects allow users to edit content via a rich text editor. And we all know what happens if the user pastes a Word document in there: the styles of the page wind up hopelessly munged. You can use striptags(), but that doesn’t clean up the CSS, so your page is still a mess.

A common workaround is to use FCK’s “paste as plaintext” mode, which thwarts attempts to paste rich text from another program. That works, after a fashion, but it’s frustrating for users. And none of the workarounds help if the user is actively trying to enter inappropriate HTML in a misguided attempt to re-style their site… then calling you to fix it for the 500th time.

HTML Tidy can do the job, but it has a reputation for being heavy and slow.

Or… you can just use pkHtml::simplify():

How to post data to a remote URL, using PHP

Monday, September 14th, 2009

I have to look this up every time I do it, so I’ll post it here so I can refer back to it easily. The following script is up on Wez Furlong’s website, HTTP POST from PHP, without cURL. He is on the core PHP team. I’m sad to say that he writes:

I don’t think we do a very good job of evangelizing some of the nice things that the PHP streams layer does in the PHP manual, or even in general. At least, every time I search for the code snippet that allows you to do an HTTP POST request, I don’t find it in the manual and resort to reading the source. (You can find it if you search for “HTTP wrapper” in the online documentation, but that’s not really what you think you’re searching for when you’re looking).

Damn, it is a bad sign when folks on the core team are also at a loss. The inconsistency of the PHP language makes it difficult to remember how to do things.

Anyway, here is the script:

function do_post_request($url, $data, $optional_headers = null)
{
$params = array(’http’ => array(
‘method’ => ‘POST’,
‘content’ => $data
));
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = @fopen($url, ‘rb’, false, $ctx);
if (!$fp) {
throw new Exception(”Problem with $url, $php_errormsg”);
}
$response = @stream_get_contents($fp);
if ($response === false) {
throw new Exception(”Problem reading data from $url, $php_errormsg”);
}
return $response;
}

$optional_headers is a string containing additional HTTP headers that you would like to send in your request.

He gives credit to Sara Golemon for much of the work on streams in PHP.

A left join in Symfony/Propel

Friday, September 11th, 2009

I previously mentioned that the worst thing about Symfony is how under-documented Propel is. I also notice that the situation as gotten better than it was in the spring of 2008, when I started using Symfony. There are more and more examples of how to do things, for instance, a Left Join:

$c = new Criteria();
$c->addJoin(PatientPeer::DOC_ID, DocPeer::ID, Criteria::LEFT_JOIN);
$this->patients = PatientPeer::doSelect($c);

All the same, in the future, I will probably use Doctrine. It is well documented.

PHP now has namespaces, closures and late static binding

Wednesday, September 9th, 2009

I guess because this was talked about for so long, I missed the official announcement, but now PHP 5.3 is out, and it supports namespaces, closures and late static binding.

Because this is PHP, all of these are just a little bit uglier than they would be in another language. I’d say that PHP strives to be the ugliest of the high level script languages, but at least it always has Perl to defend it from that accolade.

Check out the syntax for late static binding. This:

public static function test() {
self::who();
}

becomes this:

public static function test() {
static::who(); // Here comes Late Static Bindings
}

Ugly.

Which design patterns does Symfony implement

Wednesday, September 9th, 2009

Alvaro Videla thinks out loud about what design patterns are implemented in Symfony:

Some of the patterns involved in Symfony are:

* Front Controller
* Command
* Intercepting Filter
* Context Object
* Two Step View
* Helper Object or View Helper
* Table Data Gateway (i.e.: ArticlePeer.php)
* Row Data Gateway (i.e.: Article.php)
* Active Record
* Single Table Inheritance

A site converts SQL into Propel code (for Symfony, for instance)

Monday, September 7th, 2009

I think I stumbled upon this site last year, when I was first learning Symfony. At that time, the site was very rough. It is still in alpha, even now, but it looks like it has reached a point where it is useful. It converts SQL into the code needed for Propel.

So it converts this:

person.gender = ‘M’ AND (person.location IN (’Birmingham’, ‘Coventry’) OR person.location = ‘Manchester’) AND (person.enabled <> 0) AND person.age > 16

Into this:

$c = new Criteria();
$crit0 = $c->getNewCriterion(PersonPeer::GENDER, ‘M’);
$crit1 = $c->getNewCriterion(PersonPeer::LOCATION, array(’Birmingham’, ‘Coventry’), Criteria::IN);
$crit2 = $c->getNewCriterion(PersonPeer::LOCATION, ‘Manchester’);

// Perform OR at level 1 ($crit1 $crit2 )
$crit1->addOr($crit2);
$crit3 = $c->getNewCriterion(PersonPeer::ENABLED, 0, Criteria::NOT_EQUAL);
$crit4 = $c->getNewCriterion(PersonPeer::AGE, 16, Criteria::GREATER_THAN);

// Perform AND at level 0 ($crit0 $crit1 $crit3 $crit4 )
$crit0->addAnd($crit1);
$crit0->addAnd($crit3);
$crit0->addAnd($crit4);

// Remember to change the peer class here for the correct one in your model
$c->add($crit0);
$result = TablePeer::doSelect($c);

// This loop will of course need to be edited to work
foreach ($result as $obj)
{
//$val = $obj->getValue();
}

Very useful, since the worst thing about Symfony is how under-documented Propel is.

On future Symfony projects, I may convert to Doctrine.

How do loops work in PHP?

Friday, September 4th, 2009

When I first started to learn how to program I was confused by loops. I will write something short here about how loops work.

Possibly the simplest loop is the “while” loop. It loops while some condition is true.

Let’s suppose we want to get the character count of the first 20 visible words in a block of HTML (this is based on an actual request from a client). Let’s suppose that we are working on a WordPress site, so we will use the WordPress function get_the_content() to get the content:

$contentWithTextAndHtml = get_the_content();

$howManyCharactersHaveWeCountedSoFar = 0;

$howManyWhiteSpacesHaveWeFoundSoFar = 0;

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar) {

$thisCharacter = substr($contentWithTextAndHtml, $howManyCharactersHaveWeCountedSoFar, 1);

if ($thisCharacter == ” “) $howManyWhiteSpacesHaveWeFoundSoFar = $howManyWhiteSpacesHaveWeFoundSoFar + 1;

$howManyCharactersHaveWeCountedSoFar = $howManyCharactersHaveWeCountedSoFar = 1;

}

This while loop is going to continue for as long as $howManyWhiteSpacesHaveWeFoundSoFar is less than 20. Inside of the loop, every time we find a white space, we increase $howManyWhiteSpacesHaveWeFoundSoFar by 1. So after we have found 20 white spaces, this loop will stop running.

We can clean up this code somewhat, using shortcuts that PHP allows. For instance, this:

$howManyCharactersHaveWeCountedSoFar = $howManyCharactersHaveWeCountedSoFar = 1;

can also be written as this:

$howManyCharactersHaveWeCountedSoFar++;

The “++” means “add 1 to this variable”. So we can use this trick to have slightly less code:

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar) {

$thisCharacter = substr($contentWithTextAndHtml, $howManyCharactersHaveWeCountedSoFar, 1);

if ($thisCharacter == ” “) $howManyWhiteSpacesHaveWeFoundSoFar++;

$howManyCharactersHaveWeCountedSoFar++;

}

But our loop isn’t really doing what we want. We want to find the first 20 visible words, so we do not want to count the white spaces that are inside of HTML. If we had simple text, with no HTML, the above loop would work fine. For instance, it would find the first 20 words in this block of text:

“SuperAmazing.com, a subsidiary of Amazing, the leading provider of integrated messaging and collaboration services, today announced the availability of an enhanced version of its Enterprise Messaging Service (CMS) 2.0, a lower cost webmail alternative to other business email solutions such as Microsoft Exchange, GroupWise and LotusNotes offerings.”

but what if we are dealing with a block of text that has a lot of HTML in it, like this:

“<img src=”/images/corporate/logos/super_amazing.jpg” alt=”Company logo for SuperAmazing.com” /> SuperAmazing.com, a subsidiary of <a href=”http://www.amazing.com/”>Amazing</a>, the leading provider of integrated messaging and collaboration services, today announced the availability of an enhanced version of its Enterprise Messaging Service (CMS) 2.0, a lower cost webmail alternative to other business email solutions such as Microsoft Exchange, GroupWise and LotusNotes offerings.”

Let’s suppose we need to get the character count (including HTML) out to the 20th word. We will need some simple way to keep track of whether or not a white space is inside of HTML or not. So we could do something like this:

$contentWithTextAndHtml = get_the_content();

$howManyCharactersHaveWeCountedSoFar = 0;

$howManyWhiteSpacesHaveWeFoundSoFar = 0;

$areWeInsideOfHtml = false;

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar) {

$thisCharacter = substr($contentWithTextAndHtml, $howManyCharactersHaveWeCountedSoFar, 1);

if ($thisCharacter == “<") $areWeInsideOfHtml = true;

if ($thisCharacter == ">“) $areWeInsideOfHtml = false;

if (!$areWeInsideOfHtml) {

if ($thisCharacter == ” “) $howManyWhiteSpacesHaveWeFoundSoFar++;

}

$howManyCharactersHaveWeCountedSoFar++;

}

So now we only count white spaces when $areWeInsideOfHtml is false.

If loops confuse you, then you might have trouble figuring out what this line does:

$thisCharacter = substr($contentWithTextAndHtml, $howManyCharactersHaveWeCountedSoFar, 1);

We want to get one character at a time. substr() let’s us get a small section of a string. These are the 3 parameters:

$contentWithTextAndHtml – this is the string we should look inside.

$howManyCharactersHaveWeCountedSoFar – this is where in the string we start to look

1 – this is how many characters we should get. In our, case we just want to get 1 character at a time.

As the code loops, what is basically happening is this:

$thisCharacter = substr($contentWithTextAndHtml, 0, 1);

$thisCharacter = substr($contentWithTextAndHtml, 1, 1);

$thisCharacter = substr($contentWithTextAndHtml, 2, 1);

$thisCharacter = substr($contentWithTextAndHtml, 3, 1);

$thisCharacter = substr($contentWithTextAndHtml, 4, 1);

$thisCharacter = substr($contentWithTextAndHtml, 5, 1);

$thisCharacter = substr($contentWithTextAndHtml, 6, 1);

$thisCharacter = substr($contentWithTextAndHtml, 7, 1);

$thisCharacter = substr($contentWithTextAndHtml, 8, 1);

$thisCharacter = substr($contentWithTextAndHtml, 9, 1);

$thisCharacter = substr($contentWithTextAndHtml, 10, 1);

$thisCharacter = substr($contentWithTextAndHtml, 11, 1);

$thisCharacter = substr($contentWithTextAndHtml, 12, 1);

And so on. You see what is going on here? Each time we loop, we look one character further into $contentWithTextAndHtml, and we get just 1 character. This allows us to eventually get every character in the whole block of text.

But there is still a problem with our code. What happens when we are given a block of text that does not have 20 white spaces in it? What if we get text like this:

“OmniNewsGather is one of our clients.”

That text only has 5 white spaces in it. So this line of the while loop would never stop:

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar) {

We would end up with what is called an “infinite loop”. This is a loop that never ends. Because $howManyWhiteSpacesHaveWeFoundSoFar never equals 20, the loop just keeps going forever. You will be wondering why your code isn’t working.

I recall the first time I wrote an infinite loop. Debugging it was hellish because there were no errors. This is not like getting a syntax error, which ususally tells you what you need to fix. An infinite loop is a subtle, hard to find bug.

If you are lucky, substr() will throw an error which will give you a clue. The error might appear once you start requesting characters that are beyond the end of $contentWithTextAndHtml. For instance, there are 37 characters in this block of text:

“OmniNewsGather is one of our clients.”

So you might get an error once the code does this:

$thisCharacter = substr($contentWithTextAndHtml, 38, 1);

because 38 will be beyond the end of $contentWithTextAndHtml.

What we need to do is put in an extra check, to see if we have reached the end of $contentWithTextAndHtml. So our code would look like this:

$contentWithTextAndHtml = get_the_content();

$lengthOfText = strlen($contentWithTextAndHtml);

$howManyCharactersHaveWeCountedSoFar = 0;

$howManyWhiteSpacesHaveWeFoundSoFar = 0;

$areWeInsideOfHtml = false;

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar && $lengthOfExcerpt > $howManyCharactersHaveWeCountedSoFar) {

$thisCharacter = substr($contentWithTextAndHtml, $howManyCharactersHaveWeCountedSoFar, 1);

if ($thisCharacter == “<") $areWeInsideOfHtml = true;

if ($thisCharacter == ">“) $areWeInsideOfHtml = false;

if (!$areWeInsideOfHtml) {

if ($thisCharacter == ” “) $howManyWhiteSpacesHaveWeFoundSoFar++;

}

$howManyCharactersHaveWeCountedSoFar++;

}

So, what does this line mean?

while (20 > $howManyWhiteSpacesHaveWeFoundSoFar && $lengthOfText > $howManyCharactersHaveWeCountedSoFar) {

In English, this would read as “Loop until $howManyWhiteSpacesHaveWeFoundSoFar equals 20, but only while the length of the text is greater than the number of characters we have counted so far.”

The second part of this while statement protects us against infinite loops. Because now, if we have a sentence like this:

“OmniNewsGather is one of our clients.”

Then the loop will stop after counting 37 characters, even if the code has not yet found 20 white spaces outside of HTML.

When the loop is done running, $howManyCharactersHaveWeCountedSoFar might equal as little as 60 or 70 or it might equal 600 or more, depending on how much HTML there is in the first 20 visible words. For the client, our actual task was to run some tests on the full string that makes up the first 20 visible words:

$shortenedContent = substr($contentWithTextAndHtml, 0, $howManyCharactersHaveWeCountedSoFar);

if (stristr($shortenedContent, “href”)) {
// do stuff here if a link is detected
}

The while() loop is, I think, easy for beginners to get. What is tougher is the for() loop. It is important to realize that the for() loop is totally arbitrary. At some point some programmers decided it would be convenient to take the elements of a while() loop, and write them all on one line. A typical for() loop would look like this:

for ($i=0; $i < count($arrayOfWordPressPosts); $i++) {

$thisPost = $arrayOfWordPressPosts[$i];

// do stuff here with WordPress posts
}

This part of the for() loop simply sets up a variable that we can use to keep count of how many times we have looped:

$i=0

Traditionally, the “i” is suppose to stand for “incrementor”. We will increment it each time we loop. “Increment” basically means “we will add 1 to this variable”.

This part of the loop explains how long the loop should run for:

$i < count($arrayOfWordPressPosts)

Assume that we have an array with 5 WordPress posts in it. The above loop will run until $i equals 5. That is, it will run when i equals 0, 1, 2, 3 and 4, which means it will run 5 times.

The last part of this for() loop statement increments $i:

$i++

This last part is called every time the loop loops. You might ask “Why does this first part, which assigns a zero to i, run only once, but the last part runs every time that the loop loops?” That is a good question. I do not know the answer. This aspect of for() loops has always struck me as completely arbitrary.

The worst thing about Symfony is how badly documented Propel is

Monday, August 31st, 2009

There is a reason why Symfony developers are switching en masse to using Doctrine as their ORM, and that reason is the fact that Propel is badly documented. I’ve been using Symfony/Propel for a year now, and this is the most coherent explanation I’ve yet found about creating OR statements:

It is not a mistake but how propel works. I also thought that writing code like yours I will get an OR but $c->addOr() is when you want to include a rule about the same database field. By default $c->add() will overwrite the previous rules if the first argument (the table field) is the same, thus $c->addOr will make an OR statement for this field. The same is true for $c->addAnd() but you thought it works correct because by default it uses AND between fields, but the purpose of $c->addAnd is when you define different criteria for the same field and you want them connected with and AND. Also why are you using Criterion object directly?

Why does Berkeley think it should be in the business of building its own content management systems anyway?

Thursday, August 27th, 2009

Brad Delong asks “Why does Berkeley think it should be in the business of building its own content management systems anyway?“.

His complaint:

May I say that a content management system that–if you have been off dealing with another crisis in the middle of a task–decides when you come back and try to save your work that you are no longer logged in and dumps you to a login page after which it dumps you not on the page you were working on but on the root page, LOSING YOUR WORK!!!1!!

Such a content management system is HELLSPAWN!! Is WROSE THAN HILTER!1!!!1!…

He is complaining about bspace, which is based on the open-source
Sakai, a content management system written in Java, and focused on the needs of universities.

I think Delong’s post is a good reminder of how infuriating it can be for users when software fails to behave in the ways users expect. I also suspect this is a good example of an issue that users will regard as a bug, but the programmers will see it simply as a potential future feature that they may or may not add (”Should we catch POST info if a user is not logged in?”).

I should add, WordPress has exactly the same problem. Last week I started writing what I thought would be a short post for this blog, but I got carried away by my theme and wrote a long post. Then I went to get some dinner. I left the browser open, with the post unpublished. I came back after dinner and made some more edits, then hit the publish button – and just like that, my work vanished, because while I was out getting dinner, WordPress logged me out (for some reason I’d assumed that the auto-save feature was also refreshing my session info).

One of the nice things about building my own CMS was that I was free to fix the bugs that bothered me most, and this was a big one for me. I added a feature to my CMS that caught any POST info and showed it on screen, even if the person was logged out. This allowed recovery of the post. I worked on my CMS from 2002-2007 and then abandoned it because I could not keep up with projects like WordPress. Nowadays I force myself to use other people’s open source software, because it is economically rational to do so, but I hate some of the choices they make, and some of the features that they fail to implement.

In the comments, Jacob Davies posts this comment, which I thought was very funny and very on point:

Conversation that has happened more times in my career than I care to mention:

Someone else: “How long of a title shall we allow? 32 characters? 64?”

Me: “FOR THE LOVE OF GOD WHY DO WE NEED TO SET A MAXIMUM LENGTH? IS THIS 1952???”

Someone else: “But what if they put in a really long title and fill up the database?”

Me: “THE VERY NEXT FIELD – THE ‘CONTENTS’ FIELD – IS A FREE-TEXT FIELD WITHOUT A LENGTH CONSTRAINT SO IF THEY WANTED TO FILL THE DATABASE THEY COULD DO IT THERE ANYWAY.”

Someone else: “Won’t it waste space if we allow a variable-length string in the title?”

Me: “OH MY GOD YES A TERRIFYING LOSS OF ABOUT 3 BYTES ON A RECORD THAT IS A MINIMUM OF 1024 BYTES LONG AND OFTEN OVER A MEGABYTE, YOU ARE SO RIGHT.”

Someone else: “Yes but every other system has a length constraint for titles.”

Me: “YES AND I SUPPOSE IF EVERYONE ELSE WAS JUMPING OFF A BRIDGE YOU’D DO IT TOO.”

etc

Computer programmers are subject to some kind of strange mental degeneration in which they rate the potential waste of 0.00001% of the capacity of a modern hard disk as more important than the ability to enter titles longer than 32 characters in length.

The Context object in Symfony can cause hassles

Monday, August 24th, 2009

This summer I worked on a project where some other programmer had used the Context object in the model classes. This caused ridiculous problems. For instance, to run the command line tools (such as “symfony propel:build-model”) I had to hard-code the loading of a context object into the core classes – what an ugly hack!

So I was intrigued to read of the problems that the Context object can cause in your form classes, and how dependency injection gives us an easy way to avoid needing the Context object.

You might read that and think “woah, this is getting complicated!” but we’re not talking about dependency injection containers here, we’re simply saying that you can make your form object depend on something to run. The thing it depends on should not be the context singleton, it should be the minimum thing that the form needs to operate correctly – which in this case, is a user object that supports credentials.

…The test here is where we are making this form “dependent” on a user object. In this case we are insisting that the object is an instance of sfUser, which you may argue is tying us in to symfony again, but you could use any test here to ensure that the object will have the necessary functionality you need, maybe check for the existence of a “hasCredential()” method for example.

When writing a test for this form class, we now only need to instantiate a user object and load it with some credentials – much easier than doing the same thing and locking into a context singleton. There may be other times when this form could be useful in a lightweight environment, where you can get speedy access to a user object but don’t want the overhead of the symfony context – you might not think of one now, but it’s best to code this way and you’ll have less reasons to kick yourself further down the line.

How to redirect to original destination after login in Symfony

Sunday, August 23rd, 2009

How to redirect to original destination after login in Symfony. I recall this information was way too hard to find when I first went looking for it:

on first hit to your login action, store referer to the user session:

if(!$this->getUser()->hasParameter(’referer’))
{
$this->getUser()->setParameter(’referer’,$this->getRequest()->getReferer();
}

and then when login succedes, redirect user to stored referer with:

$this->redirect($this->getUser()->getParameter(’referer’);

Left JOINs with Propel in Symfony

Sunday, July 26th, 2009

Here is the stupid, clumsy way that I tried to do a LEFT JOIN in Symfony:

$query = ”
SELECT bailiwick_question.*, count(bailiwick_answer.id) AS howManyAnswers
FROM bailiwick_question LEFT JOIN bailiwick_answer
ON bailiwick_question.id = bailiwick_answer.question_id
WHERE bailiwick_question.end_at > ‘” . date(’Y-m-d h-i-s’) . “‘
GROUP BY bailiwick_question.id
ORDER BY howManyAnswers desc
“;

$connection = Propel::getConnection();
$this->questionStatement = $connection->prepare($query);

$this->pager = new statementPager(null, 10);
$this->pager->setStatement($this->questionStatement);
$this->pager->setPage($request->getParameter(’page’, 1));
$this->pager->init();

Here is the way someone much smarter than I re-wrote the code:

$c = new Criteria();
$c->addJoin(BailiwickQuestionPeer::ID,BailiwickAnswerPeer::QUESTION_ID, Criteria::LEFT_JOIN);
$c->add(BailiwickQuestionPeer::END_AT, date(”Y-m-d h-i-s”), CRITERIA::GREATER_THAN);
$c->addSelectColumn(’bailiwick_question.*’);
$c->addGroupByColumn(BailiwickQuestionPeer::ID);
$c->addDescendingOrderByColumn(’COUNT(bailiwick_answer.id)’);
$questions = BailiwickQuestionPeer::doSelectStmt($c);

A fast Symfony

Monday, May 25th, 2009

A very clever trick for using a portion of the Symfony framework to respond to Ajax calls:

Now I can execute a component from the client side. The component architecture offers native View/Controller separation, and the configuration initialization brings autoloading, database access, and more. It does work perfectly, but is it fast? Speed tests show that not launching the filter chain saves about 40% to 50% of the cost of a symfony initalization. This means that you can multiply the number of requests that your server can handle by two – for very simple requests.