Join a OrderBy pomocí Nette\Database
- zacharo
- Člen | 8
Zdravím,
už docela dlouho se snažím přijít na to jak se pomocí Nette/Database dá udělat jednoduchý sql příkaz typu
SELECT article.*, content.* FROM `article` INNER JOIN `content` ORDER BY date DESC
Prošel jsem dokumentaci i fórum, na jejichž základě jsem sestavil následující:
$this->connection->table('article')->select('article.*, content.*')->order('date ASC');
a s různými obměnami bez úspěchu zkoušel, nic nefungovalo. Všechny pokusy skončily s „Notice: Array to string conversion“ v laďence, v různých místech v závislosti na pokusu –normálně při výpisu v latte šabloně, při příkazu
$this->connection->table('article')->select('article.*, content.*')->order('date ASC')->getSql();
hned v daném místě.
Níže přidávám strukturu dotyčných tabulek.
CREATE TABLE IF NOT EXISTS `crr`.`content` (
`id` INT NOT NULL AUTO_INCREMENT ,
`date` DATETIME NULL ,
`user_id` INT NOT NULL ,
PRIMARY KEY (`id`, `user_id`) ,
UNIQUE INDEX `idcontent_UNIQUE` (`id` ASC) ,
INDEX `fk_content_user_idx` (`user_id` ASC) ,
CONSTRAINT `fk_content_user`
FOREIGN KEY (`user_id` )
REFERENCES `crr`.`user` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
CREATE TABLE IF NOT EXISTS `crr`.`article` (
`id` INT NOT NULL AUTO_INCREMENT ,
`title` VARCHAR(64) NULL ,
`text` LONGTEXT NULL ,
`subtext` VARCHAR(1024) NULL ,
`articleCategory_id` INT UNSIGNED NOT NULL ,
`content_id` INT NOT NULL ,
PRIMARY KEY (`id`, `articleCategory_id`, `content_id`) ,
UNIQUE INDEX `idarticle_UNIQUE` (`id` ASC) ,
INDEX `fk_article_articleCategory1_idx` (`articleCategory_id` ASC) ,
INDEX `fk_article_content1_idx` (`content_id` ASC) ,
CONSTRAINT `fk_article_articleCategory1`
FOREIGN KEY (`articleCategory_id` )
REFERENCES `crr`.`articleCategory` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_article_content1`
FOREIGN KEY (`content_id` )
REFERENCES `crr`.`content` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Edit: Chyba nastane např. po volání metody count nad Selection:
$x = $this->connection->table('article')->select('article.*, content.*')->order('date ASC');
$pom = ($x->count());
Děkuji za pomoc
Editoval zacharo (26. 1. 2013 23:00)
- zacharo
- Člen | 8
$this->connection->table('article')->select('article.*, content.*')->order('date ASC')->fetch();
Bohužel laděnka hlásí to samé: „Notice: Array to string conversion“
Chyba se vyskytuje v File: …/libs/Nette/Database/Drivers/MySqlDriver.php Line: 64
/**
* Delimites identifier for use in a SQL statement.
*/
public function delimite($name)
{
// @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
return '`' . str_replace('`', '``', $name) . '`';
}
- enumag
- Člen | 2118
Ok, tohle je bug. Jako nováček (dle počtu příspěvků) asi nebudeš
schopen napsat test, že? Něco s tím provedu.
Btw. když u část ->select(...)
prostě smažeš tak
by to mělo fungovat.
Moment moment, jsem si nepřečetl pořádně ten kód… bug to sice je
(nemělo by to házet takovou divnou notice) ale nevím co by to mělo udělat.
V každém případě používáš to špatně. Smaž celou tu část
->select(...)
. Data z té tabulky content se pak tahají přes
ref nebo related (podle toho co máš za relaci), případně místo ref lze
použít reflexe (->content->...
).
Editoval enumag (26. 1. 2013 23:43)
- zacharo
- Člen | 8
Jj, s Nette jsem začal minulý týden, zkouším se teď zorientovat.
Jinak ten dotaz bez toho selectu
$this->connection->table('article');
funguje, nicméně když chci řadit podle sloupce ‚date‘, který není v tabulce ‚article‘ ale je v té druhé ‚content‘, JOIN automaticky nenastane: příkaz
$this->connection->table('article')->order('date DESC');
vyhodí výjimku
PDOException #42S22
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'date' in 'order clause'
Je možné ty JOINy řešit nějakým alternativním způsobem v rámci \Nette\Database\Selection, nebo se musím uchýlit k psaní SQL dotazů ručně?
- enumag
- Člen | 2118
Základní nepochopení Nette\Database… S NDB se pracuje v podstatě bez joinů, respektive vytváří se automaticky když to potřebuješ ve where podmínkách. Pro účely získávání dat se ale s NDB pracuje tak, že se pouští nad každou tabulkou samostatný dotaz. Ne tak že bys je psal ručně přes $connection->table(…), ty dotazy se spustí automaticky při volání ref / related.
EDIT: Ne že by nešlo NDB donutit k joinům pro čtení, ale nedělej to. Raději zkus pochopit ten zamýšlený způsob, je mnohem lepší.
EDIT: Pro pochopení je podstatná tato část dokumentace, zejména ty dvě ukázky kódu. Efektivita už tě moc trápit nemusí a na API je lepší API dokumentace.
Editoval enumag (27. 1. 2013 0:01)