code tunes

Web applications, software engineering, Ruby on Rails, Cake PHP, JavaScript, etc.

Archive for the ‘behavior’ tag

UploadPack - easy and flexible way to upload files with CakePHP

with 3 comments

I have seen and worked with many scripts and plugins (not only written in PHP) that tries to deal with file-upload functionality on server side, thanks to this I think I have some view on how good file-upload plugin should work. The thing was to put it in CakePHP clothes and code it.

Here are the requirements I set:

  • save procedure of record with attached file should be no different to usual record
  • it should be possible to do some additional processing of uploaded file at the time of saving it (for example thumbnail generation)
  • easy access to uploded file, it’s URL and alternatives (different thumnails) from view level
  • everything should require no or minimum configuration to work, but still remain flexible if the whole application needs it
  • natural integration with CakePHP framework

Here’s the effect of some planning and coding - UploadPack. Right now it contains:

  • UploadBehavior - deals with saving files to disk and post-save processing
  • UploadHelper - provides nice access to files (URLs, thumbnails) from view level

Everything works quite gracefully, I think. You only need to add one field to model’s database table (which will hold file name) and attach behavior to model. The rest is done automatically. Everything is documented on repository’s page.

It’s still an early version - 0.1, but there is much it can do right now. The work is underway to provide new features. Take a look at it.

If you have any views or ideas, please leave a comment. I’d appreciate it.

Written by Michał Szajbe

November 4th, 2008 at 9:13 pm

NamedScopeBehavior upgrade

with 2 comments

I have just added a small functionality to my NamedScopeBehavior.

Now you can use named scopes from multiple models at once in a single find query. Assuming that given models are associated through belongsTo or hasOne association.

Quick example:

// model definitions
class User extends AppModel {
  var $actsAs = array(
    'NamedScope' => array(
      'activated' => array('User.activated' => 1)
    )
  );
  var $belongsTo = array(
    'Group'
  );
}
 
class Group extends AppModel {
  var $actsAs = array(
    'NamedScope' => array(
      'admins' => array('Group.name' => 'admins')
    )
  );
}
 
// in controller
$this->User->find('all', array('scope' => array('User.activated', 'Group.admins')));

New version can be found in repository.

Written by Michał Szajbe

September 15th, 2008 at 12:39 am

Posted in CakePHP

Tagged with , ,

Named scope in CakePHP

with 2 comments

Some time ago I wrote how to improve Cake controllers’ callback system basing on a solution from Ruby on Rails. Today I am going to port another cool feature of Rails to CakePHP - named scope.

Check this Rails example first if you don’t know what the named scope is:

# model definition
class User < ActiveRecord::Base
  # only activated users
  named_scope :activated, :conditions => "activated_at is not null" 
 
  # only currently online users
  named_scope :online, :conditions => "date_add(last_activity, interval 5 minute) < now()"
end

This is very simple example. In fact, named scope functionality can be used for much more than this. However my Cake version I present below is limited to defining conditions.

So we defined some scopes and gave them names. Now we can apply them to searching.

# let's find all activated users
users = User.activated.find(:all) 
 
# let's find all activated users who are currently online and has more than 10 points
users = User.activated.online.find(:all, :conditions => "points > 10")

I bet you can already see advantages of such notation. Often used conditions (for example: often you want to limit search results to activated users only) are placed in named_scope definition, the others (probably more situation-specific ones) go to usual :conditions option. Improved readability, less writing, fewer chances to make mistakes.

Let me present you NamedScopeBehavior which will give you similat functionality in CakePHP. What it does is converting scope definitions to conditions parameter of find() method and that is done transparently in beforeFind callback method.

Download named_scope.php file from repository and place it it app/models/behaviors folder of your Cake app. Then attach this behavior to a model and define named scopes.

class User extends AppModel {
  var $actsAs = array(
    'NamedScope' => array(
      'activated' => array('User.activated in not null'),
      'online' => array('date_add(User.last_activity, interval 5 minute) > now()')
    )
  );
}

Then you can use it.

// in your controller
$this->User->find('all', array('scope' => 'activated'));
$this->User->find('all',
  array('conditions' => 'points > 10', 'scope' => array('activated', 'online')))

Pagination also works fine with scopes.

// in your controller
$paginate = array(
  'User' => array(
    'order' => 'created ASC',
    'limit' => 20,
    'scope' => array('online', 'activated')
  )
);

Happy developing!

Written by Michał Szajbe

September 5th, 2008 at 2:35 pm

Posted in CakePHP

Tagged with , ,