About e-books and libraries

31 August, 13:35, by zehzinho Tags: , ,

This week I read some articles about declutering and I noticed how many books I have in my room. The fact is that I’m probably never going to read them again. What should I do with them? Some of them are old, from the time I was a freshman at the university. Nobody wants to read them anymore! What do I do with all this paper?

I was thinking about e-books and how they will help us to preserve the nature and space in our houses. And then I started to think about the future of libraries. How are the libraries of the future going to be? Do they still need to buy piles of books for the students? Then, I remembered that the newest kindle costs only US$ 139. How much do you think similar devices are going to cost in 2-5 years?

How many Kindles do you think can be put in a cabinet? I don’t know, maybe 300? And now comes another fact, kindle books cost on average US$ 10 less than the printed versions. This way, if you buy fourteen books, you already have paid for your Kindle. How many books do you think a library buys per year?

With all this in mind, I envisioned a library in which e-readers are lent instead of books. In this scenario, two things would be possible. In the worst case, students would have access to books via the campus wifi network. In the best case, all books from the library would be contained in the e-reader. Instead of getting one or two books, the whole library would be lent to students! Wouldn’t that be great?

The most amazing fact about all these thoughts I had yesterday is that they are perfectly possible, TODAY, even in a country like Brazil. Even here in my city (which is not that big), they have built a huge library. What if all that money was spent on e-readers and e-books? How much money and energy and trees would be saved?

This is surely the future I want to see coming true.

The First PHPMS Coding DOJO

14 August, 18:49, by zehzinho Tags: , ,

Today the local PHP Users Group (PHPMS) realized its first coding dojo.

It was my second dojo (the first was yesterday :P ) and I think it’s a very interesting thing you should consider to do to improve your coding, communication skills and SPECIALLY your patience! It’s a great opportunity to meet new people and solve problems the RIGHT way.

Today, the goals were very modest and we decided to solve a very simple problem, the Google Codejam’s Old Magician Problem.

You can see all the pictures I’ve taken during the event here.

UI Fundamentals for Programmers by Ryan Singer

07 August, 23:52, by zehzinho Tags:

Hi, I recently watched this presentation by Ryan Singer. I’m not a designer and I think the presentation was quite concise and straight-to-the-point. Really worth watching :)

Ryan works for 37signals and I think it’s quite enough for his resumé, right?

Digg Technical Talks – Rasmus Lerdorf

04 August, 12:31, by zehzinho Tags: ,

Hi, did you know that Rasmus, the creator of PHP, has recently given a talk at the Digg office on PHP performance optimization?

Very interesting, specially because he shows us which tools he uses to measure the performance of websites. The presentation is inspiring. It motivated me to learn more about the solutions I use and try to really understand what happens under the hood. Rasmus has proven that that is the only way to get good optimization results.

The presentation also made me think about some things regarding the CakePHP framework, specially their concern on making the new versions of the framework backwards compatible with older versions of PHP and not using the PHP 5.3 features. I searched the web for some more “aggressive” frameworks and I really liked the Recess Framework. It’s sad to see that its development is stalled =/

The Road to Success

03 August, 14:10, by zehzinho Tags: ,

I’ve just found a very nice illustration of “The Road to Success”.

The Road to Success

I really like the representations of “weak morals” and “lack o preparation” :P

[Cake on Steroids] Write-once Autocomplete Search

31 July, 19:34, by zehzinho

Hi. Tired of having to write code for searches, usually autocompletes, over and over again? If you expect JSON as the outcome of your searches, like the JQuery UI’s Autocomplete does, you may find this post interesting.

In my projects, I add the following function to my AppController to provide a fast search action to all my controllers:

function search() {
     $this->disableCache();
 
     $items = array();
     $fields = explode(',', $this -> params['named']['fields']);
     $model = $this -> modelClass;
 
     $conditions = array();
 
     if (isset($this -> params['named']['conditions'])) {
       $conds = explode(',', $this -> params['named']['conditions']);
 
       for($i = 0; $i < count($conds); $i += 2) {
         $conditions[] = array("$model.{$conds[$i]}" => $conds[$i+1]);
       }
     }
 
     $get = array();
 
     if (isset($this -> params['named']['get'])) {
      $get = explode(',', $this -> params['named']['get']);
     }
 
     if(isset($this -> params['url']['term']))
      {
        $id = (string) strtolower($this -> params['url']['term']);
 
        $selector = "%$id%";
 
        if (count($fields) == 1) {
          $conditions[] = array("LOWER($model." . $fields[0] . ') LIKE' => $selector);
        }
        else {
          $or = array();
 
          foreach($fields as $f) {
            $or[] = array("LOWER($model.$f) LIKE" => $selector);
          }
 
          $conditions[] = array('OR' => $or);
        }
 
        $args = array('conditions' => $conditions);
 
        if (count($get) > 0) {
          // the id must come automatically
          $get[] = "$model.id";
          $args['fields'] = $get;
        }
 
        $this -> {$model} -> recursive = 0;
        $items = $this -> {$model} -> find('all', $args);
      }
 
      $this -> set('items', $items);
 
      $this -> autorender = false;
      $this->viewPath = '/elements';
      $this -> render('search', 'json');
  }

(The original code has been updated. Thanks to: dogmatic69 and Cauan Cabral)

Besides the search action. You also have to have a json.ctp file in your view/layouts dir with the following content:

<?php
echo $content_for_layout;
?>

Now you’re ready to have it working. All you have to do to finally “enable” the feature is to place the view (search.ctp) in your views/elements dir:

<?php
echo  $javascript -> object($items);
?>

Using the search

Currently, the search function accepts the following three named parameters:

  • fields: the (comma separated) fields which we are going to compare against the term parameter.
  • conditions: (pairs of comma separated) conditions for the search
  • get: which (comma separated) fields we want to receive from the search (the result)

Now suppose you have a Post model in your application. If we want to:

  1. search for posts with “php” (term parameter) in the title or in it’s description (fields)
  2. the posts must be published already and the author has the user id (author_id field) equals 4.
  3. we want to retrieve only the title and tags fields

To make the previous search, we can now use the following URL to receive our JSON result:


http://example.com/posts

/search/fields:title,description
/conditions:published,1,author_id=4
/get:title,tags
/?term=php

I think you got it, right? As always, I’m waiting for your comments. See ya.

[Cake on Steroids] PHP + JS

16 July, 18:29, by zehzinho Tags: , ,

Hi, today I’m starting a series of posts with tips on how to improve your CakePHP productivity even more. By productivity I mean: doing things faster and/or in a more organized way. I’m calling it “Cake on Steroids”. As I searched the web and could not find anything like this, I think it’s ok to use this name, right? Enough said, let’s start.

Well, one thing that really annoyed me since the first time I used CakePHP was the way Javascript is handled per default by the framework. It’s not hard to find views with stuff like this:

$javascript->codeBlock(
  'window.addEvent("domready", function(){alert("hi there);});',
  array("inline" => true) );

The two main problems of writing JS code this way are:

  1. No editor can provide javascript syntax highlighting in PHP strings, right? This is a nightmare.
  2. Javascript mixed with PHP and HTML code.

We all know that the second reason can easily be solved in CakePHP, since the framework, obviously, allows us to use JS files. But there are some situations in which it would be nice to be able to use some PHP code within the Javascript code. For example, sometimes we use URLs in the javascript code (in an autocomplete function, for example) and the url() function from the Html helper is nice.

Another strong reason to use PHP + JS is to maintain consistency between elements in the view and the Javascript. What kind of elements? Images and, even more importantly for those who need it, translations. We just don’t want to have to translate things twice (one using cake and another using JS), right? Even if we could use the same translation file for PHP and JS, it would be nice to have elements attached to only one keyword, so we reduce the chances of making mistakes (eg. changing the keyword only in the PHP or only in the JS).

Well, as I said, all this annoyed me. And I think most people can figure out more scenarios in which it would be nice to have PHP + JS in their environments. So, the good news are that it is perfectly possible to do it in CakePHP.

I have found some articles which teach how to do it. Oh, I forgot to say. I’m using this solution for quite some time and I’ve been postponing this post for months and now I just couldn’t find my original sources. If I find them, I’ll update the post, ok?

So, how do we do it?

The first step is to tell cake to parse the js extension. You can do it by editing app/config/routes.php and adding the following statement:

Router::parseExtensions('js');

The second step is to add a default layout for JS. You can do it by creating and editing the file app/views/layouts/js/gen.ctp:

<?php
 
header("content-type: application/x-javascript");
 
echo $content_for_layout;
 
$this->data = null;
Configure::write('debug', 0);
?>

The third and last step is to create an action in a controller which will be responsible for loading our JS file. I like to add this action to my AppController, so I don’t have to write it in all my controllers. Edit you AppController and add the following function:

 
 public function formjs($id) {
    if ($this->params['url']['ext'] != 'js') {
        exit;
    }
 
    $this->layout = 'gen';
    $this->ext = '.js';
 
    $this->set("cacheDuration", '1 hour');
  }

Adding this function to my AppController allows me to add the following lines to my default layout (usually app/views/layouts/default.ctp):

$autoloadFormJs = APP . 'views' . DS . this->params["controller"] . DS . "js" . DS . "formjs.js";
 
$urlAction = $this -> params['action'];
 
if (($urlAction == 'add' || $urlAction == 'edit') && is_file($autoloadFormJs)) {
      $jsPath = '/' . $this->params["controller"] . '/formjs/1';
      echo $javascript->link(array($jsPath));
}

and voilá. All you have to do is create a js/formjs.js file inside the view folder of your component and it will be inserted automatically. For example, if you have a component called bodies, and you want some javascript to be automatically loaded for the add and edit actions, all you have to do is create the file views/bodies/js/formjs.js and the code above will insert the file automatically in the page.

Of course, I’m just trying to speed up your development process ;) But you can be more conservative and place the formjs function only in the bodies controller. Or you can load the javascript only in the add.ctp view of the bodies component. To do it, you would have to place following line in your views/bodies/add.ctp file:

echo $javascript -> link(array('/bodies/formjs/1'));

A positive side-effect of this approach is that you can pass the id argument in the javascript URL. In the examples above, all links to javascript files use the id = 1. But you can use different values for the id and the javascript file will be loaded the same way. This is actually a feature of this approach, since you can use aggressive caching policies for your javascript files and change the id whenever the file is modified, assuring consistency.

Now our javascript files are being loaded by the CakePHP framework and we can use PHP inside of them in anyway we want.

I usually write the PHP code inside javascript comments, so the editor does not give me syntax errors. For example:

/*<?php
$usersAutocompleteUrl = $html->url(array('controller' => 'users', 'action' => 'autocomplete'));
*/
 
$(function() {
  // using the previously defined PHP variable
  $('#userSearchField').autocomplete('<?= $usersAutocompleteUrl ?>', {
    // lots of JS code
  });
});

Finally, I created a helper called PhpInJS to help me define variables in the PHP view which can be used in a JS file. Place the following code in the views/helpers/php_in_js.php file:

class PhpInJsHelper extends AppHelper {
  function set($name, $value) {
    if (!empty($this->params['controller'])) {
      $controller = $this->params['controller'];
      $_SESSION['PhpInJs'][$controller][$name] = $value;
      return $value;
    }
 
    return null;
  }
 
  function get($name) {
    if (isset($_SESSION['PhpInJs'][$this->params['controller']][$name])) {
      return $_SESSION['PhpInJs'][$this->params['controller']][$name];
    }
  }
}

You can use this helper in the view file (eg. add.ctp) to set a variable:

$eraseImage = $phpInJs -> set('eraseImage', $html -> image('erase.png'));
 
// use the $eraseImage var in the PHP file

and use the the same value in the JS file:

/*<?php
$eraseImage = $phpInJs -> get('eraseImage');
?>*/

Well, I think it’s enough. You can/should always use the comments to help me improve/fix the solution, ok? See ya.

Welcome to the new version of my blog

07 July, 15:07, by zehzinho Tags:

Hi, after some experiences with wordpress and drupal, I decided to switch back to WordPress. I hope you all enjoy this new version. I’m planning to use this new version of the blog to expose more of my technical discoveries, specially regarding web development.

Despite the fact that I’m Brazilian, the default version of the blog is the English one, because I want to keep myself practicing the few English words I know. Of course, sometimes there will be posts that will concern only Brazilian people, and I will post only the Portuguese version.

Well. I think it’s enough for ANOTHER welcome post. See ya.

Before your next meeting, just think about it

05 July, 15:15, by zehzinho Tags:

“When you think about it, the true cost of meetings
is staggering. Let’s say you’re going to schedule a meet-
ing that lasts one hour, and you invite ten people to at-
tend.
That’s actually a ten-hour meeting, not a one-hour
meeting. You’re trading ten hours of productivity for
one hour of meeting time. And it’s probably more like
fifteen hours, because there are mental switching costs
that come with stopping what you’re doing, going
somewhere else to meet, and then resuming what you
were doing beforehand.”

Jason Fried & David Hansson, Rework

Multiple sessions for different instances of Cakephp in the same domain

26 May, 15:13, by zehzinho Tags: ,

Did you know that if you run multiple instances of the same application in Cakephp in the same domain, they will share the same Session? For example, suppose you have instances running at:

www.example.com/instance1 and www.example.com/instance2

If you login in the first instance and access instance2, you’ll see that you will already be logged in. This happens because Cakephp, per default, uses the PHP Session storage mechanism.

If this is not the behaviour you expect, Cakephp allows you to choose from three options for the Session handling method: php (default), cake and database. The current method is stored in the Session.save variable in app/config/core.php.

Changing the method from php to cake will make Cakephp store the Session variables in the app/tmp/sessions directory. If you do it, remember to create and give the appropriate permissions to this directory.

Voilá, that’s all you need to do have separate Sessions for each of your Cakephp instances.