Topic: Relazioni hasOne - belongsTo e implementazione ereditarietà
Salve di nuovo a tutti. Il quesito di questa volta riguarda un mio tentativo di implementare un meccanismo di specializzazione tra alcuni modelli.
Lo scenario è il seguente:
1) Immaginiamo di avere una classe di modello chiamata "Attachment" con attributi:
- id
- name -> pathname completo (dir + filename) del file sul server.
- type -> tipologia MIME del file.
- size -> Dimensione in bytes del file.
2) Immaginiamo ora di specializzare questa classe in un altro modello, ad esempio "Image". Questo modello "specializzato" non verrà costruito tramite i costrutti di ereditarietà della programmazione OOP, bensì ho pensato di implementarlo tramite un'associazione ER "uno-a-uno" con il modello "Attachment". In particolare il modello "Image" è così definito:
- id
- attachment_id -> "istanza" di attachment che quest'istanza di "Image" specializza.
- alt -> descrizione alternativa.
- width
- height
3) L'associazione è così definita:
//models/image.php
/**
* Un'immagine è una specializzazione di un generico allegato.
*/
var $belongsTo = 'Attachment';La cosa interessante di questo sistema è che, ad esempio, nella mia applicazione ogni allegato può essere "taggato" (così come le pagine) e questo permette di implementare un meccanismo di ricerca basato su tags rapido e completo (soprattutto usando il "behavior" che ho postato nel thread sulle HABTM).
Tale comportamento è inserito nel modello "Behavior" e, di conseguenza, viene "ereditato" in tutte le classi che implementano questa sorta di "specializzazione". Inoltre, come è ovvio, tutti i dettagli di più basso livello (nome, dimensione in bytes, tipo, ecc.) sono incapsulati in "Attachment" rendendo i modelli specializzati più piccoli e leggeri.
Avendo poi anche "controllers" separati è possibile centralizzare l'upload degli "attachments" (usando uno dei tanti componenti già pronti) ed estendendo di volta in volta il form con gli eventuali campi aggiuntivi del modello che si vuole caricare.
Non tutti gli "attachments", poi, possono avere bisogno di una gestione specializzata, rendendo così il sistema più flessibile, concentrandosi solo sui tipi di files che richiedono operazioni specifiche (ad esempio le immagini).
Bene. Ora veniamo ai problemi....
Il problema fondamentale è uno: come riuscire ad associare sempre il file "genitore" al modello specializzato in qualunque operazione che lo riguarda? Io avevo pensato di ricorrere ad un "behavior" chiamato "Allegeable" utilizzato dalle varie classi specializzate con, implementato, il metodo "afterFind":
<?php
/**
* Allegeable Behavior class file.
*
* Model Behavior to support attachment specialization.
*
* @author Emanuele 'Zuck' Bertoldi
* @filesource
* @package app
* @subpackage models.behaviors
*/
class AllegeableBehavior extends ModelBehavior {
/**
* Initiate behaviour for the model using specified settings.
*
* @param object $model Model using the behaviour
* @param array $settings Settings to override for model.
*
* @access public
*/
function setup(&$model, $settings = array()) {
$default = array('attachment_model_name' => 'attachment');
if (!isset($this->settings[$model->name])) {
$this->settings[$model->name] = $default;
}
$this->settings[$model->name] = array_merge($this->settings[$model->name], ife(is_array($settings), $settings, array()));
}
/**
* Run after a model is found, used to fill parent model attachment data.
*
* @param object $model Model about to be found.
* @param mixed $results Model rows found.
*
* @access public
* @since 1.0
*/
function afterFind(&$model, &$results) {
if (!empty($results)) {
$parent_model_name = $this->settings[$model->name]['attachment_model_name'];
$model_ref_name = $parent_model_name.'_id';
$p =& new $parent_model_name;
foreach ($results as &$m) {
$m[$parent_model_name] = $p->read(null, $m[$model->name][$model_ref_name]);
}
}
}
}
?>Questo sistema funziona solo in alcuni casi, in particolare ho riscontrato che nel seguente caso non viene invocato:
- Leggo i dati di una riga della tabella "Page" che possiede una relazione "belongsTo" con "Image". L'array restituito si ferma ad "Image" e non allega anche i dati di "Attachment" (infatti il metodo del behavior non viene invocato).
Il problema potrebbe essere nel "recursive" che deve essere maggiore di "1" per invocare anche "Attachment"? E se questo accorgimento funziona con le operazioni di "find", come sistemo la faccenda anche quando richiedo i dati tramite paginazione? In questo caso questo parametro dove lo imposto?
Grazie per l'eventuale aiuto!! ![]()