Cannot use object of type Nette\Database\Statement as array
- motorcb
- Člen | 552
Pro zjednodušení to uvedu na tomto příkladě:
Model – User.php:
/**
* Get users
* @return \Nette\Database\Table\Selection
*/
public function getAllUsers()
{
return $this->connection->query( "SELECT id, name, nick FROM users ORDER BY body DESC" );
}
Presenter:
public function renderDefault()
{
$this->template->users= $this->context->match->getAllUsers();
}
Sablona:
Mimo jiné bych chtěl vypsat ID uživatele na indexu 0:
{$users[0]->id}
Ovšem to mi hlásí chybu: Cannot use object of type Nette\Database\Statement as array
Nevěděl by někdo jak to vyřešit?
Díky
- jtousek
- Člen | 951
Záleží jak moc složitý. Můžeš sem hodit celé SQL? Některé věci se totiž v NDB dají obejít.
- motorcb
- Člen | 552
@**jtousek**:
Nejsem ted na svem PC ale jde o takovyto dotaz ktery ma vlozeny dotaz:
SELECT b.name, (SELECT count(id) FROM `book` WHERE l.book_id = id ) AS contBook
FROM book b
LEFT JOIN lend l on b.id = l.book_id
LEFT JOIN users u on l.user_id
WHERE u.id = 5
ORDER BY l.date ASC
Vypis me pujcene knizky a zaroven spocitej kolikrat jsem mel knihu pujcenou
- jtousek
- Člen | 951
Mám pocit, že ani přímo to SQL ti nevybere přesně to co chceš. Hlavně ten poddotaz se mi nezdá.
Jinak myslím, že by to v NDB mělo jít vyřešit, jen by to asi udělalo více než jeden dotaz (což nepovažuji za nevýhodu). Ale na to bych musel vidět strukturu databáze, takhle jsem z toho poněkud zmaten. Co přesně chceš vypsat? Všechny knihy, které jsem někdy měl vypůjčené a u každé z nich počet výpůjček?
- jtousek
- Člen | 951
Mimochodem ten JOIN na tabulku users je zbytečný, dále NDB používá zásadně inner join:
SELECT b.name, COUNT(l.id) AS countBook
FROM book b
INNER JOIN lend l on b.id = l.book_id
WHERE l.user_id = 5
GROUP BY b.id
ORDER BY l.date ASC
V NDB by to mohlo jít nějak takto, ale nejsem si úplně jistý.
$connection->table('book')->select('name, COUNT(lend:id) AS countbook')->where('user_id', 5)->group('book.id')->order('lend.date');
EDIT: přidáno group()
Editoval jtousek (7. 10. 2012 11:25)
- jtousek
- Člen | 951
To co chceš jedním dotazem nepůjde ani v SQL (nebo jen velmi velmi složitě). V NDB by to mělo jít pomocí related poměrně jednoduše – můj názor je ten že jednodušeji to asi ani jít nemůže. Bohužel momentálně nemám vůbec čas nad tím přemýšlet, už jsem agregace v NDB delší dobu nepoužíval a musel bych studovat API.
- Caine
- Člen | 216
Treba tak?
$myBooks = $connection->table('book')->select('name, COUNT(lend:id) AS countbook')->where('user_id', 5)->group('book.id')->order('lend.date');
foreach ($myBooks as $book) {
$book['lendcount'] = $book->related('lend')->count('*');
}
PS: Mozna bys mel zacit studovat API NDB, kdyz uz to chces pouzivat..
- motorcb
- Člen | 552
Abychom se tu jen tak nedohadovali, tak to uvedu na pravou míru.
Databáze:
CREATE TABLE IF NOT EXISTS `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=7 ;
INSERT INTO `book` (`id`, `name`) VALUES
(1, 'kniha1'),
(2, 'kniha2'),
(3, 'kniha3'),
(4, 'kniha4'),
(5, 'kniha5'),
(6, 'kniha6');
CREATE TABLE IF NOT EXISTS `lend` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `book_id` (`book_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=5 ;
INSERT INTO `lend` (`id`, `book_id`, `user_id`, `date`) VALUES
(1, 1, 1, '2012-10-09 00:00:00'),
(2, 1, 2, '2012-10-09 00:00:00'),
(3, 1, 3, '2012-10-09 00:00:00'),
(4, 2, 1, '2012-10-09 00:00:00');
(5, 1, 1, '0000-00-00 00:00:00');
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nick` varchar(50) COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=4 ;
INSERT INTO `user` (`id`, `nick`) VALUES
(1, 'ctenar1'),
(2, 'ctenar2'),
(3, 'ctenar3');
ALTER TABLE `lend`
ADD CONSTRAINT `lend_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
ADD CONSTRAINT `lend_ibfk_1` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);
Výše uvedený dotaz, který mi byl doporučen ne počítá správně ( kolikrát jsem měl knihu vypůjčenou)
SELECT b.name, COUNT(l.id) AS contBook
FROM book b
LEFT JOIN lend l on b.id = l.book_id
LEFT JOIN users u on l.user_id
WHERE u.id = 1
GROUP BY b.id
ORDER BY l.date ASC
Tento dotaz dělá to co požaduji:
Vypíše názvy mých vypůjčených knih, počet mých výpůjček a počet
všech výpůjček:
SELECT
b.name,
u.nick,
( SELECT COUNT( id ) FROM lend WHERE book_id = b.id and user_id = u.id) AS mujPocetPujceni,
( SELECT COUNT( id ) FROM lend WHERE book_id = b.id) AS celkovyPocetPujceni
FROM book b
LEFT JOIN lend l ON b.id = l.book_id
LEFT JOIN user u ON l.user_id = u.id
WHERE u.id = 1
GROUP BY b.name
Dokázal by někdo tento dotaz přepsat do NDB?
Díky
Model databáze: http://s8.postimage.org/…knihovna.png
Editoval motorcb (9. 10. 2012 19:16)
- Caine
- Člen | 216
Boze, je to spravne az na par chybicek..
$myBooks = $connection->table('book')->select('book.id, book.name, COUNT(lend:id) AS countbook')->where('user_id', 1)->group('book.id')->order('lend:date'); //dvojtecka musi byt vsude
$books = array();
foreach ($myBooks as $book) {
$book['lendcount'] = $book->related('lend')->count('*');
$books[] = $book;
}
Coz polozi dotazy
SELECT `book`.`id`, `name`, COUNT(`lend`.`id`) AS `countbook`
FROM `book`
LEFT JOIN `lend` ON `book`.`id` = `lend`.`book_id`
WHERE (`user_id` = ?)
GROUP BY `book`.`id`
ORDER BY `lend`.`date`
a
SELECT COUNT(*), `lend`.`book_id`
FROM `lend`
WHERE (`lend`.`book_id` IN (2, 1))
GROUP BY `lend`.`book_id`
a vrati presne to, co chces.
- jtousek
- Člen | 951
Tak dnešní test jsem snad zvládl takže už mám čas. :-) Cainovo řešení je správné – téměř přesně to, co jsem měl na mysli. Trochu více NDB way mi připadá rozložit to na 3 dotazy (níže). Kód mi také připadá o něco málo lépe srozumitelný, ale samozřejmě vše co píšu je pouze věc názoru.
$books = $connection->table('book')->where('lend:user_id', 1)->group('book.id')->order('lend:date');
foreach ($books as $book) {
$book->related('lend')->count('*'); //počet půjčení celkem
$book->related('lend')->where('user_id', 1)->count('*'); //počet mých půjčení
}
- motorcb
- Člen | 552
Ještě další zdokonalení :)
Chtěl bych vypisovat kolik procent z celkové výpůjčky knihy tvoří mé
výpůjčky:
Kniha byla půjčená 10×, já ji měl půjčenou 1× ⇒ 10%
Kniha byla půjčená 1×, já ji měl půjčenou 1× ⇒ 100%
Kniha byla půjčená 3×, já ji měl půjčenou 1× ⇒ 33,33%
A nevím kde mám počítat procenta. Není prasárna počítat procenta
v šabloně?
Nebylo by elegantnější si připravit data v presenteru a v šabloně je
zobrazit?