The unset($args[0]) PHP Pattern

Suppose you are working on a system, and want to allow users to use so-called hooks to hook into the system and change it’s behavior. Think of it as wordpress’ filter/action kind-of-thing. This is in a way, something similar to events in javascript, and the purpose is basically the same: you want to do, or let others do something when something else happens, and potentially change the way the system works, or extend its functionality.

Implementing this kind of feature is surprisingly simple. All you need is a way to let people subscribe to your hooks, and a way to call all subscribed members for a certain hook at some point. The implementation details are not really our concern right now, but what happens when you call each subscribed member.

In order for hooks to be useful, you need to be able to pass relevant information to the subscribed members at call time. For example, in Javascript, native events get passed an event object that contains all sorts of useful information. The way you pass this information to the subscribed members will depend on your implementation of the subscribe method you use.

One pattern I’ve noticed working with drupal is unset($args[0]).

Drupal uses a hook system that allows developers to hook into the system simply by following some function naming conventions. The drupal specifics are not important right now. What is important is the way drupal calls its hooks: it uses a function called module_invoke_all.

The module_invoke_all function, in its definition, takes a single argument: the name of the hook. We already mentioned the importance that being able to pass information to the subscribed member has, so why is it that the drupal function to invoke hooks takes only the name of the hook as argument? How do you pass the relevant information?

PHP, just like other programming languages allows you to pass more arguments to a function that its formal parameters. The way you access the extra arguments passed to the function varies depending on the language. In php all arguments passed to a function are kept in the $args array.

Lets say you call module_invoke_all as follows:

module_invoke_all(‘my_hook’, ‘something cool’, ‘something interesting’);

Inside the function, the $args array will have 3 members, one for each argument passed to it. So, if you want to pass those values, minus the hook name to the subscribed members, all you need to do is get rid of that, and pass the resulting array to the subscribed members. That is why unset($args[0]) does.

I’m not sure this is the best way to do it, but it is certainly interesting. If you want to read the full code for the module_invoke_all function, just check out the drupal documentation on it (https://api.drupal.org/api/drupal/includes!module.inc/function/module_invoke_all/7)

Web Scraping with PHP

Web scraping is an interesting thing to do. There is a lot of data on the web, and there are many interesting things that can be done with it if it is scraped and organized in more meaningful ways. There are many ways of scraping data, and you may choose the one that is best for what ever it is you are trying to do. From the simplest of ways, manually copy and pasting, to the more complex such as automatic link following and computer-simulated human interaction, web scraping is useful, interesting and fun.

Imagine you want to study plane ticket prices and how the fluctuate over time.You may want to just bookmark the site, and visit every day. Copy the price and paste it into a spread sheet. This is OK since you only need to get a price and you could set some kind of reminder to make sure you don’t forget to do it. But what happens when you want to get price for the same ticket but different travel agencies, or even different airlines? Lets say you want to compare 100 different agencies. Now copy and paste doesn’t seem like a good idea.

A few days ago I had to gather information on car dealers from a site that allowed you to find car dealers near you based on your zip code. I had to run all the US zip codes, and get all the information into a database. That definitely didn’t sound like something I wanted to do with copy and paste, so I did what programmers do best: let the computer do the work.

I think many programmers will agree when I say that programmer are inherently lazy. I’m not talking about programmers spending all the time like a couch potato, because in fact many programmers work day and night. What I mean is that we like to do as little work as possible to accomplish a task. That is why we program in the first place, because we want to automate tasks so that we don’t have to bother ourselves with repetitive tasks.

So, how do you program a web scraper? There are many ways to do it, but the basic idea is always the same: fetch a resource from the net, usually a web page, analyze the code searching for the data that is relevant to you. Save that data somewhere. That is all you really need to know to start scraping data. So, lets build a simple web scraper in php.

Before continuing, I’d like to mention that there are scraping solutions already made. There is software for scraping data, and there are libraries written for many languages that specialize on data scraping. However, for the sake of learning, we are going to code our scrapers here by hand.

What do we need?
We need php, and a way to interact with the DOM. If you read my previous entry where I talk about php and the DOM, you know of a few options to do that. We will also need an idea of what we want to scrape. Lets start with something simple. We will scrape the box office information from IMDB. We will only do it this one time, but in a real life situation you may want to set a cron job to scrape the data daily, weekly or at any other interval of time.

The first thing we need to know is the URL of the page from which we want to scrape the data. In this case it is http://www.imdb.com/chart/
Then we need to know how to find the data in which we are interested. For that, since we are going to be using the DOM, you can just look at the source code of the page. You will notice that the information that we want to scrape is in a tr element with a class name of either chart_odd_row or chart_even_row. That is what we will use to identify the information.

Now, let the fun begin.

Crete a file called box_office_scraper.php. I placed it inside a directory called IMDB. Open the file on your favorite editor, and get ready to type.

First, lets get the document from the web:


$url = "http://www.imdb.com/chart/";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$document = curl_exec($curl);

echo $document;

We declare a variable to hold the url of the document we want to fetch.
Then we initialize curl, passing in the url.
We set the CURLOPT_RETURNTRANSFER option so that curl returns a string containing the document rather than printing it.
Then we execute curl, and save the returned string in a variable.
Finally we echo the contents of the variable just to make sure we got everything right. You should now be seeing the same thing you would see if you visited the url directly. We echo the contents just to verify, but we don’t really want to echo the contents, so you can now delete that echo line.

Now that we have the document, it is time to search for the data we want, but first we need to create a DOM representation of the document we have. Continue editing you file:


$dom_rep = new DOMDocument;
$dom_rep->loadHTML($document);

If you reload your page now, you should no longer see the page that you were seeing before (provided you deleted the echo). Depending on your php configuration, you may, however, see a bunch of warnings. That is because the document is malformed. Personally, I prefer to turn those warnings off in this case. Usually, I like to have all error and warnings visible, so I can find ways to get rid of them by fixing whatever is causing them, but in this case those warning are only polluting my page. If you want to get rid of the warnings, just add this line at the top of the document, right after the opening php tag:


error_reporting(E_ERROR);

This way you tell php to only report errors. We want to be able to see when something goes wrong.

Now that we have a DOM representation of the document, we can start working with it. Since we know the data we want is in tr elements, we can just grab them all and see if they have the class names we are looking for. Unfortunately, the DOM library that comes with php has no way to get elements by class name, so we will have to write our own.


$all_trs = $dom_rep->getElementsByTagName('tr');
$trs_we_want = array();
foreach ($all_trs as $tr) {
  $class_name = $tr->getAttribute('class');
  if (preg_match("/chart_(even|odd)_row/", $class_name)) {
    $trs_we_want[] = $tr;
  } 
}

We wrote a simple loop, but we could have written a more robust function. In this case the loop is enough.

Now that we have all the elements we need, we can proceed to get the data. One thing to notice is that we will get 30 tr elements, but we are only interested in the first 10. We get 30 because we also get the ones from the other two tables in the page.

Lets loop our elements up to the 10th and get the data:


for ($i = 0; $i getElementsByTagName('td');
  $the_tds_arr = array();

  foreach ($the_tds as $td) {
    $the_tds_arr[] = $td;
  }

  $movie_title = $the_tds_arr[2]->nodeValue;
  $rank = $the_tds_arr[0]->nodeValue;
  $weekend = $the_tds_arr[3]->nodeValue;
  $gross = $the_tds_arr[4]->nodeValue;
  $weeks = $the_tds_arr[5]->nodeValue;
  echo "
"; echo "

$movie_title

"; echo "Rank: $rank
"; echo "Weekend: $weekend
"; echo "Gross: $gross
"; echo "Weeks: $weeks
"; echo "
"; }

As you can see, we are only looping and getting the data that we want. We created the $all_tds_arr array because we cannot access the $all_tds as an array. We could have used more DOM, but the idea here was to keep it as simple as possible. In this example we are only printing the info on screen, but on a real life situation you may want to save it to a file, a database, or a spreed sheet, or some other kind of back end that you have.

Here is all the code:


error_reporting(E_ERROR);

$url = "http://www.imdb.com/chart/";
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$document = curl_exec($curl);

//echo $document;

$dom_rep = new DOMDocument;
$dom_rep->loadHTML($document);

$all_trs = $dom_rep->getElementsByTagName('tr');
$trs_we_want = array();
foreach ($all_trs as $tr) {
  $class_name = $tr->getAttribute('class');
  if (preg_match("/chart_(even|odd)_row/", $class_name)) {
    $trs_we_want[] = $tr;
  }
}

for ($i = 0; $i getElementsByTagName('td');
  $the_tds_arr = array();

  foreach ($the_tds as $td) {
    $the_tds_arr[] = $td;
  }

  $movie_title = $the_tds_arr[2]->nodeValue;
  $rank = $the_tds_arr[0]->nodeValue;
  $weekend = $the_tds_arr[3]->nodeValue;
  $gross = $the_tds_arr[4]->nodeValue;
  $weeks = $the_tds_arr[5]->nodeValue;
  echo "<div>";
  echo "<h2>$movie_title</h2>";
  echo "Rank: $rank<br />";
  echo "Weekend: $weekend<br />";
  echo "Gross: $gross<br />";
  echo "Weeks: $weeks<br />";
  echo "</div>";
}

On the next post we will see how we could use the libraries we talked about in the past for working with the DOM to make scraping easier.

DOM and PHP

My first programming language was javascript, and the book that made me first realize that I wannted to program for a living was DOM scripting from publisher Friends of ED. Back then I thought javascript was all about DOM manipulation, and honestly, back then it was. Now, javascript has become a more respected language and has found its place as the king on the realm of client side programming, and it has made its way to the server end. But DOM manipulation is still a need. For better or worse, the DOM doesn’t seem to be going away any time soon.

Just this week I’ve been working with the DOM, but this time in php. So how is it like to work with the DOM in php? While this is not my first time working with the DOM in php, I must say that it feel wierd. I think PHP + DOM is not a natural combination, but it works well none the less.

When you want to work with the DOM in PHP, you have a few options. I’ve found that the PHP library is enough, but maybe not the most comfortable way. It is what I use anyway, but that is because I only needed to interact with the DOM very little, if you need heavy DOM interaction in PHP, I would recommend you look at some of these projects:

htmlSQL: htmlSQL is a very simple php class that makes it really easy to navigate the DOM using SQL-like syntax. The project has been abandoned, but if you just need to do some interaction with the DOM, it should be enoug. Optionally, if you really like the project, you could fork it and continue its development.

Simple HTML DOM: This is another options. It follows a more OOP approach to navigating the DOM, and it has fetures that the PHP DOM library lacks, like the hability to pass in a URL and get the DOM representation of that resource. If you want to do that with the PHP DOM library, you would need to first fetch the document using something like cURL, and then load the HTML into the DOM object.

PHPQuery: This is probably the most interesting project. It is ispired by jQuery, so if you are familiar with jQuery, you will love phpQuery. Do not expect, however, to find function like fade or animate, they would not make sense on the server side where there is no visual representation of the DOM. You can ofcourse make animations on the server side, but that would just be silly.

Next time I will show you how to build a simple web scraper with php, and we will use these libraries, and the PHP DOM library and see which one is the easiest to work with.

Even more links

Some may say I’m not even running a blog anymore since all I do is share links. The truth is that there is so much material out there, and some of it deserves to be shared. That, and also the fact that I’ve hadn’t taken the time to write some content of my own. I do, however, have two of a few articles that I’m writing for a series called Practical PHP Applications. I haven’t decided yet if I will publish them here or look for a place in a site specialized in php, but I will let you know when I decided.

Anyway, here is a big list of links not arranged in any order. Some of them are in Spanish, so just click around and hope to be lucky!

http://www.atareao.es/ubuntu/listando-en-el-terminal-con-color-en-ubuntu-y-un-poquito-de-bash/
http://arstechnica.com/information-technology/2013/03/genius-or-insanity-exec-did-all-his-work-on-galaxy-note-for-a-year/?
http://androidandme.com/2013/03/applications/android-rookies-10-new-apps-worth-checking-out-this-week-15/
http://alt1040.com/2013/03/curiosity-vida-en-marte-2
http://alt1040.com/2013/03/individualidades-tendiendo-a-lo-salvaje-le-declara-la-guerra-a-la-nanotecnologia
http://arstechnica.com/science/2013/03/atmospheric-analysis-reveals-an-exoplanet-thats-as-alien-as-can-be/
http://ginicharts.com/google-reader-alternatives
http://www.nytimes.com/aponline/2013/03/14/world/europe/ap-eu-switzerland-god-particle.html
http://www.scamk.com/www-ceylon-tech-com-tech-support-is-a-big-scam.html (This one I searched for after getting a few calls from ceylon tech)
http://stackoverflow.com/questions/107683/when-and-why-should-request-be-used-instead-of-get-post-cookie
http://stackoverflow.com/questions/3983933/security-risk-request-variables-on-the-local-stack
http://phpmaster.com/avoid-the-original-mysql-extension-1/
http://phpmaster.com/preventing-code-rot-101-unit-testing/
http://phpmaster.com/the-mvc-pattern-and-php-2/
http://phpmaster.com/pci-compliance-and-the-php-developer/
http://phpmaster.com/logging-with-psr-3-to-improve-reusability/
http://phpmaster.com/dip-intro/
http://en.wikipedia.org/wiki/Dependency_inversion_principle
http://phpmaster.com/top-10-php-security-vulnerabilities/
http://phpmaster.com/5-more-php-security-vulnerabilities/
http://arstechnica.com/tech-policy/2013/03/wordpress-to-fight-legally-deficient-and-objectionable-prenda-subpoena/
http://tech.cueup.com/blog/2013/03/06/how-our-terminal-friendly-jobs-page-works/
http://techblog.netflix.com/2013/03/python-at-netflix.html
http://www.campaul.net/blog/2013/03/10/why-im-switching-back-to-firefox/
http://www.technologyreview.com/view/512381/astrobiologists-find-ancient-fossils-in-fireball-fragments/
http://felixge.de/2013/03/11/the-pull-request-hack.html
https://github.com/felixge/node-mysql
https://github.com/felixge/node-formidable
http://openmymind.net/Things-I-Wish-Someone-Had-Told-Me-About-Go/
http://amazonbitcoins.com/
https://www.bitspend.net/
http://www.cstthegate.com/davetrott/2013/03/working-while-youre-asleep/
https://news.ycombinator.com/item?id=5358010
http://www.theregister.co.uk/2013/03/08/modernmix_saves_windows8/
http://www.arcticstartup.com/2013/03/11/starthq-targets-and-launches-web-apps
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=33357 (Interesting Analog clock with SQL)
http://blogs.discovermagazine.com/discoblog/2009/01/29/the-curious-case-of-the-immortal-jellyfish/

There are a whole lot more links where these came from, but unless you are addicted to reading like me, then I think it is enough for today.

Shoot Yourself on the Foot by Using PHP’s Extract

PHP’s extract function is one of those function that we use mostly because we are lazy. It makes it really easy to access associative arrays’ members without having to write too much. For example, imagine you have to process a form submitted by the user that has 50 different fields. You would have to do something like this in order to access the field values:


$name = $_POST['name'];
$meail = $_POST['email'];
$company = $_POST['company'];
.....

You would have to write 50 lines that look like those ones above to access every field value in the submitted form. I don’t think I need to mention what a pain that is. In fact, it is such a burden that on a lazy evening we might just write something like this:


extract($_POST);

Which is a really nice way to shoot yourself on the foot.

The problem with that is that it may end up overwriting variables defined previously. I guess you could argue that the first piece of code in this post does the same thing. For example if $name is already defined, it would be overwritten, which is certainly true. However, you are aware of that, and even if you are not, you will notice it a some point. The problem with extract is that another variable could be inserted and you would never know it. Lets see an example of what I mean:

Yesterday, while working on a project, I realized the security risks of extract. I have been working on this project for the last few days, and I was using extract in a few places on the code, but I was feeling uneasy about that. I thought there might be security implications with extract. In my experience, any function that makes handling unsafe data easy has some security implications. I decided to look into that, and sure enough there are security risks if extract is used carelessly, and just because you are too lazy to do things the long, usually right, way.

The applications that I’m working on has members, so we need a way to log them in and we do it through a form. This for is posted to a file on the application’s engine that takes care of processing it and determining whether the user should be logged in or not. For testing purposes I was using a variable a flag for users being logged in or not. Usually you would use sessions to do that, but for testing purposes a variable was good enough. Lets imagine the code looked like this:


$logged_in;

if(logged_in){
   //render screen for logged in users
}else{
   //render log in form
}

As I mentioned before, the log in form posts to a file that takes care of the log in logic. Then, if something goes wrong, it redirects to the log in page, and sends the submitted data using GET. The log in page then checks if that data is been submitted via GET, and if so, it uses it to display the submitted values on the form so the user doesn’t have to write all his info again. With that in mind, lets modify the code a bit:


$logged_in;

if($_GET && isset($_GET['data'])){
    userialize($_GET['data']);
    extract($data);//This makes getting the data information easy.
}

if(logged_in){
   //render screen for logged in users
}else{
   //render log in form
}

You can see where we are using extract. It will create variables based on the indexes of the data array. Now, what happens if someone modifies that data array? Suppose the array looks like this:


$data = array('name'=>'John Doe', 'email'=>'john@doe.com');

When we use extract this would create two variables. This is what we want, so that instead of doing $data['name'] we can access the value directly by doing $name. But if someone modifies the array to something like this:


$data = array('name'=>'John Doe', 'email'=>'john@doe.com', 'logged_in'=>true);

Then we have problems. This will create a logged_in variable with true as its value. This would overwrite whatever value is set on our $logged_in variable, and let the user log in without the right credentials. Now, remember that the code above is all just for the sake of this example. I don’t think anyone who knows what they are doing would write code like that. However, it serves the purpose of showing how dangerous it can be to use extract carelessly.

The extract function can be called with parameter that specify how it should handled variable collisions. But in my opinion, you should just avoid using it when processing user submitted data or any other kind of unsafe data.

I recommend reading the extract documentation if you plan on using it.

Double or Single Quotes on preg_replace ?

Today I run into a curious issue while implementing payment processing via authorize.net on a website. The issue has nothing to do with the website or authorize.net, but rather with php.

On the website, users ca chose a donation option. This options have values like “Donation Option – $50”. I have to submit them like that because that value needs to be passed to authorize.net as a custom field, but in order to capture the monetary value, I need to parse that string. At some point I end up wit just the number, and the sign (ej: $50). At this point it is just a matter of removing the sign from the number, so I do this:

preg_replace("/\$/", "", $money);//$money holds the value, in this case "$50"

But that does not work. Inspecting a bit further I realize what the problem is:

preg_replace("/\$/", "B", $money);// gives back "$50B"

this means, that piece of code is actually being interpreted as:

preg_replace("/$/", "B", $money);

so the $ is not being escaped, and we are loosing / at some point. So I decided to do a little duckduckgoing (that is like googling, but for duckduckgo.com), and I find this form discussion:

http://board.phpbuilder.com/board/showthread.php?t=10124101

Let’s try it out:

preg_replace("/\\$/", "", $money);//gives back 50.

This works!, but why? Well, the fact that this works means we need to escape the \ as well in order to be able to scape the $. What about something a bit different:

preg_replace('/\$/', "", $money);//gives back 50

This works too! At this point I remember that in php strings are treated differently depending on how you quote them. You can read more about it on http://www.php.net/manual/en/language.types.string.php

So, I conclude that this problem has to do with string expansion, and that is is better to use single quotes (‘) instead of double quotes (“) when working with regexps in php.

Back References in PHP: How to Create Variable Variables Using Them

I found and interesting problem today. I am working on a wordpress plugin and I wanted to use some sort of template to display the results of a search. I came out with a nice solution that would let me use some text wrapped around % and %. This should be replaced by some variable value. Since I wanted the template to be future proof, I did not want to do something like:

$template = preg_replace(‘/%name%/’, $name);
$template = preg_replace(‘/%last%/’, $last);

but rather, I wanted something that would “guess” the variable names from the text to be replaced. This seemed like an easy thing to do. The first thing I thought was backreferences.

The idea was that if I created a variable variable from the backreference I would be able to accomplish the job. However, it was not that easy.

This is what I have.

I have a function that takes an argument. This argument is an array of arrays containing the data to be placed in the template. A simplified version of the array would look like this:

array(
  [0] = array(
    [name]="John",
    [last]="Smith",
    [phone]="(123)123-1234"
  ),
  [1] = array(
    [name]="John",
    [last]="Smith",
    [phone]="(123)123-1234"
  ),
  [2] = array(
    [name]="John",
    [last]="Smith",
    [phone]="(123)123-1234"
  )
)

so, that is what the function would receive. The function looks like this:

function templating($data){
  foreach($data as $d){
    extract($d);
    ob_start();
    ?>
    <p>
      Name: %name% %last%
      <br />
      Phone: %phone%
    </p>
    <?php
    $mkp = ob_get_contents();
    ob_end_clean();
    $mkp = preg_replace('/%(.+?)%/', $"$1", $mkp);
    echo $mkp;
  }
}

Well, this doesn’t work. It turns out you cannot create a variable variable out of the backreference like I tried to do there. After some failed attempts to create a variable variable out of a backreference, I tried something different.

Before we continue, if you don’t get it. Let me explain the thoughts that led me to write the code up there.

Since I have the array structured showed earlier, I thought I could extract the values into their own variables and reference them in the replacement. The commented code might help you understand better, (and maybe even me in the future when I forget all this XD)

function templating($data){
  foreach($data as $d){
    extract($d);
    //at this point I have individual variables holding the data for each loop run
    //so, for the first loop I have:
    //$name = "John"
    //$last = "Smith"
    //$phone = "(123)123-1234"
    ob_start();
    ?>
    <p>
      Name: %name% %last%
      <br />
      Phone: %phone%
    </p>
    <?php
    $mkp = ob_get_contents();
    ob_end_clean();
    $mkp = preg_replace('/%(.+?)%/', $"$1", $mkp);//the regexp matched %name%, %last%, %phone%, and returned name, last, and phone as backreference values.
    //I thought I could create a variable variable using $"$1", since that would
    //become $name, $last, and $phone, but that is not what happens.
    echo $mkp;
  }
}

I decided to take a look at preg_replace_callback.

I rewrote the function like this:

function templating($data){
  foreach($data as $d){
    extract($d);
    ob_start();
    ?>
    <p>
      Name: %name% %last%
      <br />
      Phone: %phone%
    </p>
    <?php
    $mkp = ob_get_contents();
    ob_end_clean();
    $mkp = preg_replace_callback('/%(.+?)%/', function($m){
      global ${$m[1]};
      return ${$m[1]};
    }, $mkp);
    echo $mkp;
  }
}

But that didn’t work either, although it was closer.
I kept on modifying the function a bit more, and came out with this:

function templating($data){
  foreach($data as $d){
    ob_start();
    ?>
    <p>
      Name: %name% %last%
      <br />
      Phone: %phone%
    </p>
    <?php
    $mkp = ob_get_contents();
    ob_end_clean();
    $mkp = preg_replace_callback('/%(.+?)%/', function($m){
      extract($d);
      return ${$m[1]};
    }, $mkp);
    echo $mkp;
  }
}

This did not work either, but it gave me a clue of why the previous function hadn’t worked. I thought that since the callback was within templating, it would have access to the variables, but it did not. Then I made $d global in the callback, but it still didn’t work. So I figured that it was not accessing the variable. I finally made $d global in templating, and that worked. Note that we declare $d global before the loop, otherwise the $d declared in the loop will be overwritten by the global declaration of $d.

The function ended up like this:

function templating($data){
  global $d;
  foreach($data as $d){
    ob_start();
    ?>
    <p>
      Name: %name% %last%
      <br />
      Phone: %phone%
    </p>
    <?php
    $mkp = ob_get_contents();
    ob_end_clean();
    $mkp = preg_replace_callback('/%(.+?)%/', function($m){
      global $d;
      extract($d);
      return ${$m[1]};
    }, $mkp);
    echo $mkp;
  }
}

This way I was able to accomplish the goal, and I got a pretty nice templating system. Now I can even move the HTML into a template file and load that template file instead of having the markup in the functions. Why would I do that? Because that keeps the code cleaner and makes it easy to edit the template without touching the function, which is always a good thing.

I was curios about why the very first attempt did not work, so I asked a question on one of those Q&A sites, you can follow it here: http://programmers.stackexchange.com/questions/133685/is-it-possible-to-create-a-variable-variable-from-a-back-reference-in-php

I also found this page useful since I didn’t remember how to get the backreferences in php:
http://stackoverflow.com/questions/4694169/how-to-use-backreferences-in-php

And finally, if you want to read more about variable variables, you should read:
http://www.php.net/manual/en/language.variables.variable.php

Making Decisions Inside Function Calls

I am currently actively developing using CORE. CORE is a library I’m writing to simplify the tedious process of writing HTML. Instead of doing this:

<div class="wrap">
  <p>Hello There <a href="somePage.html">read this</a></p>
</div>

You can do this:

div(
  p(
    'Hello There'
    .a('read this', 'somePage.html')
  )
  ,'wrap'
);

I really find it more pleasing to write that kind of code than writing markup, and I’ve seen an increase on my productivity due to the fact that I have to write less code, the end result is easier to read, it is easy to divide the page in functions that display different sections of the page. For example,you can do this:

div(
  theContent()
  .theComments()
);

theContent() is a function that returns the markup for the content of the page, and theComments() does the same for the comments section of the page. There are many other benefits, like the fact that I no longer need to worry about closing tags in the right order, or making sure all tags have a matching closing tag.

There is, however, one problem that was driving me nuts. Quite often you want to write something or other depending on some parameters. For example, if you are developing a wordpress theme, you might want to display some alternative text when there are no comments to show on a page. The usual way to do that would be:

if(have_comments()){
  //code here to show the comments
}else{
  ?><p>There are no comments to display</p><?php
}

But how do you do that with CORE?

One way would be to manage your logic outside the function call:

if(have_comments()){
  $comments = //code to show the comments
}else{
  $comments = p('There are no comments to display);
}

div(
   theContent()
   .$comments
);

But there are sometimes when you just want to handle the logic inside the function call. I can’t remember how many times I said “I wish I could just handle that inside the function call instead of having to create an extra if”.

Well, today I got an Idea. It istarted with a simple

alert(1==2 || 'b');// this is javascript

which then became

alert((1==1 ? 'b' : 'c') + ' yep');//still javascript.

Then I decided to take that idea into php. I think that was the best thing that I did today. Now I can do something like this:

div(
        h4('What people are saying')
        .(have_comments() ?
                '<ol id="comment_list">'
                .loadFunction('wp_list_comments')
                .'</ol>'
        :       
                'There are no comments to display. Add yours'
        )
        .br()
        .loadFunction('comment_form')
        ,'two_third'
);

Don’t mind the loadFunction() calls, they just “trap” the output of functions that do not return their result, but print it. What is important here is to notice the ternary operator, which makes handling the logic inside the function call possible.

What do you think about this? Personally, I believe it opens up many new possibilities, especially for people like me, who love working with functions, and who got excited when php 5 started supporting lambdas.

Como activé curl en ubuntu 9.10?

Ayer estaba actualizando una aplicación que hice hace un tiempo. La app está basada en php y necesita comunicarse con pay pal. Para lograr comunicación con pay pal uso curl, pero cuando quise correr la app en local me di cuenta que mi php no estaba usando curl. Para poder usar curl solo tuve que hacer dos cosas:

1)instalar curl para php. Para eso basta con correr la siguiente instrucción en terminal:

sudo apt-get install curl libcurl3 libcurl3-dev php5-curl

Tedarás cuenta que estamos instalando más que solo curl para php, pero está bien. Probablemente esos paquetes ya venían por default (como en muchas distribuciones de linux). No cheque antes de instalar.

Una vez tenemos curl, solo basta con recompilar php si lo compilaste manualmente. Solo baja la distribución que quieras compilar, puedes aprovechar para instalar una versión nueva si no has actualizado. Una vez estes listo para correr el ./configure, agrega la –with -curl a las opciones:

./configure –with-curl

Toma en cuenta que tienes que agregar todos los demás –with dependiendo de lo que quieras configurar en tu instalación. No explico mucho en este punto ya que si tienes que hacer esto quiere decir que ya has complilado php anteriormente y sabes de lo que hablo.

Por último, reincica apache o inicialo si no lo has hecho ya.

sudo /usr/local/apache2/bin/apachectl -k start

para iniciar o:

sudo /usr/local/apache2/bin/apachectl restart

Eso asumiendo que tu instalación de apache esta en /usr/local/

Espero que puedan seguir las instrucciones y poner a disponibilidad curl que puede ser muy útil.

Formularios más inteligentes con php.

Bueno, una nota primero en cuanto al titulo del articulo. La neta que no sabía ni como llamarlo, así que el titulo igual y no sea 100% descriptivo del contenido del post.

Habiendo dicho eso, prosigamos. Hace unos días me encontraba con un dilema. Has encontrado alguna vez con un formulario que quieres que muestre una página u otra dependiendo de si la acción fue realizada con éxito o no? Bueno, pues ese era mi dilema. Es muy sencillo solucionarlo, pero yo no quería tener que cambiar la estructura de toda la aplicación (un CMS).  Explico el problema para que veas un poco más de lo que hablo:

Tengo una pagina que se llama digamos “informacion.php”. Esta pagina se encarga de tres cosas, 1)agregar información nueva, 2)editar información existente y 3)borrar información existente. Para poder hacerlo toma el valor de una variable que se le pasa por GET, de modo que si la variable tiene como valor “aInfo”, la pagina muestra un formulario para poder agregar información nueva. El formulario tiene como action ‘informacion.php?modo=aInfo’, de modo que si al hacer la validación del formulario se determina que el formulario no es valido, se muestra un error y se vuelve a mostrar el formulario con los elementos que ya habían sido introducidos. Esto es por motivos de usabilidad ya que si el action del formulario fuera solo ‘informacion.php’, la aplicación no mostraría nuevamente el formulario y al presionar el enlace que nos lleva al formulario los datos de POST se perderían dejando sin posibilidad de introducir automáticamente los datos previamente introducidos por el usuario, obligando al usuario a escribir todo de nuevo en lugar de solo editar lo que estaba mal.

Algunos pueden argumentar que se puede usar GET para enviar los datos de POST al formulario nuevamente, pero eso representa más trabajo, a demás de no representar ninguna garantía debido a las limitaciones de GET e incluso podría ser perjudicial ya que el usuario pensaría que todo esta como él lo había dejado anteriormente cuando la realidad pudiera ser que un texto muy largo no haya sido incluido en su totalidad por GET, eso solo por mencionar uno de los muchos problemas que esta ‘solución’ nos podría traer. Otro método igualmente ineficiente es pensar que como se implementará validación en tiempo real mediante javascript se puede confiar en que el problema será captado por javascript y no habrá necesidad de requerir al usuario que navegue manualmente al formulario nuevamente después de haberse encontrado un error en el formulario enviado.

Ninguna de estas dos opciones me convence por completo. Para que comprendas mejor de lo que hablo, muestro aquí una estructura de como está el código:

<?php

$ok = chacarFormulario(‘info’);
//checarFormulario regresa true o false dependiendo de si el formulario es o no valido
if(!$ok){
$error=”formulario invalido”;
//La variable error es capturada después por la aplicación y mostrada al usuario
}else{
//Guardo todo en la base de datos
}

?>

Si todo está bien no necesito mostrar el formulario ya que eso puede confundir al usuario a demás de que se ve feo. Si, por el contrario, hay algún error, necesito mostrar el formulario con los campos previamente llenados con la información que el usuario introdujo antes de enviar el formulario. Esta info se encuentra en $_POST, pero no entrare en esos detalles. La cosa es que para poder mostrar esa formulario action tiene que estar como ‘informacion.php?modo=aInfo’, pero eso me trae problemas si todo estuvo bien ya que para que no se muestre el formulario la variable modo no tiene que estar presente (o seteada como dicen algunos).

En otras palabras, si el formulario está correcto su action debería ser “informacion.php” y si no, el action debería ser “informacion.php?modo=aInfo”, pero claro, es imposible cambiar el action del formulario después de haberlo enviado y no hay forma de saber si el formulario es valido y así cambiar su action antes de enviarlo. Un dilema con una solución más fácil de lo que parece.

Mientras algunos empezarían a hacer raras convinaciones entre POST y GET y a usar variables para esto y para lo otro creando una pesadilla de código. Yo preferí sentarme a analizar el tema y llegue a la conclusión de que, si el problema era la existencia de la variable modo, bastaría con borrar esa variable y todo andaría bien.

Efectivamente, basta un simple unset para solucionar el problema:

<?php

$ok = chacarFormulario(‘info’);
//checarFormulario regresa true o false dependiendo de si el formulario es o no valido
if(!$ok){
$error=”formulario invalido”;
//La variable error es capturada después por la aplicación y mostrada al usuario
}else{

//Guardo todo en la base de datos
unset($_GET[‘modo’]);
}

?>

De esta manera, para cuando la applicación llega a la parte que decide que parte mostrar (un formulario para gregar info, un listado de la información existente o una tabla con opciones de editar y borrar), lo cual hace dependiendo del valor de modo, se da cuenta que modo no existe, aún cuando en nuestra URL siga estando. Como para php modo ha sido eliminada y por consiguiente ya no existe, la aoplicación toma el valor por defecto. Para entenderlo mejor, te muestro la estructura de la parte de la app que decide que parte mostrar:

<?php

if($_GET && isset($_GET[‘modo’])){
switch($_GET[‘modo’]){
case ‘aInfo’:
//muestra formulario para agregar info
break;
case ‘eInfo’:
//muestra opciones para editar info
break;
//mas de lo mismo case break, case break…
}
}else{
//si la variable $_GET[‘modo’] no existe entonces:
//muestra tabla con lista de info existente y opciones de borrar y eliminar.
}

?>

En caso de que todo haya estado bien, la vaiable modo es eliminada (para eso usamos unset()) por lo que cuando se llega a la parte de código apenas mostrada arriba, se ejecuta el código dentro del else{ } como si nuestro formulario hubiera sido enviado con action=”informacion.php”, cuando en realidad ha sido enviado con action=”informacion.php?modo=aInfo”.

Bueno, espero que se haya entendido por lo menos un poco. Creí que era un buen método para compartir con los visitantes de este blog. Espero sus comentarios.