Category Archives: PHP

Autocompleter plugin v 1.2

Autocompleter Plugin 1.2Hey guys,

today I’ve released a new version of the WordPress Plug-in “Autocompleter”.

What is the change?

The new version contains ability to display number of matches per word or phrase in the drop-down. The example is available in this blog (top/left search field). Of course in order to activate this you should go to Admin under the Settings section, where there is an option “Autocompleter” πŸ™‚

Bear in mind that ‘number of matches’ are not the posts in the blog, but number of times where the tag or category is used. I would provide small example of this.

Let’s imagine that in your blog you have 3 posts all tagged with WordPress and one of them is in the WordPress category, while other 2 are in another category.

The result in matches for wordpress would be 4, because there are 3 tags attached to the posts and 1 of the posts is attached to the wordpress category. Hope this make sense to you.

There is also ability to change the word ‘matches’ with your own, or even word in your language.

If you want to play with position of the matches, you could change autocompleter.css from the plug-in directory.

That’s it. I hope you like this plug-in.

Strange issue with captcha field

Captcha caseWell, it’s more an observation than a real problem.

For my current CakePHP project I had to set a captcha field to a user registration form. I decided to be “creative” and I set the captcha image as background of the input field. In fact the graphical representation wasn’t bad at all. Unfortunately when it’s used, the captcha word shows wrong image and of course the result was wrong. To be correct the first attempt was always ok, but the second one (let’s say if the user decided to register again) the captcha was always wrong.

I checked everything especially after the image in Javascript library case and I couldn’t find anything suspicious.

The solution came when I removed the image from the background of the field and call it with an <img> tag. This time everything went just fine. This make me think that it’s a cache problem. I didn’t dig it deeply, because for now it’s working and as you can see it’s looking better.

So, an advise from me – never put your captcha image as background of your field, or call through css. Just use good old <img> tag instead.

Autoload your javascript and css in CakePHP

Have you ever wanted to have all your css or javascripts files loaded automatically once they are on place under /webroot/js and webroot/css folders? Well this is the solution.

What is all about

I’ve build a quick helper which will include all files under the js/ and css/ directories. So once the javascripts and css are there, they will be loaded automatically.

How to use it?

Using it is really easy. It’s like a normal helper:
1. add the file autoload.php under your /app/views/helpers
2. add it in the $helpers var in the controller
3. add the following snippet in your layout file. It should be under /app/views/layouts:

<?php echo $autoload->javascript();?>

This will include all files under /webroot/js

<?php echo $autoload->css();?>

This will include all files under /webroot/css

<?php echo $autoload->all();?>

This will include all files under /webroot/js and /webroot/css

Key features:

1. The helper includes all files recursively.
2. The helper includes also files under /root/vendors/js and /root/app/vendors/js too (same apply to css). Vendors are loaded first. (Thanks to suggestion from Juan Basso)
3. The order of the files in one directory is based on the name, so now you can control the order as well. (Thanks to suggestion from Juan Basso)
4. Files starting with . (dot) are not included, files under directories starting with . are not included as well, so you can exclude some files
5. if you want to load some files after other use directories. For example if you want to include plugins after the main lib (jQuery), place them in plugins directory like:
js/plugins/plugin_one.js
js/plugins/plugin_another.js
js/.hidden/plugin_third.js
js/jquery.js
the result will be:

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/plugins/plugin_one.js"></script>
<script type="text/javascript" src="js/plugins/plugin_another.js"></script>

(same apply to css as well)

Warning: I’ve noticed that this helper doesn’t work properly with scriptaculous, because the script tries to load the additional plugins and they fail, but for jQuery there is not a problem at all.

Finally here is the code of the helper:
Continue reading

Careful with JavaScript includes

Ok, this is not a code snippet article. It’s just an experience which you probably already met, but it was nightmare to find and it took me 1/2 a day to fix this “stupid” bug.

So what is the case?

Working on a project including some advanced JavaScript and Ajax techniques my coworker Milen noticed that the Session is not behaving as expected. In a simple function like:

 function test($id = false){
  if ($id != false) {
    echo $id;
    echo $k = $this->Session->read('some_var');
    $this->Session->write('some_var', $id);
  }
  $this->set('tests', $this->paginate());
 }

The result should be quite easy to be predicted: if you pass for example 5 on the second reload the $k should be with the same value as $id. Unfortunately instead of 5 the $k was ‘images’. Yep, quite strange, isn’t it?

if you put die() at the end of the function, the result is as expected.

What was the problem

In our current project we are using jQuery and some of it’s plugins. So the problems was in the ThickBox plugin. If you remove it from the header everything works.

Digging into unpacked version of the plugin we’ve noticed that the loading picture is not where it should be. there is an variable

 var tb_pathToImage = "images/loadingAnimation.gif"

and as you may notice the path is not compatible with Cake convention and obviously it’s not in the http://server/cakeapp/tests/test/images/.

In the example above we were writing id into the session. Yes but calling: http://server/cakeapp/tests/test/images/loadingAnimation.gif mean that $id take value of ‘images’.

It was quite tricky, because if you loading CSS or JavaScript and the file is not there, FireBug or even the html /if there is no correct CSS the styling will fail/ will warn the developer, but image loaded into the JS function is quite difficult to find.

Anyway, the conclusion is “Watch you JavaScript libs and what files they require”.

Translating plural and singular forms in CakePHP

I don’t know how good you know the *.po translation file syntax, but for me it was a text file with “msgid” and “msgstr”, where msgid is the string, which could be found in a code of the app, wrapped with __() function and msgstr is the string which is the translation.

Following this convention in all of my projects I had not problems till now. But on this one I’ve noticed that the translation is not quite accurate especially when translating time. I am speaking about usage of timeAgoInWords() function from the TimeHelper.

I noticed that when there is a translation file for the specific language singular and plural words are not translated properly, I had results like “3 hour and 34 minute” instead of “3 hours and 34 minutes”.

I thought that I’ve found a bug, and I submitted a ticket in the trac, but I was wrong, because syntax of the PO files is a little bit extended than my understanding. πŸ™‚

99% of the cases the standard approach could fit just fine, but when it’s used __n() function which is described as:

Returns correct plural form of message identified by $singular and $plural for count $count.

the translation file needed a specific syntax. Here is the example of it:

msgid "hour"
msgid_plural "hours"
msgstr[0] "hour"
msgstr[1] "hours"

As you can see instead of msgid<->msgstr pair, there is also msgid_plural and array of msgstr which holding the translations of singular and plural values. Note that in some languages plural could have 2 or more forms. In these cases the syntax will be (Czech):

msgid "%1 second"
msgid_plural "%1 seconds"
msgstr[0] "%1 sekunda"
msgstr[1] "%1 sekundy"
msgstr[2] "%1 sekund"

It’s good to set the plural forms definition in the project settings which are in the beggining of the file. This is very handy when you use PoEdit or similar translation tools, because if is your setting is correct, these tools will provide for each plural form separate tab.

The syntax of plural form definition is like:

"Plural-Forms: nplurals=1; plural=0;\n"

It hold 2 parameters the first one holding the number of plural forms in the specific language and the second one is an expression how to determine the plurals. If you don’t know how to set this correct for a specific language, check this good document of all available languages. πŸ™‚

More information about the PO syntax I founded in that article. I’ve noticed in that the article there are shortcuts, which are not useful for me so far, but you never knows, in the future they could be handy.

Regarding to that I am wondering is there a POT file for the core lib translations which could be a big helper to anyone who need to translate the whole framework.

Blast from the past

Hey guys,

last week I’ve worked on a project which I finished somewhere in spring of 2007 and I decided to share my experience with this post. I don’t know did you had such experience, but for me it was interesting, because working on old code is always challenge.

Basically, the project was really small one, which uses 80% of scaffolding, so really nothing complicated. Now the client wanted some extensions to the core functionality /like adding few more look-up tables and some basic reports/ and because I was the only one developer who worked on it, they ask me to do this and I agreed.

My first thought was to upgrade the core CakePHP lib to the last version, but after thinking I decided not to, because if something goes wrong /like some deprecated functions/, I need to do more work in debugging rather than focusing on the real tasks.

What I noticed while I coded?

The major one – Improvement of the console script. In the past it was in the /cake/scripts/. In the folder there were acl.php, bake.php and bake2.php, extract.php for label extraction and master bake which I never used. Now, the console script is more advanced and provide more functions. Still I am not big expert on it and I still using it for basic operations :).

Fully translated labels – it’s related to the previous one – when the code was generated with old bake script, some of the labels weren’t wrapped with __() function and especially for me it was biggest pain. Someone could tell me that there was ability to modify the templates, but I personally never did it.

The truth is that CakePHP in fact is improved a lot since then. Hopefully it will continue in this direction in the future as well.

Anyway, it was really interesting experience for me.

Working with nested data and find method with breadcrumbs in CakePHP

Do you working with tree data in your projects?

Well, in CakePHP there is a Tree behavior which will help you to handle such structures. Let me show you how to use it in your projects. Hierarchical data structures are very well described here by Mike Hillyer and I would suggest you to take a look before you continue reading.

Let’s say we have following data structure:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `parent_id` INT(10) DEFAULT NULL,
  `name` VARCHAR(255) DEFAULT NULL,
  `lft` INT(10) DEFAULT NULL,
  `rght` INT(10) DEFAULT NULL,
  PRIMARY KEY  (`id`)
)

Note, that in that table there are 3 special fields: parent_id, lft and rght.

The first one is very familiar to everyone who understanding the tree structures. The other 2 are to handle the MPTT logic (see the article mentioned above). The beautiful part of using Tree behavior is that you don’t need to worry about these 2 extra columns. The behavior will fill them automatically. πŸ™‚

So, continue with the example. Attach the Tree behavior to your Model:

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');
}
?>

That’s it. Now when you save (insert or update) your data into the table, the fields lft and rght will be automatically populated with the correct values. Of course your task is to have proper value set in parent_id πŸ™‚

Why this is so important?
As you already know /if you read the article for MPTT/ using lft and rght values will give possibility to get very easy nested data in various ways.
In Model::find function there is already threaded option, but what about having breadcrumbs?

Here is a way to extend the Model::find function with this functionality. /inspired by Daniel Hofstetter’s post/

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');

    public function find($type, $options = array()) {
        switch ($type) {
            case 'breadcrumbs':
                if(!isset($options['fields']))
                    $options['fields'] = null;
                if(!isset($options['recursive']))
                    $options['recursive'] = null;
                if(is_object($this->Behaviors->Tree) && $options['id']){
                    return $this->Behaviors->Tree->getpath($this, $options['id'], $options['fields'], $options['recursive']);
                } else {
                    return null;
                }
                break;
            default:
                return parent::find($type, $options);
        }
    }
}
?>

As you can see I am using the function TreeBehavior::getpath. There are a lot of handy functions in this behavior, but for breadcrumbs example this is just enough.

How to use it?

$this->Category->find('breadcrumbs', array('id'=>1));

so if you have data like this:

1 Root
2     Cat1
3         Cat1.1
4     Cat2

and use the function mentioned above with id=3 the result will be:

Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 1
                    [parent_id] =>
                    [name] => Root
                    [lft] => 1
                    [rght] => 8
                )
        )

    [1] => Array
        (
            [Category] => Array
                (
                    [id] => 2
                    [parent_id] => 1
                    [name] => Cat1
                    [lft] => 2
                    [rght] => 5
                )
        )

    [2] => Array
        (
            [Category] => Array
                (
                    [id] => 3
                    [parent_id] => 2
                    [name] => Cat1.1
                    [lft] => 3
                    [rght] => 4
                )
         )
)

After this with

$breadcrumbs = Set::extract('/Category/name', $result);
echo ' / '.implode(' / ', $breadcrumbs);

you will have the following result

/ Root / Cat1 / Cat1.1

I am leaving to you the styling of it as well as adding the links to the parent nodes.

Building cake application (Part VI)

Saturday (Day 6)

Problem with validation messages while translating
Although my native language is Bulgarian and the requirement from the client was to have this site only in Bulgarian, I’ve preferred to have it in English and to make the translation with the i18n functions of CakePHP. There are 2 reasons to do this:

1. This will give me the possibility to show you the result of all these days of coding and
2. I can reuse some part of the codes the same as I’ve used in this project

So, up to my experience having application in English is never a bad idea. πŸ™‚

You know, that the translating process is not very exciting process, but someone need to do it and because there is no one who can help me with this I’ve start the translation. Anyway. πŸ™

While translating I noticed that the most of the validation messages are not appear of the translation file. I knew this from my past experience, but I needed to find an easy and elegant solution to translate these messages instead of putting them in all views. Putting in the view you need to do this at least 2 times.
Continue reading

Building cake application (Part V)

Friday (day 5)

Constructing SQL statement for the search
Yep, today I need to finish the Profile search for the admin part. As I mentioned, the search is only by fields of experience, so there is no big and scary where clause /especially if you want to cover all cases, like splitting the words with AND, OR etc. will cause huge where with all possible combinations/.

There are 2 specific requirements here: The results need to be ordered by relevance and the report need to show fields of competence which are match to the search criteria next to each row /user/.

What does it means? Let’s say there are 2 users. First one has following skills like Java, PHP, MySQL, HTML and JavaScript, the second one knew only JavaScript and HTML, so when we search for users matching criterion PHP and HTML, the search results need to be ordered like this:

User1 – matching fields: PHP, HTML – relevance 2 criteria matched
User2 – matching fields: HTML – relevance: 1 criteria matched
and so on.

At first glance it look like I had to build huge SQL including few sub queries or functions for fetching the fields of relevance and matching fields and I was prepared for at least one day to accomplish this task, but in fact it was very fast.
Continue reading

Building cake application (Part IV)

Thursday (day 4)

Today I need to go downtown again. I am quite unhappy, because this mean that I need to work extra later on, but there are priorities, as you probably know. Here is what I’ve done today.

Working on the administration part
Today, I’ve worked on the administration part. There are some small bugs and glitches which I needed to clear in the Key look-up tables such as, stripping down the Categories functionality – this application requires only 2 levels of nesting in the Fields of experience, so allowing the extra levels will confuse the customers.

fixing some bugs in the front end as well
I’ve still have troubles with the redirects in the Auth component. I know it’s all my fault but it’s really annoying. I need to check what exactly is the problem with this. πŸ™

Adding delete all related records to the external user’s profile
Back to the admin part. I needed to implement delete all related records interface – if an admin user decide to remove an External user profile – let’s say someone try to test the application, or just an appropriate user /spammer/ this action should delete all relative records to that profile.

The problem was that I thought that key node is ‘dependent’ while the right one is ‘exclusive’. So, it’s set to true in the hasMany, hasOne etc. and if the parent record is deleted all records in the child tables are deleted too.
Continue reading