Neporušuje NDBT princípy MVC?

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

Zdravím vás,
mohli by ste mi napísať aký je váš názor na to, že NDBT volá databázu zo šablon?
Každý zápis typu $book->autor->name v podstate robí niečo, čo v šablonách podľa všetkých príručiek nemá čo robiť. Podľa MVC by to malo byť v modely, nie?

Dá sa to takto implementovať aj teraz? Nejako si neviem predstaviť ako by taký zložený dotaz vyzeral. Alebo sa trápim zbytočne?

Editoval Čamo (4. 8. 2014 15:31)

Jan Tvrdík
Nette guru | 2595
+
0
-

NDBT zcela úmyslně preferuje stručnost zápisu nad správnou abstrakcí.

Nicméně lze argumentovat, že se jedná prostě o aktivní view, které si data z modelu tahá samo.

japlavaren
Člen | 404
+
0
-

osobne NDTB pouzivam cisto v modeloch. Akonahle totiz nemam 100% istotu, ze budem mat konzistentne data v db, osetrovat to cele v sablonach je prasacina a nocna mora (uz som to zazil).
Preto pouzivam NTDB na skladanie dotazov

<?php
if(...) $result->where(...);
?>

a vytahovanie dat z ref tabuliek

<?php
$data = array_map(function($row){
	return $row->toArray() + array(
		'category' => $row->categoryId ? $row->ref('category')->name : NULL,
	);
}, $result->toArray());

return $data;
?>
Čamo
Člen | 798
+
0
-

Jan Tvrdik
No lenže tá architektúra má svoj význam. Síce je práca s latte fakt elegantná, ale to čo píše Plavaren je fakt.
Japlavaren
Presne tú nočnú moru mám na mysli.
Nemohol by si ten tvoj model trochu rozpísať resp previesť na ten príklad z dokumentácie ako book->ref(autor)->name?

David Grudl
Nette Core | 8228
+
0
-

MVC rozhodně neporušuje, protože s ním nijak nesouvisí. Nejspíš máš na mysli vícevrstvou architekturu. A tady použití NDBT v šabloně může velmi snadno vést k obcházení vrstev.

Jan Tvrdík
Nette guru | 2595
+
0
-

No lenže tá architektúra má svoj význam.

To pochopitelně. Však nikdo ti nebrání použít tolik vrstev abstrakce, kolik dává pro tvoji aplikaci smysl. Můžeš se například podívat (nebo opatrně vyzkoušet) na Nextras ORM (představovací video), které implementuje nad NDBT ORM. Vynechání určitých vrstev je možnost, nikoliv nutnost.

Čamo
Člen | 798
+
0
-

DG
Netrúfam si s tebou polemizovať o tom čo je to MVC a už vôbec nie o multitier archytektúre. To čitam prvý krát. Ale teda mi povedz ak môžeš v čom je moja predstava MVC mylná:
Model-spravuje data oboma smermi
Controler-určuje čo sa bude diať podľa požiadavky uživateľa
View-zodpovedá za formátovanie dát, ktoré mu dodal contoler.
Prečo by mal view komunikovať s modelom. Jedným z hlavných argumetov, je presne to čo napísala plavaren. Keď potrebujem zmeniť model siahnem presne k nemu. Podľa mňa sa to takto triešti.

Jan Tvridk
Prečo odporúčaš miesto NDBT Dibi? Máš to v podpise.

Editoval Čamo (5. 8. 2014 11:39)

Šaman
Člen | 2666
+
0
-

@Čamo: Ale NDbT není model! Je to jen databázová vrstva, nad kterou si můžeš vytvořit klidně celé ORM, nebo architekturu modelu s API, jaké uznáš za vhodné. To znamená, že všechno načítání dat může být v modelu a do view předáš opravdu jen připravená data, třeba jao prostý array. Proto David psal, že samotná NDb s problematikou MVC nemá přímou souvislost. Ukázku řešení velmi jednoduchého modelu nad NDb mám třeba tady. Ano, i tady se dá přímo v modelu traverzovat mezi entitama pomocí vazeb, ale pokud to budeš chápat jako lite verzi ORMu, tak entita je objekt, který zná své vazby a ve view tedy nezasahuješ do modelu, ale jen se ptáš objektu (entity), kterou ti model předal. Např. $book->author->name.

A co se týče Dibi vs. NDb(T), tak se o tom dá něco dohledat na fóru. Tahle otázka vždycky trochu zčeří vody, protože každý máme své oblíbené a každý to svoje začne hned hájit. Taková typická flamewarová otázka, jen specifická pro Nette fórum :)

Editoval Šaman (4. 8. 2014 21:08)

japlavaren
Člen | 404
+
0
-

Čamo napsal(a):
Japlavaren
Presne tú nočnú moru mám na mysli.
Nemohol by si ten tvoj model trochu rozpísať resp previesť na ten príklad z dokumentácie ako book->ref(autor)->name?

Najprv troska teorie, ako to robim ja:

  1. zasadne vymenonavam stlpce, ktore chcem v z modelu previest. s cachomvanim stlpcov, ktore sa maju vypisat som mal problem a chcem to mat plne pod kontrolou
  2. na tabulky mam interface. ITableName::TABLE obsahuje nazov tabulky + mam tam konstanty zoradovania
    • ak je nazov modelu zhodny s tabulkou, implementujem interface ITableName (v modeli pouzivam self::TABLE)
    • v ostatnych modeloch pouzivam ITableName::TABLE
    • ak potrebujem zmenit hocico suvisiace s tabulkou, dam len vyhladat interface a viem, kde ju mam pouzitu

IBookTable.php (podobnym sposobom su napisane i ostatne I*Table)

<?php

namespace App\Model;

interface IBookTable
{
	const TABLE = 'book';

	const SORT_NAME = 'name';
	const SORT_NAME_DESC = '-name';
	const SORT_PRICE = 'price';
	const SORT_PRICE_DESC = '-price';
}

?>

BookModel.php

<?php

namespace App\Model;

class BookModel extends BaseModel implements IBookTable
{
	/** @var array */
	protected $sortOptions = array(
		self::SORT_NAME,
		self::SORT_NAME_DESC,
		self::SORT_PRICE,
		self::SORT_PRICE_DESC,
	);


	/**
	 * @param array $filter
	 * @param string $sort
	 * @param int $limit
	 * @param int|null $offset
	 * @return array
	 */
	public function getUsers(array $filter, $orderBy, $limit, $offset = NULL){
		if(!in_array($sort, $this->sortOptions)) {
			$this->log(new \InvalidArgumentException("Invalid sort value '$sort'"));
			return array();
		}

		// $this->db je z BaseModel typu Database\Context predana cez BaseModel::__construct()
		$result = $this->db->table(self::TABLE)
			->select('id, authorId, name, price, description')
			->order($this->processSort($sort))
			->limit($limit, $offset);

		if(isset($filter['name']) && $filter['name']) $result->where('name LIKE ?', "%$filter[name]%"));

		return array_map(function($row) {
			return $row->toArray() + array(
				'author' => $row->authorId ? $row->ref(IAuthorTable::TABLE)->name : NULL, // osetrenie pre nepovinne cudzie kluce
			);
		}, $result->fetchAll());
	}


	// funkcia sa nachadza v BaseModel
	/**
	 * convert initial minus to DESC attribute
	 * @param string $sort
	 * @return string
	 */
	protected function processSort($sort) {
		if (strpos($sort, '-') === 0) {
			return substr($sort, 1) . ' DESC';
		} else {
			return $sort;
		}
	}
}

?>

pisane z hlavy, moze obsahovat chyby

Editoval japlavaren (4. 8. 2014 21:14)

Čamo
Člen | 798
+
0
-

Šaman, Plavaren
Ďakujem za snahu.
Ako tak nad tým uvažujem, tak v podstate z toho modelu tak či tak dostanem nejaké pole a budem s ním pracovať podobne ako doteraz. Takže ak sa udeje nejaká významná zmena modelu, tak sa to aj tak premietne do tej šablony.

Ešte raz díky všetkým za námahu.

Editoval Čamo (4. 8. 2014 22:47)

Jan Tvrdík
Nette guru | 2595
+
0
-

Jan Tvridk
Prečo odporúčaš miesto NDBT Dibi? Máš to v podpise.

Jednak ten podpis je z doby, kdy NDBT obsahovalo spoustu chyb (v Nette 2.0, teď už je to snad v klidu). Jednak má dibi mnohem mocnější jazyk na skládání složitých dotazů. Není prostě možné nahradit hromadu modifikátorů jedním otazníkem a očekávat, že to bude umět to samé. Neumí. A to i přesto, že se NDB pomocí temné (a nespolehlivé) magie snaží.