logo

Alphabetical Pagination / Sort by in CakePHP

logo

CakePHP has some great pagination functions built in – however these are normally categorised with “sortby” and “Number per page”.

I found on another blog this code (http://foldifoldi.com/news/?p=169):

function index($filter = null) {
	$this->SttwTrack->recursive = 0;
 
	$this->set('filter', $filter);
 
     // query all distinct first letters used in names
     $letters = $this->SttwTrack->query('SELECT DISTINCT SUBSTRING(`title`, 1, 1) FROM `sttw_tracks` ORDER BY `title`');
 
     $links = array();
     // push all letters into a non-nested array
     foreach ($letters as $row) {
          array_push($links, current($row[0]));
     }
 
     $this->set('links', $links);
 
     $this->paginate['SttwTrack'] = array(
     'limit' => 10,
     'order' => array(
          'SttwTrack.title' => 'asc'
      )
	);
 
	$data = $this->paginate('SttwTrack',
	     array(
	          'SttwTrack.title LIKE' => $filter .'%'
	     )
	);
 
	$this->set('data', $data);
	$this->set('filter', $filter);
	$this->set('sttwTracks', $this->paginate());
}

The code above basically creates a custom query to find the first letter of each title from the SttwTrack model, it then adds each of these into an array to be passed to the view.

in your view the following code should display the Alphabet list and link any of the letters that have titles in them.

// set url arguements
$paginator->options(array('url' =>  array($filter)));
 
// render the previous link
echo $paginator->prev('prev',null,null,null);
 
// set up your alphabet
$alpha = range('A','Z');
echo "<ul class=\"sortby\">";
for ($i=0; $i < count($alpha); $i++) {
	echo "<li>";
	// if current letter is not in the links array, do not make it clickable
	if(!in_array($alpha[$i], $links)) {
		echo"<span class='nolink'>" . $alpha[$i] . "</span>";
	} else {
		if ($alpha[$i] == $filter) {
			// if the current letter matches the filter, give it a selected style
			echo $html->link($alpha[$i], array('controller' => strtolower($this->params['controller']), 'action' => 'index', $alpha[$i]), array('class' => 'link_selected')) . "";
		} else {
			echo $html->link($alpha[$i], array('controller' => strtolower($this->params['controller']), 'action' => 'index', $alpha[$i]), array('class'=>'link')) . "";
		}
	}
	echo "</li>";
}
echo "</ul>";
// render the 'next' link
echo $paginator->next('next', null, null, null);

I know its just a snippet but hopefully it should make some sense to you :)

Share with your friends and help out this site:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogosphere News
  • E-mail this story to a friend!
  • Identi.ca
  • LinkedIn
  • Live
  • MisterWong
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
  • Yahoo! Buzz

Pagination Across Models / Associations

logo

For a CakePHP n00b the pagination thing might seem a bit complicated. Well to be frank it is in someways. For instance you can only currently paginate stuff easily when there is a model involved!

For instance here is a pagination with a deep association:

$this->UserProfile->User->Friend->recursive = -1;
		$this->set('userFriends', $this->paginate($this->UserProfile->User->Friend, 
			array('Friend.user_id' => $userid, 'Friend.accepted' => 1)));
 
		$this->set('userFriendsWaiting', $this->paginate($this->UserProfile->User->Friend,
				array('Friend.user_id' => $userid, 'Friend.accepted' => 0, 'Friend.rejected' => 0)));
 
		$this->set('userFriendsRejected', $this->paginate($this->UserProfile->User->Friend,
				array('Friend.user_id' => $userid, 'Friend.accepted' => 0, 'Friend.rejected' => 1)));

in this it is to ensure that you have the paginate var set in your Friend Model – and that each conditions field (the stuff in the array() is prefixed with the table of this model

Hope this clears it up

Share with your friends and help out this site:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogosphere News
  • E-mail this story to a friend!
  • Identi.ca
  • LinkedIn
  • Live
  • MisterWong
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
  • Yahoo! Buzz

Should you stop supporting IE6?

logo

Age old argument isnt it? When should you stop supporting a browser that is outdated? Ok so I know the majority of the time outdated is subjective – but lets face it – Im pretty sure that there isnt one person on the face of this earth that doesnt think think IE6 is outdated.

But what is outdated really? Old? Undersupported? Dwindling numbers?

When working for a web development agency – everything was based on the W3C stats, once a particular metric fell below 10% then it was officially unsupported. I was there to see the fall of 800 x 600 to below 10% and welcomed the chance to be able to build sites at 1000px width (well 960px but thats just getting petty).

So ignoring the W3C stats and looking at our own sites I can see that there is still a shocking large number of people using IE6:

Percentage using various versions of Internet explorer (of a total percentage of 34%)

1. 1,786 52.44%
2. 983 28.86%
3. 635 18.64%
4. 1 0.03%
5. 1 0.03%

As you can see – that is still a large percentage of people (18% of 34%) using IE6 – that on this site equates to about 2000 customers.

2000! If 2000 of these customers could not access the site or use it correctly – regardless of how morally you want stand on this – your client is going to be pissed!

Other sites of ours show pretty much similar numbers – which to be frank scares me somewhat

So what can you do? We by default now put a nag screen on all of our sites saying something along the lines of “The browser you are using is outdated and as such tis site might not display correctly” but we at no time disallow them access to the site. Yes it is a ball ache trying to get the site looking half decent in IE6 – but I know that im not the only developer going through this trouble.

So the answer to the original question is No – you shouldnt. You can try and talk about the demographics of your customer base but take this example above for instance. It is a site selling digital downloads to people who will ALL be interested in music production – that includes having the best most powerful computer, the best equiptment and lets face it the majority of them are likely to be huge computer nerds. Yet there is still that massive percentage of them using IE6. You have to bear in mind that companies often roll out stuff like citrix complete with IE6 or might have a standard desktop that only includes IE6. Either way if you deny these people access then you are going to be losing that number of sales each month.

Dan

Share with your friends and help out this site:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogosphere News
  • E-mail this story to a friend!
  • Identi.ca
  • LinkedIn
  • Live
  • MisterWong
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
  • Yahoo! Buzz

View what variables are being passed to the view

logo

I sometimes think it is useful to see exactly what variables (and values are being passed to the view in cakePHP), especially if the project you are working on is complex with much pseudo repetitive data.

A simple solution to do this is to insert this piece of code in your view:

foreach ($this->getVars() as $name) {
 
	pr($$name);
}
Share with your friends and help out this site:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogosphere News
  • E-mail this story to a friend!
  • Identi.ca
  • LinkedIn
  • Live
  • MisterWong
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
  • Yahoo! Buzz

A CakePHP Friends List not using HABTM

logo

Right,

When I started out on this I hit t’internet looking for any kind of hints as to the best way of going about this. The first thing I came across was the use of a Self Referential HABTM relationship ( User<-HABTM->User ), naturally not being the uber Cake Nerd this really didnt work out too well for me ( although if you want to do it this way it will work if you follow my previous post about redirects after save() ).

So after deciding to scrap the HABTM relationship and move over to a hasMany() / belongsTo() association things became much easier.

I have the following tables:

  • users
  • friends

basically in this friends acts as the “HABTM” join table (basically it is the table we write the associations into – user_id(1) is friends with user_id(2) blah blah blah).

My friends model looks like this:

class Friend extends AppModel {  	 
var $name = 'Friend';   
}

Nice eh?

Ok my user profile has the following(stripped down for conciseness). I use Bake for my code generation as it generally does a much better job at finding associations – just bear in mind that you will need to have good DB design skills and remember to name foreign keys correctly for it to work.

 
class User extends AppModel {
 
	var $name = 'User';
	var $validate = array(
		'username' => array('notempty'),
		'password' => array('notempty'),
		'group_id' => array('numeric'),
		'active' => array('numeric'),
		'email' => array('email'),
 
	var $belongsTo = array(
		'Group' => array(
			'className' => 'Group',
			'foreignKey' => 'group_id',
			'conditions' => '',
			'fields' => '',
			'order' => ''
		)
	);
 
	var $hasMany = array(
		'Friend' => array(
			'className' => 'Friend',
			'foreignKey' => 'user_id',
			'dependent' => false,
			'conditions' => '',
			'fields' => '',
			'order' => '',
			'limit' => '',
			'offset' => '',
			'exclusive' => '',
			'finderQuery' => '',
			'counterQuery' => ''
		)
	);
 
	var $hasAndBelongsToMany = array(
		'Group' => array(
			'className' => 'Group',
			'joinTable' => 'groups_users',
			'foreignKey' => 'user_id',
			'associationForeignKey' => 'group_id',
			'unique' => true,
			'conditions' => '',
			'fields' => '',
			'order' => '',
			'limit' => '',
			'offset' => '',
			'finderQuery' => '',
			'deleteQuery' => '',
			'insertQuery' => ''
		)
	);
 
}

And basically that is it. You will need a piece of code in your controller (or model I guess) that actually adds the friend (ask and you shall receive:)

function addfriend($user_id, $friend_id) {
    	//$user_id = $this->Session->read('User'); //when logged in disabled for testing
        $this->data['Friend']['user_id'] = $user_id;
        $this->data['Friend']['friend_id'] = $friend_id;
        $this->data['Friend']['accepted'] = 0;
        $this->data['Friend']['rejected'] = 0;
        //print_r($this->data);
        $this->User->Friend->Create();
        $count = $this->User->Friend->find('count', 
        		array('conditions' => 
        				array(	'user_id' => $user_id, 
        						'friend_id' => $friend_id)));
        if( $count < 1) {
	        if($this->User->Friend->save($this->data)){
	                $this->Session->setFlash('Friend Added');
	                $this->redirect('/user_profiles/view/'.$this->User->UserProfile->profileID($user_id));
	                exit;
	        } else {
	                $this->Session->setFlash('Error Adding Friend');
	                exit;
	        }
 
		} else {
			$this->Session->SetFlash('That Friend Exists');
			$this->redirect('/user_profiles/view/'.$this->User->UserProfile->profileID($user_id));
			exit;
		}
	}

One thing ill state is that the whole

 $count = $this->User->Friend->find('count', 
        		array('conditions' => 
        				array(	'user_id' => $user_id, 
        						'friend_id' => $friend_id)));
        if( $count < 1) {

is pretty lame on my part – the correct way would be to create a validation rule in your model but im in a bit of a rush and just need to get this part working.

Hope this helps – obviously you just call /users/addfriend/1/2 or something similar to add a friend and then the rest should all come together.

Dan

Share with your friends and help out this site:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogosphere News
  • E-mail this story to a friend!
  • Identi.ca
  • LinkedIn
  • Live
  • MisterWong
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati
  • Tumblr
  • Twitter
  • Yahoo! Bookmarks
  • Yahoo! Buzz

« Previous Entries Next Entries »

logo
Powered by Nu Order Webs