Skip to content

Instantly share code, notes, and snippets.

@pacifists
Created February 27, 2013 10:08
Show Gist options
  • Save pacifists/5046833 to your computer and use it in GitHub Desktop.
Save pacifists/5046833 to your computer and use it in GitHub Desktop.
This shows how to use CakePHP Expandable behavior with single table and make kind of polymorphic association. This uses a little bit modified version of expandable behavior so that it automatically adds model name to correct field for the associations.
CREATE TABLE IF NOT EXISTS `cms_custom_fields` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entity_id` int(11) DEFAULT NULL,
`key` varchar(100) DEFAULT NULL,
`val` blob,
`model` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ENTITY_ID` (`model`,`entity_id`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
<?php
class CustomField extends AppModel {
var $name = 'CustomField';
var $actsAs = array('Search.Searchable');
public $filterArgs = array();
}
<?php
/**
* undocumented class
*
* @package default
* @access public
*/
class ExpandableBehavior extends ModelBehavior{
var $settings = array();
function setup(&$Model, $settings = array()) {
$base = array('schema' => $Model->schema());
if (isset($settings['with'])) {
$conventions = array('foreignKey', $Model->hasMany[$settings['with']]['foreignKey']);
return $this->settings[$Model->alias] = am($base, $conventions, $settings);
}
foreach ($Model->hasMany as $assoc => $option) {
if (strpos($assoc, 'Field') !== false) {
$conventions = array('with' => $assoc, 'foreignKey' => $Model->hasMany[$assoc]['foreignKey']);
return $this->settings[$Model->alias] = am($base, $conventions, !empty($settings) ? $settings : array());
}
}
}
function afterFind(&$Model, $results, $primary) {
extract($this->settings[$Model->alias]);
if (!Set::matches('/'.$with, $results)) {
return;
}
foreach ($results as $i => $item) {
foreach ($item[$with] as $field) {
$results[$i][$Model->alias][$field['key']] = $field['val'];
}
}
return $results;
}
function afterSave(&$Model) {
extract($this->settings[$Model->alias]);
$fields = array_diff_key($Model->data[$Model->alias], $schema);
$id = $Model->id;
foreach ($fields as $key => $val) {
$field = $Model->{$with}->find('first', array(
'fields' => array($with.'.id'),
'conditions' => array($with.'.'.$foreignKey => $id, $with.'.key' => $key),
'recursive' => -1,
));
$Model->{$with}->create(false);
if ($field) {
$Model->{$with}->set('id', $field[$with]['id']);
} else {
$Model->{$with}->set(array($foreignKey => $id, 'key' => $key));
}
$Model->{$with}->set('val', $val);
$Model->{$with}->set('model', $Model->name);
$Model->{$with}->save();
}
}
}
<?php
class Place extends AppModel {
public $name = 'Place';
public $belongsTo = array(
'Location'
);
public $hasAndBelongsToMany = array(
'Expedition'
);
// Here's the important part hasMany for Expandable to work properly
public $hasMany = array(
'CustomField' => array(
'foreignKey' => 'entity_id',
'conditions' => array('CustomField.model' => 'Place'),
'dependent' => true
),
);
public $actsAs = array(
'Expandable',
'Utils.Sluggable' => array(
'label' => 'name',
'unique' => false,
'separator' => '-',
'length' => 100,
'update' => true,
)
);
function beforeSave() {
// need to just count and update the name count
if (isset($this->data[$this->name]['prisoner_names'])) {
$names = explode(',', $this->data[$this->name]['prisoner_names']);
$count = 0;
if (!empty($names[0])) {
$count = count($names);
}
$this->data[$this->name]['prisoner_name_count'] = $count;
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment