2011-11-09 17 views
6

Tengo una tabla llamada categorías. La tabla contiene categorías y sus sub (subsub) Categorías ...Cómo implementar un modelo de autorreferencia (parent_id) en cakephp

Su una mesa de fácil:

  • Identificación
  • parent_id
  • título

De esta manera puedo hacer categorías con profundidad infinita ... Esperaba que cakephp entendiera parent_id (también probé category_id, pero eso hace que CakePHP se una a sí mismo: D)

¿Cuál es la forma correcta de abordar esto?

NOTA: También hay una tabla de 'muchos a muchos' llamada lugares. Esos lugares pueden pertenecer a una o más categorías.

Respuesta

18

El comportamiento de árbol es excesivo para esta situación. Sólo tiene que establecer su modelo de esta manera:

class Category extends AppModel { 

    public $hasMany = array(
    'Children'=>array(
     'className'=>'Category', 
     'foreignKey'=>'parent_id' 
    ) 
); 

    public $belongsTo = array(
    'Parent'=>array(
     'className'=>'Category', 
     'foreignKey'=>'parent_id' 
    ) 
); 

} 

Ahora, cuando se hace una find() en la Categoría, obtendrá dos modelos adicionales llamado padre (que apunta a la ID de padre) y niños (que enumera sus hijos).

+0

Hola Richard, estaba buscando el comportamiento del árbol, pero estoy de acuerdo que puede ser excesivo. De todos modos. ¡Gracias por señalar esto! –

2

En el modelo Categoría: Padres belongsTo y hasMany niños, ambos tienen la clase 'Categoría' y clave externa 'parent_id'

5

Mira el tree behaviour; con la lógica MPTT. El enlace proporcionado al sitio web de Oracle está muerto; pero puede encontrar un montón de material sobre cómo usarlo en cake manual y online.

CREATE TABLE categories (
    id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    parent_id INTEGER(10) DEFAULT NULL, 
    lft INTEGER(10) DEFAULT NULL, 
    rght INTEGER(10) DEFAULT NULL, 
    name VARCHAR(255) DEFAULT '', 
    PRIMARY KEY (id) 
); 

Solo asegúrese de que su mesa coincida con esa estructura para obtener mejores resultados dentro de Cake y su horneado.

+0

Gracias hombre, cosas interesantes, y de hecho exactamente lo que necesito. ¡Todo está configurado sin problemas! –

+0

En muchos casos esto es excesivo. Una tabla simple de autorreferencia, como se menciona a continuación por Anh Pham con las asociaciones apropiadas, es más que adecuada en la mayoría de las causas. El comportamiento de los árboles se vuelve cada vez más útil a medida que los niveles de "profundidad" van más allá del nivel (es decir: los niños pueden tener hijos). – pimbrouwers

0

Pregunta relacionada: supongamos que tengo una jerarquía de autorreferenciación de 3 niveles implementada según lo recomendado por @RichardAtHome. Entiendo que cuando intento encontrar una Categoría en particular, también obtengo la categoría principal y todas las categorías secundarias. Sin embargo, ¿cómo puedo hacer que encuentre el camino de regreso a la raíz? ¿Hay algún truco limpio para lograr esto o requerirá un truco personalizado?

Me imagino usando esto en escenarios donde la tabla Product tiene una ID de categoría asociada, pero cuando la visualizo a los usuarios me gustaría mostrar toda la cadena parental para que puedan ver algo como 'confectionaries/seasonal/nestle '- y luego el usuario puede alterar toda la jerarquía de productos

1

la siguiente custom recursive function tree() trabajado para mí

public function index() { 
    $c = $this->tree(); 
    debug($c); 
    exit; 
} 


function tree($parent=null){ 
    $arr = array(); 
    $categories = $this->Category->find('all',array(
     'conditions'=>array('Category.parent_id '=> $parent) 
    )); 
    foreach($categories as $key => $category){   
     $arr[$category['Category']['id']]['title'] = $category['Category']['name'];    
     $arr[$category["Category"]["id"]]['children'] = $this->tree($category['Category']['id']); 
    } 
    return $arr; 
} 
Cuestiones relacionadas