Jak předat argument připojení

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

Ahoj, rád bych se zeptal, jak na to. Mám:

class Connection

<?php

namespace App\Model;

use Nette\Database\Context;

class Connection
{
    /** @var Context */
    protected $connection;

    /** @var array */
    private $services = [];

    public function __construct(Context $connection)
    {
        $this->connection = $connection;
    }

    /** @return Context */
    public function getConnection()
    {
        if (!isset($this->services['connection'])) {
            $this->services['connection'] = $this->connection;
        }
        return $this->services['connection'];
    }
}

V configu:

- App\Model\Connection

Poté class Rating, kde potřebuju to připojení:

<?php

namespace App\Model;

class Rating {
    private $pripojeni;

    public function __construct(Connection $pripojeni)
    {
        $this->pripojeni = $pripojeni->getConnection();
    }

    public function UpdateRating()
    {
        $this->pripojeni->table('rates')->fetch();
    }
}

A nakonec v jednom presentru v handle metodě:

$update = new \App\Model\Rating($pripojeni);
$update->UpdateRating();

A jde o to, že musím inicializovat tu proměnnou $připojení

Takže nad tu první instanci bych dal něco jako:

$pripojeni = new \App\Model\Connection();

Nevím, jestli je to dobře a co by tato instance měla mít za argument. Dokáže mi někdo pomoct? Děkuji předem.

CZechBoY
Člen | 3608
+
0
-

V presenteru si to injectneš klasicky přes konstruktor nebo přes inject* metodu – žádný new XxxService nedělej pokud je to služba!

K čemu má vlastně sloužit třída Connection?

ps. ještě nějaký odkazy do dokumentace ohledně DI
https://doc.nette.org/…introduction
https://doc.nette.org/…dependencies

Editoval CZechBoY (31. 10. 2017 18:46)

ForestCZE
Člen | 209
+
0
-

CZechBoY napsal(a):

V presenteru si to injectneš klasicky přes konstruktor nebo přes inject* metodu – žádný new XxxService nedělej pokud je to služba!

K čemu má vlastně sloužit třída Connection?

ps. ještě nějaký odkazy do dokumentace ohledně DI
https://doc.nette.org/…introduction
https://doc.nette.org/…dependencies

Z jakého důvodu to nemůže být pomocí new? Není to služba, je to prostě třída, ve které chci zavolat metodu jen v handle metodě.

K čemu slouží třída Connection? Tak abych se připojil k databázi, ne? Pokud ses spletl a chtěl ses zeptat na třídu Rating, tak ok, ale je jedno co bude dělat přesně. Řekněme, že vytáhne data z tabulky a zapíše je do jiné. Ale potřebuji zrealizovat to připojení.

CZechBoY
Člen | 3608
+
0
-

Aha, tak potom – Proc ta trida neni sluzba?

No Connection jen vezme nette Connection a zas to vrati tak moc nechapu k cemu takova vec je…

ForestCZE
Člen | 209
+
0
-

CZechBoY napsal(a):

Aha, tak potom – Proc ta trida neni sluzba?

No Connection jen vezme nette Connection a zas to vrati tak moc nechapu k cemu takova vec je…

Musí být snad každá třída službou?

Tak potřebuju se připojit k databázi, abych s ní mohl pracovat, nevím, co je na tom k nepochopení.

Mysteria
Člen | 797
+
+3
-

Nechtěl jsi spíš napsat něco takovéhleho?

namespace App\Model;

use Nette\Database\Context;

class Rating {
	/** @var Context */
    private $database;

    public function __construct(Context $database)
    {
        $this->database = $database;
    }

    public function updateRating()
    {
        $this->database->table('rates')->fetch();
    }
}

A do config.neon do services přidej App\Model\Rating.

A v presenteru pak budeš mít

/** @var Rating @inject */
public $rating;

$this->rating->updateRating();

Všimni si že nikde není použito ani jedno new, takže nemusíš řešit, co předávat do connection za parametry a podobně. O všechno se za tebe postará DI.

CZechBoY
Člen | 3608
+
0
-

No ze to pripojeni uz sluzba je.
Prosim precti si ty zaklady di.

ForestCZE
Člen | 209
+
0
-

CZechBoY napsal(a):

No ze to pripojeni uz sluzba je.
Prosim precti si ty zaklady di.

Ano, Connection už služba je. Ale Rating není jediná třída, kde Connection používám. A myslel jsem, že se tu nemusíme dohadovat o tom, co je služba a co není. Vycházel jsem z toho, že nechci, aby Rating byla služba a chtěl jsem jenom poradit, jak předat to připojení. Nechápu, co je špatně na vytvoření instance.

CZechBoY
Člen | 3608
+
+1
-

Uplne vsechno :-)
Treba nekdy v budoucnu budes chtit pridat dalsi zavislost pro tridu Rating. Jelikoz uz budes mit na 50 mistech v kodu napsany new Rating($connection) tak to bude docela zabava na dlouhou noc. Pokud bys ale mel sluzbu a pouzival tu tridu jako sluzbu tak bys zmenil jen konstruktor (pripadne smazal cache) a je hotovo.

ps. indikatorem ze by trida mela byt sluzbou mi je to, ze trida ma zavislost na jine sluzbe

ForestCZE
Člen | 209
+
0
-

Mysteria napsal(a):

Nechtěl jsi spíš napsat něco takovéhleho?

namespace App\Model;

use Nette\Database\Context;

class Rating {
	/** @var Context */
    private $database;

    public function __construct(Context $database)
    {
        $this->database = $database;
    }

    public function updateRating()
    {
        $this->database->table('rates')->fetch();
    }
}

A do config.neon do services přidej App\Model\Rating.

A v presenteru pak budeš mít

/** @var Rating @inject */
public $rating;

$this->rating->updateRating();

Všimni si že nikde není použito ani jedno new, takže nemusíš řešit, co předávat do connection za parametry a podobně. O všechno se za tebe postará DI.

Vůbec jsem si tvého příspěvku nevšiml a nakonec jsem to tak udělal. Moc děkuju :)

Jan Mikeš
Člen | 771
+
0
-

CZechBoY napsal(a):

Uplne vsechno :-)
Treba nekdy v budoucnu budes chtit pridat dalsi zavislost pro tridu Rating. Jelikoz uz budes mit na 50 mistech v kodu napsany new Rating($connection) tak to bude docela zabava na dlouhou noc. Pokud bys ale mel sluzbu a pouzival tu tridu jako sluzbu tak bys zmenil jen konstruktor (pripadne smazal cache) a je hotovo.

ps. indikatorem ze by trida mela byt sluzbou mi je to, ze trida ma zavislost na jine sluzbe

Ne tak docela. Rating služba být nemusí, můžeš si vytvořit RatingFactory, která bude tvůj rating vytvářet, a tuto továrnu zaregistruješ jako službu.

class RatingFactory
{
	private $database;


	public function __construct(Context $database)
	{
		$this->database = $database;
	}


	public function create(): Rating
	{
		return new Rating($this->database);
	}
}

Použití v presenteru by pak vypadalo takto:

class Presenter
{
	/** @var RatingFactory @inject */
	public $ratingFactory;


	public function renderDefault()
	{
		$rating = $this->ratingFactory->create();
	}
}

Avšak v tomto případě to nedává smysl, protože třída Rating by opravdu měla být službou, uvádím to tedy pro úplnost řešení a odpověď na otázku Vycházel jsem z toho, že nechci, aby Rating byla služba a chtěl jsem jenom poradit.

Editoval Jan Mikeš (1. 11. 2017 0:37)

CZechBoY
Člen | 3608
+
0
-

@JanMikeš samozřejmě, to už jsem to nechtěl míchat… Dělat repozitář přes továrnu by byla pěkná zvrácenost :-)