An Akismet Behavior
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(null, true)) {
...
}
?>
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.
Comments
Comment
1 Had to make a small change to get this working.
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.Comment
2 And besides blog comments?