Proč se musí psát ->ref()?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
tomaass
Člen | 74
+
0
-

Ahoj,

mám v DB tabulky a nedaří se mi je propojit tím hezkým způsobem

$row->tabulka_jina->polozka

Ale když použiji druhý (otřesný) způsob

$row->ref('package','barcode')->quantity

tak to jde.

Jenže já chci psát ten první a už jen proto že je to hezčí, ale i proto, že to bude v šabloně.

Jinak v DB (Postgre) mam krásné primární klíče i cizí a je to k ničemu, protože to píše:

PDOException

No reference found for $movement->package

Data tam také jsou, a je to vazba N:1. Nebo-li: pro každý z N řádků najdeme přávě 1 záznam v druhé tabulce.

Jak docílím prvního zápisu aby to fungovalo? Děkuji za rady

vvoody
Člen | 910
+
0
-

Nastavenie FK nieje postačujúca podmienka aby ti fungoval reflection!

Ukáž nám reálny kód na ktorom ti vybehol ten error a taktiež dump tabuliek.

tomaass
Člen | 74
+
0
-

ok. Chci propojit tabulky movement->package

kód:
V Modelu:

$data =
    $this->connection->table('movement')
                        ->where(
                            array(
                                'date'=>$inventorying->checkdate,
                                'action_id'=>Action::INVENTURA))
                        ->order('id');

Kód v šabloně:

{if count($history)}
    {foreach $history as $row}{dump $row}
        <div class="badge info">
            <i class="icon-barcode icon-white"></i> {$row->barcode|BarCode} |
            Součet: <span style="color:red;">{$row->ref('package','barcode')->quantity}</span><span class="muted">/{$row->package->packagequantity}</span>
            {if $row->quantity}
                <span class="pull-right">
                    {if $row->quantity > 0}+{/if}{$row->quantity}
                </span>
            {/if}
        </div>
    {/foreach}
{else}
        Není co zobrazit.
{/if}

Tabulky:

CREATE TABLE "package"
(
  component_id integer NOT NULL,
  id integer NOT NULL,
  packagequantity integer NOT NULL,
  quantity integer NOT NULL,
  checkdate timestamp without time zone,
  location_id integer,
  status_id integer,
  note text,
  company_id integer,
  supliercode text,
  price real,
  barcode integer NOT NULL,
  CONSTRAINT "PK_package" PRIMARY KEY (barcode),
  CONSTRAINT "FK_company_id" FOREIGN KEY (company_id)
      REFERENCES company (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_component_id" FOREIGN KEY (component_id)
      REFERENCES component (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_location_id" FOREIGN KEY (location_id)
      REFERENCES location (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_status_id" FOREIGN KEY (status_id)
      REFERENCES status (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT package_barcode_key UNIQUE (barcode)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE "package"
  OWNER TO postgres;



CREATE TABLE movement
(
  id serial NOT NULL,
  package_id integer NOT NULL,
  component_id integer NOT NULL,
  date timestamp without time zone NOT NULL DEFAULT now(),
  quantity real NOT NULL,
  shipment_id integer,
  user_id integer NOT NULL,
  action_id integer,
  location_id integer,
  barcode integer,
  CONSTRAINT "PK_movement" PRIMARY KEY (id),
  CONSTRAINT "FK_action_id" FOREIGN KEY (action_id)
      REFERENCES action (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_location_id" FOREIGN KEY (location_id)
      REFERENCES location (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_package_id" FOREIGN KEY (barcode)
      REFERENCES "package" (barcode) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_shipment_id" FOREIGN KEY (shipment_id)
      REFERENCES shipment (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "FK_user_id" FOREIGN KEY (user_id)
      REFERENCES "user" (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT "UQ_movement_id" UNIQUE (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE movement
  OWNER TO postgres;

Jake jsou dalsi podminky pro ten reflection?

vvoody
Člen | 910
+
0
-

Tvoj FK neodkazuje na PK tabulky package, takže by ani ref nemalo fungovat, teda fungovať bude ale, myslím že teraz sa matchuje

movement.barcode = package.id

namiesto toho čo očakávaš ty

movement.package = package.barcode

Nette Database vždy čaká že sa odkazuje na PK. Pozri sa do debug baru aké sqlka to vykonáva, či sa náhodou nemýlim.

K tomu správnemu zápisu bez funkcie ref, to pri Discovered Reflection konvencia nieje ako si písal:

$row->tabulka_jina->polozka

Správne to je takto:

$row->cast_nazvu_FK->polozka

Pozri si príklad s knihami a autormi. Často sa stáva že v jednej tabulke (book) sú dva FK (author_id,maintainer_id) ktoré odkazujú na tú istú tabulku, preto by sme si v tomto prípade nevystačili s konvenciou:

$row->tabulka_jina->polozka

Ak by sme v tom príklade premenovali tabulku authors na users, tak by stále korektne fungoval zápis:

$book->author->name;
$book->maintainer->name;

Takže ak použiješ časť názvu FK (barcod,barco,barc…)

$movement->barcod->polozka

Áno, je to logický nezmysel pristupovať k $movement->barc a podobným nezmyselným properties, preto treba dodržovať konvencie vytvárania názvov FK, čiže u teba by som premenoval movement.barcode na movement.package_barcode. V takomto prípade už ti bude fungovať práve to čo si asi pôvodne chcel:

$movement->package->polozka

Ale skorej si skontroluj to, čo som písal na začiatku tohto postu, že s ktorým stĺpcom z package sa matchuje FK z tabulky movement.

tomaass
Člen | 74
+
0
-

Děkuji.

Bohužel, PK tabulky package je opravdu ‚barcode‘ a v movementu je FK namireny na package.barcode.

Zkousel jsem zapsat

	$row->FK_package_id->quantity

vysledkem je opet:

No reference found for $movement->FK_package_id

Kde se dájí najít ty informace, co jsi mi tu předal? O těch FK? To demo jsem pročítal ale nic takovýho jsem tam nenašel…

vvoody
Člen | 910
+
0
-

Nehovoril som o Constraints ale priamo o názve stĺpca v ktorom je FK. Informácie o tom získaš asi len tak že si prejdeš zdrojáky tej reflection. Pozrel si sa na tie sqlka ktoré to vykonáva ak použiješ metódu ref?

edit: aha pardon, takže barcode je PK :) ked som videl id tak som automaticky predpokladal že práve ono je PK. Tak potom navrhujem premenovanie toho FK (názvu stĺpca) na package_barcode a potom vyskúšať

$movement->package->quantity

alebo zmena štruktúry neprichádza do úvahy?

Editoval vvoody (8. 11. 2012 19:47)

tomaass
Člen | 74
+
0
-

vykonání:

	 $row->barcode->quantity

udělá chybu: Trying to get property of non-object

vykonání:

	$row->ref('package','barcode')->quantity

udělá dotaz asi takový:

SELECT "barcode", "quantity"
FROM "package"
WHERE ("barcode" IN (20481985, 20481986, 20481987, 186624))

to funguje…

tomaass
Člen | 74
+
0
-

tak a teď to funguje. Děkuji Vám.

A ještě mi prosím napovězte.

vyřešilo to přejmenování toho sloupce na „package_barcode“ jak jste navrhoval.

Když se ten sloupec jmenoval jen barcode, tak to nefungovalo ($row->barcode->quantity)
ale po přejmenování na „package_barcode“ to jde, když volám $row->package->quantity.

Jakto? Používá se snad část názvu FK na název rabulky nebo co?

vvoody
Člen | 910
+
0
-

Ano, ako som písal, pre referencie na iné tabuľky sa používa časť názvu FK. Určite nie jeho celý názov, lebo tým len získame hodnotu daného Fk/stĺpca (to dôvod tej chyby Trying to get property of non-object).

Je to proste, dovolím si tvrdiť, široko zaužívané pravidlo nazývať FK názvom odkazovanej tabulky s pripojením postfixu _id. V tvojom prípade más PK namiesto id na stĺpci barcode, preto postfix _barcode čo zafunguje tak isto dobre. Discovered reflection proste s takýmito konvenciami počíta.