SimpleAuthenticator v Nette2
- 22
- Člen | 1478
Nejsme si jistý, jestli to dělám správně, může mě někdo zkontrolovat včetně config.neon /připojení k sqlite přes dibi/. Sice to funguje, ale jestli je to správně?
neon
common:
php: # PHP configuration
date.timezone: Europe/Prague
# session.save_path: "%tempDir%/sessions"
zlib.output_compression: yes
default_charset: "UTF-8"
services:
authenticator:
class: SimpleAuthenticator
robotLoader:
run: true
database:
driver: sqlite3
database: %appDir%/db/db.sqlite
profiler: true
lazy: true
run: true
result:
detectTypes: true
bootstrap
...
// Load configuration from config.neon file
$configurator = new Configurator();
$configurator->loadConfig(__DIR__ . '/config.neon');
// Connection to database
$connection = $configurator->container->params->database;
dibi::connect($connection);
// Configure application
$application = $configurator->container->application;
$application->errorPresenter = 'Error';
$application->catchExceptions = FALSE;
$authenticator = new SimpleAuthenticator(array(
'admin' => '****',
));
$user = $configurator->container->user;
$user->setAuthenticationHandler($authenticator);
...
Editoval 22 (26. 5. 2011 22:00)
- Filip Procházka
- Moderator | 4668
Zdá se mi to, nebo nastavuješ 2× authenticator? To je opravdu potřeba?
- bojovyletoun
- Člen | 667
IMHO máš tam „dvakrát“ definici authenticatoru (v neonu a v php)
1. buď použij v neonu toto:
services:
authenticator:
class: SimpleAuthenticator
arguments:
admin: root
2. nebo to v phpčku. A ještě bych to trochu přiupravil. Tímto
způsobem při(e)dáváš authenticator do kontextu usera. Čistší a méně
pracné se mi jeví toto:
$config->cont['authenticator']=$authenticator;
Resp.
nepředávat $authenticator, ale schovat tvorbu authenticatoru do lmbda funkce,
ať je to lazy.
- 22
- Člen | 1478
přesněji řečeno, nezdá se mi:
neon:
services:
authenticator:
class: SimpleAuthenticator
to by tam asi nemuselo vubec byt anebo da se simple autheticator nejak nastavit komplet v neonu?
a pak:
$connection = $configurator->container->params->database;
nedá se k nastavení databáze dostat nějak jinak?
A jakou roli teď hraje Environment? Jsem z toho nějaký zmatený..
Edit: to řešení v configu se mi pozdává víc
Editoval 22 (26. 5. 2011 21:51)
- bojovyletoun
- Člen | 667
- Environment hraje stejnou roli jako dřív. (jen si uprav kód dle toho ) Ale ty přece chceš používat DI? Tak žádné Environment nebudeme používat.
- k přístupu. Vtip je v tom, že k db takhle, jak si psal „uvnitř“
aplikace nebudeš přistupovat (ani přes Environment – viz předchozí
věta). v presenteru to bude takhle
$this->context->params->database
. Ale nevím, k čemu ti budou parametry připojení, asi jsi myslel služby modelu rovnou… - Ano Authenticator se dá nastavit v neonu jak jsem ukázal. Pro pochopení
viz komentář v kódu zde
- pomocí php:
//možnost 1(// hotový objekt )
$authenticator = new SimpleAuthenticator(array('admin' => '****',));
$configurator->container['authenticator']=$authenticator;
//možnost 2 (možnost 2 // pomocí lambda funkce.- objekt se vytvoří, pokud bude potřeba)
$configurator->container['authenticator']=function($context){
return new Authenticator(array('admin'));
} //proměnná $context je aktuální kontejner, klidně ji ignoruj
No, snad už trochu rouzumím DI.
Editoval bojovyletoun (26. 5. 2011 22:06)
- 22
- Člen | 1478
ok, s DI už to chápu, Environment si mažu z hlavy :-) za ukázku nastaveni v neonu díky, ale ještě jak to myslíš s tou DB? ja přece vytvořím lazy spojení v bootstrapu a už se o to nikde v modelech nestarám a do dibi::connect() nějak dostat to pole, za starých časů to bylo:
dibi::connect(Environment::getConfig('database');
Editoval 22 (26. 5. 2011 22:09)
- Tharos
- Člen | 1030
Lazy připojení dibi můžeš provést například v
$application->onStartup
:
// Setup router
$application->onStartup[] = function() use ($application, $configurator) {
dibi::connect($configurator->getContainer()->params['database']);
// zde pokračuje definice rout
};
Tento kód předpokládá, že se někde „nad tím“ provede vytvoření
$configurator
:
// Load configuration from config.neon file
$configurator = new Nette\Configurator;
$configurator->loadConfig(__DIR__ . '/config.neon');
Přesně takto je to momentálně v sandboxu.
Editoval Tharos (26. 5. 2011 22:16)
- Tharos
- Člen | 1030
Samozřejmě nemusíš, v případě lazy připojení je to opravdu jedno a to i z hlediska odchytávání případně vyhozených výjimek (vyhodí se v tom případě totiž až někde v modelové třídě mnohem později). V případě non-lazy připojení by to připojení ale určitě bylo vhodné umístit až za definici errorPresenteru (anebo odchytávat ručně).
Editoval Tharos (26. 5. 2011 22:37)
- Vojtěch Dobeš
- Gold Partner | 1316
Aby bylo dibi
s DI
(tedy vyhnutí se používání
„statického registru dibi
“), tak myslím by to mělo být
košer takto:
$container = $configurator->getContainer();
$container->addService('dibi', function ($container) {
return dibi::connect($container->params['database']);
});
Protože dibi
je jen zkratka pro přístup k
DibiConnection
, které connect
vrací.
- bojovyletoun
- Člen | 667
správná definice Authenticatoru (chyběly namespace předchozí zápis
tvoříl new Authenticator('root',123)
místo
new Authenticator(array('admin'=>'root','eva'=>123)
) –
bylo nutné "vnořit pole
authenticator:
class: Nette\Security\SimpleAuthenticator
arguments:
- # první a jedinný argument
admin: root # je pole
eva: 123
vojtech.dobes mě předběhl – napsal defakto to samé, jen v php (což považuji za srozumitelnější oproti neonu
Databázi bych pořešil takto (pak by bylo spojení dostupné v presenteru
pod $this->context->connection
, za předpokladu, že pracuji
rovnou s databází v presenteru, ale to je jiná věc)
connection: # v sekci services
class: DibiConnection # pozn: dibi::connect() je totéž jako new DibiConnection
arguments1:
- %database% # zde je háček - v neonu se jde odkázat pouze na skalární typ
arguments: #proto musíme nastavení vypsat sem
-
driver: mysql
password: root
Editoval bojovyletoun (26. 5. 2011 23:22)
- Tharos
- Člen | 1030
@bojovyletoun: K čemu přesně slouží ty arguments1
a
arguments
? Já osobně registruji Dibi jako službičku v neonu
takto a funguje to dobře:
common:
services:
dibi:
class: DibiConnection
option:
driver: mysql
charset: utf8
lazy: true
result:
detectTypes: true
production < common:
# zde je vynecháno doupřesnění option pro produkční server
development < common:
services:
dibi:
option:
host: localhost
username: root
password: xxxxx
database: xxxxx
Přijde mi to jako nejjednodušší řešení. V presenteru se pak k
DibiConnection
přistupuje samozřejmě takto:
$this->getContext()->dibi
.
- bojovyletoun
- Člen | 667
arguments je synonymum pro option. arguments1 mělo demonstrovat, že se do argumentů konstruktoru mělo dosadit sekce database z configu (popsáno tam, vyhodí to exception „Parameter ‚database‘ is not scalar.“)
- 22
- Člen | 1478
ještě malý problém v modelu s tímto:
dibi:
class: DibiConnection
option:
driver: sqlite3
database: %appDir%/db/sovereign.sqlite
lazy: true
profiler: true
result:
detectTypes: TRUE
formatDateTime: TRUE
run: true
profiler běží, ale když zavolám dibi z modelu, tak vyskočí Exception
Dibi is not connected, takže jak to má být správně?
dřív stačilo v bootstrapu se připojit přes dibi::connect a dibi bylo
dostupné i v modelu, což by mělo být stejné jako run: true
Tak co zase nevím?
Editoval 22 (30. 5. 2011 20:58)
- bojovyletoun
- Člen | 667
Totéž co zde, musíš parametry odsadit a vložit před ně prázndou pomlčku jako v odkazu. A nebo obalit parametry {{ nebo [[. Vize ne-on.org
- 22
- Člen | 1478
dibi:
class: DibiConnection
arguments:
-
driver: sqlite3
database: %appDir%/db/sovereign.sqlite
lazy: true
profiler: true
result:
detectTypes: TRUE
formatDateTime: TRUE
run: true
..fajn, ale model pořád hlásí: DibiException: Dibi is not connected to
database :-(
Z toho, že v debugBaru je aktivní profiler, usuzuju, že connection je ale
aktivní nebo inicializce nějak částečně proběhla…
Editoval 22 (30. 5. 2011 21:30)
- Jur4
- Člen | 51
Myslím, že problém je v tom, že takhle vytváříš službu jako
instanci DibiConnection a v modelu používáš statické dibi
a
problém je v tom, že pokud to neprošlo přes dibi::connect
tak
dibi
nemá o tom, že je někde vytvořena instance DibiConnection
vuběc ponětí.
Editoval Jur4 (30. 5. 2011 21:44)
- bojovyletoun
- Člen | 667
no vidíš, mě hned napadlo, že staticky to už nevoláš a používáš
DI. Takže buď používej DI ($this->context->dibi->fetch() a nebo si
do configu nahraď class: DibiConnection
za
factory: dibi::connect
( ale DI budeš moci používat taky)
Editoval bojovyletoun (30. 5. 2011 22:11)
- bojovyletoun
- Člen | 667
ve zkratce (pozpátku): (už se mi to nechce dopodrobna popisovat)))
- $this->context->dibi->fetch()
- PresenterFactory::createPresenter : $presenter->setContext($context) (původní context)
- Application::getPresenterFactory->createPresenter
- getPresenterfactory: application->getcontext->presenterfactory : Container::getservice (presenterFactory) (*)
- Application->run
- $configurator->application (viz *)
- configurator->createservicepresenterfactory bere původní context
- configurator::createserviceapplication
- new Configurator;
- 22
- Člen | 1478
jsem se inspiroval v examples a nakonec jsem to udělal takoto:
dibi:
class: DibiConnection
option:
driver: sqlite3
database: %appDir%/db/sovereign.sqlite
lazy: true
profiler: true
result:
detectTypes: TRUE
formatDateTime: TRUE
testimonial:
class: Models\TestimonialModel
arguments: ["@dibi"]
class TestimonialModel extends BaseModel
{
protected $conn;
public function __construct($conn)
{
$this->conn = $conn;
}
public function getColumns()
{
return $this->conn->getDatabaseInfo()->getTable($this->table)->getColumnNames();
}
}
- srigi
- Nette Blogger | 558
@22: neviem ako presne riesis Modely v aplikacii, ale podla mna musi byt otravne pre kazdy Model pridavat sluzbicku so Neonu a pod. Takze ten loader myslim nieco take ako mam vo svojej kucharke:
private $connection = null;
private $models = array();
public function __construct($connection)
{
$this->connection = $connection;
}
public function getModel($model)
{
if (!isset($this->models[$model])) {
$class = 'Model\\' . ucfirst($model);
$this->models[$model] = new $class($this->connection);
}
return $this->models[$model];
}
- bojovyletoun
- Člen | 667
Takhle se mi to líbí, jen bych to upravil tak, aby se v případě
neexistence Model\EntityName vytvořil Model\BaseModel. A samozřejmě
konstruktor upravit
takto function __construct($connection,$EntityName)
- 22
- Člen | 1478
ještě z5 k SA. Poslední Nette už umí expandovat sekci do objektu ArrayHash, ale SimpleAuthenticator očekáva v konstruktoru array, dá se config donutit, aby vyplivl čistý pole? Nebo upravit upravit SimpleAuthenticatoru na ArrayHash?:
common:
services:
authenticator:
class: Nette\Security\SimpleAuthenticator
arguments: ['%users%']
users:
admin: admin
jediný zápis, co mi vrací pole
arguments:
-
admin: admin
což vypadá minimálně divně :-)
Editoval 22 (30. 6. 2011 5:27)
- Patrik Votoček
- Člen | 2221
Nedá ale můžeš řešit továrničkou. Nebo upravit upravit
SimpleAuthenticatoru na
To bylo imho asi lepší
(ale né na ArrayHash ale na Traversable).ArrayHash
?
- Filip Procházka
- Moderator | 4668
Tohle je vskutku problém…
test:
test: [['one', 'two'], 'three', {lala: 'tada'}]
Nette\ArrayHash(1) {
test => Nette\ArrayHash(3) {
0 => Nette\ArrayHash(2) {
0 => "one" (3)
1 => "two" (3)
}
1 => "three" (5)
2 => Nette\ArrayHash(1) {
lala => "tada" (4)
}
}
}
Do teď jsem naivně doufal, že by to třeba mohlo tvořit pole, když to bude mít číselné klíče od nuly…
- Patrik Votoček
- Člen | 2221
22 napsal(a):
no na ArrayHash jsem to přehodil, Traversable?
Nemělo by se to nějak vyřešit v rámci nějakýho pool requestu?
No bazénem se to moc nepořeší… :-) Ale pull requestem bych to řešil… :-)