DB connection v modelu – jak na to?
- Mára98
- Člen | 47
Dobrý den,
vytvořil jsem si v modelu třídu Book
, která ve svém
konstruktoru bere ID, na základě kterého se inicializuje vnitřní stav
instance této knihy daty z databáze:
class Book
{
...
public function __construct($id)
{
// Získá knihu na základě ID
$book = $this->database->table('BOOKS')
->where('id = ?', $id)
->fetch();
// Inicializuje vnitřní stav objektu
$this->id = $id;
$this->name = $book->name;
$this->description = $book->description;
}
...
}
Problém je v tom, že netuším, jak si vyžádat databázové spojení v modelu. V presenteru pak třídu používám nějak takto:
final class BooksPresenter extends BasePresenter
{
public function renderDefault($id)
{
// Získá knihu na základě předaného ID
$book = new Book($id);
// Předá hodnoty do view
$this->template->book = $book;
}
}
Dočetl jsem se, že svou třídu musím do configu uvést jako službu a pak si jí vyžádat. Absolutně ale nepobírám, jak na to. Předem děkuji za jakoukoliv pomoc.
- nightfish
- Člen | 519
Ve třídě Book
mícháš dohromady dvě věci – samotná
data a jejich získávání z databáze. Lepší je tuto funkčnost rozdělit
do více tříd.
Třída Book bude jen přepravka na data.
namespace App\Model;
final class Book {
private $id;
private $name;
private $description;
public function __construct(int $id, string $name, string $description) {
$this->id = $id;
$this->name = $name;
$this->description = $description;
}
// + gettery, aby ses k datum dostal v šabloně
}
Dále pak vytvoříš třídu, která má na starosti načtení knihy z databáze podle ID.
namespace App\Model;
final class BookRepository {
private $database;
public function __construct(\Nette\Database\Connection $database) {
$this->database = $database;
}
public function get(int $id): Book {
// Získá knihu na základě ID
$row = $this->database->table('BOOKS')
->where('id = ?', $id)
->fetch();
return new Book($row->id, $row->name, $row->description);
}
}
Tuto třídu zaregistruješ do config.neon jako službu:
services:
bookRepository:
class: App\Model\BookRepository
Následně si v presenteru vyžádáš instanci
BookRepository
:
final class BooksPresenter extends BasePresenter
{
/** @var \App\Model\BookDepository */
private $bookRepository;
public function __construct(\App\Model\BookRepository $bookRepository) {
$this->bookRepository = $bookRepository;
}
public function renderDefault(int $id)
{
// Získá knihu na základě předaného ID
$book = $this->bookRepository->get($id);
// Předá hodnoty do view
$this->template->book = $book;
}
}
- Mára98
- Člen | 47
Pokusil jsem se to naprogramovat, ale hlásí mi to
Call to undefined method Nette\Database\Connection::table()
.
Netušíte, co je špatně? Jsem už opravdu zoufalý.
config.neon:
#
# WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
# https://nette.org/en/security-warning
#
parameters:
application:
errorPresenter: Error
mapping:
*: App\*Module\Presenters\*Presenter
session:
expiration: 14 days
database:
dsn: '---'
user: ---
password: ---
options:
lazy: yes
services:
- App\Model\UserManager
router: App\RouterFactory::createRouter
bookRepository:
class: App\Repository\BookRepository
Book.php:
<?php
// Namespace
namespace App\Model;
/**
* Book je třída sloužící k ukládání informací o
* učebnicích.
*/
class Book
{
// ID učebnice
public $id;
// Název učebnice
public $name;
// Popis učebnice
public $description;
/**
* Konstruktor učebnice.
*/
public function __construct($id, $name, $description)
{
// Inicializuje vnitřní stav objektu
$this->id = $id;
$this->name = $name;
$this->description = $description;
}
}
BookRepository.php:
<?php
// Namespace
namespace App\Repository;
// Usingy
use App\Model;
/**
* BookRepository slouží k načtení knih z databáze
*/
class BookRepository
{
// Databázové spojení
private $database;
/**
* Konstruktor repositáře.
*/
public function __construct(\Nette\Database\Connection $database)
{
$this->database = $database;
}
/**
* Získá učebnici s předaným ID
* @param int $id ID učebnice
* @return Book Kniha s daným ID
*/
public function get(int $id) : Book
{
// Získá knihu na základě ID
$row = $this->database->table('BOOKS')
->where('id = ?', $id)
->fetch();
// Vrátíme novou knihu
return new Book($row->id, $row->name, $row->description);
}
}
BooksPresenter.php:
<?php
// Namespace
namespace App\Presenters;
// Usingy
use App\Model\Book;
/**
* BooksPresenter je třída zajišťující správné zobrazení
* obsahu knih
*/
final class BooksPresenter extends BasePresenter
{
private $bookRepository;
public function __construct(\App\Repository\BookRepository $bookRepository) {
$this->bookRepository = $bookRepository;
}
/**
* Defaultní render metoda.
* @param int $id ID knihy, kterou budeme zobrazovat
*/
public function renderDefault($id)
{
// Získá knihu na základě předaného ID
$book = $this->bookRepository->get($id);
// Předá hodnoty do view
$this->template->book = $book;
}
}
Editoval Mára98 (19. 7. 2019 12:52)
- Šaman
- Člen | 2667
Ty si v konstruktoru žádáš Nette\Database\Connection
, ta
opravdu žádnou table
nezná. Nad connection se použivá prosté
->query()
. Ty potřebuješ Nette\Database\Context
,
což je takové rozšíření.
Dokumentace:
Connection: https://doc.nette.org/…atabase/core
Context: https://doc.nette.org/…ase/explorer
Editoval Šaman (19. 7. 2019 13:23)