cook
  • Home
     
  • About Me
     

OpenX and HostGator shared hosting

Jimmy Bourassa | March 16, 2009

This post is totally unrelated to CakePHP, but oh well!

As you might have noticed, OpenX does not work on HostGator’s default shared hosting. Every ad you post on your website through OpenX will be viewable, but clicking the ad will lead to a 403 forbidden page.

It has something to do with HostGator Apache’s default configuration on shared hosting. Globally, it is because of some configuration of mod_security, but I don’t know what it is exactly. I found out that you can’t turn off mod_security within the .htaccess. Thanksfully, the tech team will fix you up through the live support within minutes.

Comments
No Comments »
Comments rss Comments rss

Common mistakes when working with accentuated characters

Jimmy Bourassa | March 2, 2009

Working with accentuated characters in CakePHP can definitely be a pain if you’re unfamiliar with a few basic guidelines.

All your files must be encoded in UTF-8

Make sure all your files containing accentuated characters are encoded in UTF-8 (no BOM or it’ll screw everything up!). If your file does not have the correct encoding, any string that contains an accentuated character will just be considered as empty, which can be frustrating to debug.

Database connection must use UTF-8 encoding

This will prevent elements from the database to be considered as empty.

//In /app/config/database.php
class DATABASE_CONFIG {
	var $default = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'some_host',
		'login' => 'some_user',
		'password' => 'some_ow',
		'database' => 'some_db',
		'prefix' => '',
		'encoding'=>'utf8'
	);
}

Set App.Encoding to UTF-8 in core.php

Actually, I’m not sure why we’re doing this, but I figured it couldn’t hurt. Everytime I start a project I make sure my App.Encoding is set to UTF-8 in core.php.

Configure::write('App.encoding', 'UTF-8');

Make sure to define the charset in your html files

Definitely not as hard to debug as the other, but remember to define the charset in your layout.

echo $html->charset();

Hope it helps!

Comments
6 Comments »
Comments rss Comments rss

Model “X” with multiple associations leading to Model “Y”

Jimmy Bourassa | February 23, 2009

This seems like a fairly common case, but it might not be obvious for everyone. While the title is not totally clear, let’s use an exemple to show where the problem lies.

Let’s say we have a Message model, which has the following fields : id, sender, receiver, created, title, text. We’d like our sender and receiver field to link with our User model, so from and to will contain a user id. If we were to follow CakePHP’s naming convention, we’d have two user_id fields, which is not going to work for obvious reasons. So this is where we have to break CakePHP’s naming convention, which can lead to some confusion. Fear not, the solution is quite simple!

In order for this case to work, all we have to do is change the key in our association :

<?php
class Message extends AppModel {
 
	var $name = 'Message';
	var $belongsTo = array(
		//In most case, this would be User instead of Sender
		'Sender' => array('className' => 'User',
				'foreignKey' => 'sender_id'
 
		),
		//Same goes for Receiver
		'Receiver' => array('className' => 'User',
				'foreignKey' => 'receiver_id'
		),
	);
}
?>

Once the key is changed, data returned from a find on the Message model will be broke down with these keys we just set.

Comments
3 Comments »
Comments rss Comments rss

Sort search results by relevance

Jimmy Bourassa | December 24, 2008

When creating a search function for your website, it is fairly important to sort results by relevance. I had to do this last week, so I might as well share how I did it.

I wanted to search the News model with simple keywords. Here’s my News table :

CREATE TABLE `news` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `slug` varchar(100) NOT NULL,
  `created` datetime NOT NULL,
  `published` tinyint(1) NOT NULL,
  `title` varchar(150) NOT NULL,
  `description` varchar(255) NOT NULL,
  `text` text,
  PRIMARY KEY  (`id`),
  KEY `slug` (`slug`)
);

In order to keep beautiful URLs, I made a simple function in NewsController that redirects to the search function using the data submitted in post. The format is param:value/param2:value …

function searchToUrl(){
	foreach($this->data['News'] as $paramKey=>$paramValue){
			if ($paramValue!=null && $paramValue!='0')
				$redirectStr .= $paramKey.':'.urlencode($paramValue).'/';
	}
	$this->redirect(array('action'=>'search', $redirectStr));
}

The search function I wrote checks for every keyword submitted and awards points when the keyword is found. Every word is worth 3 points when found in the title, 1 point when found in the main text. 4 points is also awarded for the exact match in the text and 10 points for the exact match in the title. The search function I wrote does more than just keyword search, but that’s not the point of this post, so we’ll skip it for now (if you’d like to see it all, ask away and I’ll write something about it).

//Part of the search() function in the NewsController
$conds = array();
$this->paginate = array(
	'News'=>
		array(
		'recursive'=> 1,
		'limit'=>15,
		'fields'=> array('DISTINCT id', 'slug', 'title_fr','classification',
    				 'text_fr', 'Reference.name', 'datepublished')
    		),
	'Country'=>
		array(
		'recurisve'=>-1,
		'fields'=>array('id', 'name_fr'))
    );
 
if(isset($this->params['named']['keywords'])){
	//Replaces ' by '', to avoid breaking the SQL queries
    $this->params['named']['keywords'] = str_replace("'", "''", $this->params['named']['keywords']);
    //Split de keywords in an array
    $keywords = preg_split('/[\s,]+/',$this->params['named']['keywords'],-1,PREG_SPLIT_NO_EMPTY);
    $condsKw = null;
    //Relevance Order is a pseudo col in the SQL queries that is going to be used for order.
    $relOrd = '';
    foreach($keywords as $keyword){
       //Title
    	$condsKw[]= "title LIKE '%$keyword%' ";
    	//Each keyword in title is worth 3 points.
    	$relOrd .= "+ (CASE WHEN title LIKE '%$keyword%'  THEN 3 ELSE 0  END) ";
 
       //Text
    	$condsKw[]= "text LIKE '%$keyword%' ";
    	//Each keyword in text is worth 1 points.
    	$relOrd .= "+ (CASE WHEN text LIKE '%$keyword%'  THEN 1 ELSE 0  END) ";
    }
    //Must be at least 3 words and 7 chars to receive points for exact string match
    //This can obviously be tailored to fit your needs.
    if(count($keywords) -> 2 && strlen($this->params['named']['keywords']) -> 6 ){
    	//10 points if the exact match is found in the title
    	$relOrd .= "+ (CASE WHEN title LIKE '%".$this->params['named']['keywords']."%'  THEN 10 ELSE 0  END) ";
 
    	//4 points if the exact match is found in the text
    	$relOrd .= "+ (CASE WHEN text LIKE '%".$this->params['named']['keywords']."%'  THEN 4 ELSE 0  END) ";
    }
    //Formats then adds the pseudo column to the field list.
    $relOrd = '(' . substr($relOrd, 1) . ') AS Relevance';
    $this->paginate['News']['fields'][] = $relOrd;
    $conds['AND'][] = join(' OR ',$condsKw);
 
    //Sets the order if no other order is defined in the params.
    if(!isset($this->params['named']['sort'])){
    	$this->paginate['News']['order'] = array('Relevance'=>'DESC');
    }
    //Sets keywords for use in the view, this can be used to highlight the keywords in the search results
    $this->set('kwArr', $keywords);
 
	//Preserves the data in the html form.
	$this->data['News'] = $this->params['named'];
 
	$this->set('news', $this->paginate('News', $conds));

I think everything else should be fairly straightforward (the view etc.) If not, ask away in a comment!

Comments
No Comments »
Comments rss Comments rss

Redirecting to the proper page after actions

Jimmy Bourassa | November 29, 2008

A couple days ago, a client I currently work for found a little annoyance with cakePHP default’s behaviour of redirecting to the index action after a delete or edit action, thus ignoring the page you were on.

Indeed, redirecting to $this->referer wouldn’t work in this case because the data is posted to the same action, therefore $this->referer = $this->here. The solution is quite simple, add this code to your action:

if ($this->referer != $this->here)
	$this->Session->write('referer', $this->referer);

Then, if your save method is successful, you can safely redirect with the Session variable that’s just been set :

$this->redirect($this->Session->read('referer'));

It’s pretty simple, but I guess it might come in handy. Thanks to TommyO from the irc channel for this hint!

Comments
1 Comment »
Comments rss Comments rss

Recent Posts

  • OpenX and HostGator shared hosting
  • Common mistakes when working with accentuated characters
  • Model “X” with multiple associations leading to Model “Y”
  • Sort search results by relevance
  • Redirecting to the proper page after actions

People I like

  • Jean-Philippe Doyle
  • Knowland Design
rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox