An Akismet Behavior

By Tom OReilly (TommyO)
There have been a lot of tools written in the past to help CakePHP apps deal with comment spam. This is yet another.

Where many code snippets have addressed Akismet with a model, a datasource or a component, it is my opinion that the best fit is as a Behavior.


Configuration

The behavior expects the following configuration values to be set:

  • Akismet.key: provided by Akismet
  • Akismet.blog: the base url to your site.
  • Akismet.timeout: in seconds - optional - defaults to 3

Setting up the behavior in your Model

The params array can be used to map Akismet fields to Model fields and activate additional options.

Model Class:

Download code <?php 
class Comment extends AppModel {

    var 
$actsAs = array('Akismet' => array(
            
'content'=>'body',
            
'author'=>'User.name',
            
'type'=>false,
            
'owner'=>'owner_id',
            
'is_spam'=>'spam'
    
));
}
?>

In the above example we map the required field of 'content' to the 'Comment.body' field, 'author' to a field in the associated User model, protected the 'type' field from being submitted, added a custom 'owner' field and activated the automagic trigger to save the results to the 'Comment.spam' field(see below).

The fields that the behavior looks for to send to Akismet have the following default names, but can be mapped to local Model fields or, with the exception of the 'content' field, to a field in an associated model:

  • content
  • author
  • author_email
  • author_url
  • type

If the field doesn't exist in the submitted data it will be skipped quietly. If the field does exist but you do not want it submitted, map it to false, like in the above example. Additional fields can be added if there is something else you'd like submitted.


notSpam(): sending a comment to Akismet for testing

notSpam() Parameters:

  • $data placeholder to meet custom validation requirements. Ignored here.
  • $strict whether or not to report errors communicating with Akismet as spam.

This is the heart of the behavior. There are three ways to use this method.

1. Using it as a validation rule in the model:

Download code <?php var $validate = array('body'=>array('notSpam'=>array('rule'=>array('notSpam'true)))); ?>

2. Calling it directly from a Model method or the controller:

Download code <?php
    $this
->Comment->set($this->data);
    if (
$this->Comment->notSpam(nulltrue)) {
        ...
    }
?>

3. Using the automagic of the 'is_spam' parameter

Map the name of a local Model field to the 'is_spam' param to trigger the method in the beforeSave() callback and add the results to the mapped field.

Download code <?php var $actsAs = array('Akismet'=>array('content'=>'body''is_spam'=>'spam')); ?>

This example will save 0 on clear, 1 on spam or null on error, to the 'spam' field. If you need to suppress this behavior, be sure to leave the mapped field out of the $whitelist param in the save call.


markAs(): changing the status of a comment previously tested

markAs() Parameters:

  • $type 'spam' or 'ham' to set the status.
  • $report whether or not to report the change back to Akismet. Only useful when 'is_spam' parameter is set.

You can change the results on spam missed by Akismet or those caught as a false positive. For example, from the controller:

Download code <?php
    $this
->Comment->set($this->data);
    
$this->Comment->markAs('spam');
?>

If you are using the 'is_spam' magic as described above, the field in the database will be updated as well.

Page 2: The code

Comments 955

CakePHP Team Comments Author Comments
 

Comment

1 Had to make a small change to get this working.

Needed to add a key called Akismet.blog with the base url to my bootstrap.php Configure::write('Akismet.blog','http://www.example.com/');  to get this working. Not sure if the API changed, but the verify-key call needs 'blog' populated, not 'url.' With that change, it works very well! Thanks for sharing this.
Posted Apr 2, 2009 by Myron Hayden
 

Comment

2 And besides blog comments?

I suppose this could also be used for user feedback on forms that submit to email? I'd imagine the spam content is somewhat similar if it's coming from a bot trolling for forms.
Posted Apr 11, 2009 by Cameron Perry