1

Temat: Problem z relacjami

witam,

mam trzy tabele:
products
symbols
ingredients

chcialbym wszystkie 3 tabele polaczyc za pomoca products_id i wybierac dane za pomoca symbolu z tabeli symbols.

Produkt ma wiele symboli i wiele skladnikow (ingredients).
symbole i skladniki naleza do produktu.

tak wyglada model symobl

    var $belongsTo = array(
        'Product' => array(
            'className' => 'Product',
            'foreignKey' => 'id'
        ),
        'Ingredient' => array(
        'className' => 'Ingredient',
        'foreignKey' => 'products_id'
        )
    );

Problem tego typu ze wybierajac http://localhost/symbols/views/ss-540 wybiera mi dane z bazy ze zlymi parametrami.

SELECT `Symbol`.`id`, `Symbol`.`products_id`, `Symbol`.`symbol`, `Product`.`id`, `Product`.`name`, `Product`.`dosage`, `Product`.`other_ingredients`, `Product`.`serving_size`, `Product`.`type`, `Product`.`date`, `Ingredient`.`id`, `Ingredient`.`product_id`, `Ingredient`.`name`, `Ingredient`.`quantity`, `Ingredient`.`rdz`, `Ingredient`.`order`, `Ingredient`.`proprietary_blend` FROM `sklady_symbols` AS `Symbol` LEFT JOIN `sklady_products` AS `Product` ON (`Symbol`.`id` = `Product`.`id`) LEFT JOIN `sklady_ingredients` AS `Ingredient` ON (`Symbol`.`products_id` = `Ingredient`.`id`) WHERE `Symbol`.`symbol` = 'PV-0139' LIMIT 1

Oczywiscie polaczenia sa zle, poniewaz `Symbol`.`id` = `Product`.`id`, a powinno byc `Symbol`.`products_id` = `Product`.`id` oraz zamiast `Symbol`.`products_id` = `Ingredient`.`products_id`.

byc moze powinien wybierac przez controller product ale nie umiem sie odwolac w tym cotrolerze do symbolu w innej tabeli.

2

Odp: Problem z relacjami

Ja zrobił bym tak, że w modelu symbolu wpisał:

    var $belongsTo = array(
        'Product' => array(
            'className' => 'Product',
            'foreignKey' => 'products_id'
        )
    );

i w modelu Ingredient:

    var $belongsTo = array(
        'Product' => array(
            'className' => 'Product',
            'foreignKey' => 'products_id'
        )
    );


Albo w modelu produktu:

    var $hasMany = array(
        'Symbol' => array(
            'className' => 'Symbol',
            'foreignKey' => 'products_id'
        ),
        'Ingredient' => array(
            'className' => 'Ingredient',
            'foreignKey' => 'products_id'
        )
    );

Mam nadzieje ze nie wprowadzam w błąd

Ostatnio edytowany przez Bonetti (2009-06-12 11:29:19)

3

Odp: Problem z relacjami

tak zrobiłem.

dodatkowo ustawilem recuresive na 2.
działa idealnie. dzieki!

pozdr.

4

Odp: Problem z relacjami

Na moje oko blednie stworzyłeś nazwy pola bo powinno być 'product_id' anie 'products_id'. To co Bonetti podał to wsłanie naprawia ten bład.

5

Odp: Problem z relacjami

nazwy tabel sa w liczbie mnogiej a standardowo do klucza obcego dodajemy _id wiec na moje oko jest wlasnie OK.

6

Odp: Problem z relacjami

duke_piotr napisał/a:

nazwy tabel sa w liczbie mnogiej a standardowo do klucza obcego dodajemy _id wiec na moje oko jest wlasnie OK.

Dodajemy _id ale już do liczby pojedynczej czyli np. user_id, a nie users_id. Można to zobaczyc na przykładzie w dokumentacji przy relacjach : link

7

Odp: Problem z relacjami

duke_piotr napisał/a:

nazwy tabel sa w liczbie mnogiej a standardowo do klucza obcego dodajemy _id wiec na moje oko jest wlasnie OK.

Moze i w przykladach tak jest lecz jednym z glownych nurtow nazewnictwa w RBD jeset wlasnie nazwa tabeli (l.m.) plus _id.

Z powodzeniem stosuje to w cake i nie ma problemu jak do tej pory (mialem jeden gdy tabela nazywala sie queues a w Cake nie szlo modelu nazwac Queue tylko tez Queues).

8

Odp: Problem z relacjami

mam kolejny problem. podlacze sie pod ten temat poniewaz rowniez jest o relacjach.
mam dwa modele. Gallery oraz GalleryFile

<?php
class Gallery extends AppModel {

    var $name = 'Gallery';
    var $validate = array(
        'name' => array('notempty')
    );
    var $recuresive = 2;
    var $hasMany = array(
        'GalleryFile' => array(
            'className' => 'Galleryfile',
            'foreignKey' => 'galleries_id',
            'dependent'        => true,
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );

}
?>
<?php
class Galleryfile extends AppModel {

    var $name = 'Galleryfile';
    var $validate = array(
        'galleries_id' => array('numeric'),
        'filename' => array('notempty'),
        'name' => array('notempty')
    );

    //The Associations below have been created with all possible keys, those that are not needed can be removed
    var $belongsTo = array(
        'Gallery' => array(
            'className' => 'Galleries',
            'foreignKey' => 'galleries_id',
            'conditions' => '',
            'fields' => '',
            'order' => ''
        )
    );

}
?>

w kontrolerze Galleries w metodzie index chce miec liste galerii - oczywiscie to dziala

    function index() {
        $this->Gallery->recursive = 1;
        $this->set('galleries', $this->paginate());
        
        $this->pageTitle = __("pageTitle_home" ,true) .__("Galleries",true);
    }

tyle tylko, ze wczytuje mi od razu cala tablice z plikami.
potrzebuje tylko jeden rekord z tabeli GalleryFile w tej metodzie - zebym mogl wyciagnac miniature do galerii.
da sie to jakos zrobic?

pozdr.

9

Odp: Problem z relacjami

Tylko po cholere to dzielic na dwie tabele ....

CREATE TABLE IF NOT EXISTS `cake_tmodule_galleries` (
  `id` int(10) NOT NULL auto_increment,
  `user_id` int(10) NOT NULL,
  `type` enum('album','image') NOT NULL default 'image',
  `parent_id` int(10) NOT NULL default '0',
  `image_name` varchar(32) default NULL,
  `name` varchar(32) NOT NULL,
  `description` varchar(128) default NULL,
  `publish_from` varchar(10) default NULL,
  `publish_to` varchar(10) default NULL,
  `featured` tinyint(1) NOT NULL default '0',
  `status` tinyint(1) NOT NULL default '0',
  `allow_comment` tinyint(1) NOT NULL default '0',
  `allow_rate` tinyint(1) NOT NULL default '0',
  `sort` int(10) NOT NULL default '0',
  `order_by` varchar(32) NOT NULL,
  `created` datetime default NULL,
  `modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `deleted` tinyint(1) NOT NULL default '0',
  `deleted_date` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=423 ;

teraz po koleji :
user_id - w mojej aplikacji mam jakies 3k usyztkownikow, kazdy moze miec swoja galerie, stad user_id
type - typ rekordu, album ( "galeria" moze zawierac inne "pod-galerie"), albo zdjecie
parent_id - id elementu rodzica
image_name - nazwa oryginalnie zuploadowanego obrazka ( u mnie wygenerowana losowo, kazdy obrazek ma domyslnie 3 rozmiary, thumbnail, image i featured , wyswietlajac zdjecie na stronie uzywam jednego z prefixow czylu np "thumbnial_" + image_name, gdy brak zdjecia dla alumu, album wyswietli losowo wbrany obrazek z posrod elementow ktore sie w nim zawieraja)
name - nazwa obrazka lub albumu
description - jak wyzej
publish_from, publish_to , daty poczaku i konca publikacji, uzywane jedynie przez cron'a  ktory co minute sprawdza dla ktorych rekordow ( nie tylko w galerii ) nalezy zaczac lub zakonczyc publikacje, i zmienia wtedy status z 1 na 0 lub 0 na 1
featured- wyroznianie odpowiedniego zdjecia , albumi itp , do roznych celi , np pokaznie na glowne stronie.
status , gdy = 0, rekord nie jest wybierany zadnym zapytaniem
allow_comment - zezlwala lub zabrania komentowania danego zdjecia przez uzytkownikow, ustawienie w przyapdku albumu powoduje dziedziczenie tego ustawienia dla wszytskich elementow w dol.
allow_rate - zelzwala lub zabrania oceniania danego zdjecia , reszta tak jak wyzej
sort - daje mozliwosc recznego przypisania kolenosci wyswietlania
order_by - sposob sortowania t po nazwie, dacie dodania, ilosci zdjec w labumie, ocenie , losowo  lub po wartoscie pola sort itd ....
pola deleted* - pola behaviora SoftDeletable

dodatkowo mozliwosc uploadu wielu zdjec naraz ( przetwarzanie koleki cronem w tle i powiadomienie smsem po skonczeniu przetwarzania)

do wbierania rekordow zwykle uzywam find("all") albo find("threaded"), prosto przyjemnie i latwo sie cache'uje.