Created
February 27, 2013 10:08
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class CustomField extends AppModel { | |
var $name = 'CustomField'; | |
var $actsAs = array('Search.Searchable'); | |
public $filterArgs = array(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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