QuickStart – Odkaz na přihlášení (SignPresenter)
- kotrvecko
- Člen | 20
Ahojky, jedu podle návodu:
Odkaz na přihlášení
Jak se vlastně dostaneme na přihlašovací stránku? Není zde žádný odkaz,
který by na ni vedl. Tak si ho tedy přidáme do šablony
app/presenters/templates/@layout.latte. Pokuste se najít vhodné místo,
může to být téměř kdekoliv.
<ul class="navig">
<li><a n:href="Homepage:">Články</a></li>
{if $user->loggedIn}
<li><a n:href="Sign:out">Odhlásit</a></li>
{else}
<li><a n:href="Sign:in">Přihlásit</a></li>
{/if}
</ul>
Pokud není uživatel přihlášen, zobrazí se odkaz „Přihlásit“.
V opačném případě se zobrazí odkaz „Odhlásit“.
Tuto akci také doplníme do SignPresenter.
Kam to mám vložit do SignPresenter?
Hlásí mi to chybu: syntax error, unexpected ‚<‘, expecting function
(T_FUNCTION)
File: …\nette-blog\app\presenters\SignPresenter.php:11
<?php
2:
3: namespace App\Presenters;
4:
5: use Nette;
6: use Nette\Application\UI\Form;
7:
8:
9: class SignPresenter extends Nette\Application\UI\Presenter
10: {
11: <ul class="navig">
12: <li><a n:href="Homepage:">Články</a></li>
13: {if $user->loggedIn}
14: <li><a n:href="Sign:out">Odhlásit</a></li>
15: {else}
?>
Děkuji za radu.
Editoval kotrvecko (9. 10. 2016 12:59)
- ViPEr*CZ*
- Člen | 818
No myšleno je tuto akci Sign:out
Tedy do Presenteru je nutné přidat třeba
public function actionOut() {
$this->getUser()->logout();
$this->redirect("Homepage:default");
}
Pak ten link bude v šabloně teprve aktivní/reálný. Jinak se tam místo url bude generovat nějakej error… jako, že neexistuje právě ta daná akce.
Editoval ViPEr*CZ* (9. 10. 2016 13:08)
- Jan Mikeš
- Člen | 771
Ten kód dej do latte šablony, máš to tam napsáno ;)
app/presenters/templates/@layout.latte
Tím může to být téměř kdekoliv
je myšleno kdekoliv v té
šabloně
@ViPEr*CZ* pokud by signpresenter existoval, tak by se linky normálně vygenerovaly bez erroru
Editoval Lexi (9. 10. 2016 13:09)
- kotrvecko
- Člen | 20
Aha, takže když to dám pryč a Sign:out už tam mám, tak mám problém s authenticatorem.
Chyba:
Service ‚security.user‘: Multiple services of type
Nette\Security\IAuthenticator found: security.authenticator,
28_App_Model_UserManager. If you want to overwrite service
security.authenticator, give it proper name.
…\eds-www\nette-blog\app\bootstrap.php:20 source
Nette\Configurator->createContainer()
<?php
10: $configurator->setTimeZone('Europe/Prague');
11: $configurator->setTempDirectory(__DIR__ . '/../temp');
12:
13: $configurator->createRobotLoader()
14: ->addDirectory(__DIR__)
15: ->register();
16:
17: $configurator->addConfig(__DIR__ . '/config/config.neon');
18: $configurator->addConfig(__DIR__ . '/config/config.local.neon');
19:
20: $container = $configurator->createContainer();
21:
22: return $container;
?>
- kotrvecko
- Člen | 20
Lexi napsal(a):
Ten kód dej do latte šablony, máš to tam napsáno ;) app/presenters/templates/@layout.latte
Tímmůže to být téměř kdekoliv
je myšleno kdekoliv v té šabloně@ViPEr*CZ* pokud by signpresenter existoval, tak by se linky normálně vygenerovaly bez erroru
V šabloně @layout.latte to mám, ale pod tím je ještě napsáno „Tuto akce také doplníme do SignPresenter.“ Což mě zmátlo.
- kotrvecko
- Člen | 20
config.neon
<?php
# 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
services:
- App\Model\UserManager
- App\Forms\FormFactory
- App\Forms\SignInFormFactory
- App\Forms\SignUpFormFactory
router: App\RouterFactory::createRouter
security:
users:
admin: secret # user 'admin', password 'heslo'
?>
config-local.neon
<?php
parameters:
database:
dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
user: root
password:
options:
lazy: yes
?>
Editoval kotrvecko (9. 10. 2016 13:44)
- kotrvecko
- Člen | 20
Lexi napsal(a):
Ukaž tvůj config.neon a config.local.neon
Vím, že mé configy nestojí za nic, ale teprve začínám. :-D Kdyby se ti v nich něco nezdálo, tak si ráda nechám poradit. :-) Pro jistotu ještě posílám bootstrap.php.
<?php
require __DIR__ . '/../vendor/autoload.php';
$configurator = new Nette\Configurator;
//$configurator->setDebugMode('23.75.345.200'); // enable for your remote IP
$configurator->enableDebugger(__DIR__ . '/../log');
$configurator->setTimeZone('Europe/Prague');
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig(__DIR__ . '/config/config.neon');
$configurator->addConfig(__DIR__ . '/config/config.local.neon');
$container = $configurator->createContainer();
return $container;
?>
- kotrvecko
- Člen | 20
ViPErCZ napsal(a):
Tohle ještě pošli: App\Model\UserManager
V tom jsem ještě nic nedělala.
<?php
namespace App\Model;
use Nette;
use Nette\Security\Passwords;
/**
* Users management.
*/
class UserManager implements Nette\Security\IAuthenticator
{
use Nette\SmartObject;
const
TABLE_NAME = 'users',
COLUMN_ID = 'id',
COLUMN_NAME = 'username',
COLUMN_PASSWORD_HASH = 'password',
COLUMN_EMAIL = 'email',
COLUMN_ROLE = 'role';
/** @var Nette\Database\Context */
private $database;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
}
/**
* Performs an authentication.
* @return Nette\Security\Identity
* @throws Nette\Security\AuthenticationException
*/
public function authenticate(array $credentials)
{
list($username, $password) = $credentials;
$row = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_NAME, $username)->fetch();
if (!$row) {
throw new Nette\Security\AuthenticationException('The username is incorrect.', self::IDENTITY_NOT_FOUND);
} elseif (!Passwords::verify($password, $row[self::COLUMN_PASSWORD_HASH])) {
throw new Nette\Security\AuthenticationException('The password is incorrect.', self::INVALID_CREDENTIAL);
} elseif (Passwords::needsRehash($row[self::COLUMN_PASSWORD_HASH])) {
$row->update([
self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
]);
}
$arr = $row->toArray();
unset($arr[self::COLUMN_PASSWORD_HASH]);
return new Nette\Security\Identity($row[self::COLUMN_ID], $row[self::COLUMN_ROLE], $arr);
}
/**
* Adds new user.
* @param string
* @param string
* @param string
* @return void
* @throws DuplicateNameException
*/
public function add($username, $email, $password)
{
try {
$this->database->table(self::TABLE_NAME)->insert([
self::COLUMN_NAME => $username,
self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
self::COLUMN_EMAIL => $email,
]);
} catch (Nette\Database\UniqueConstraintViolationException $e) {
throw new DuplicateNameException;
}
}
}
class DuplicateNameException extends \Exception
{}
?>
- Jan Mikeš
- Člen | 771
Už to vidím, nette se nelíbí to, že máš 2 implementace
authenticatoru, jednu aktivuješ tím, že máš v configu sekci
security
a druhou, protože máš u tvého App\Model\UserManager
implements Authenticator
, buď tedy zruš to
implements ...
, nebo celou sekci security:
z configu.
- kotrvecko
- Člen | 20
Lexi napsal(a):
Už to vidím, nette se nelíbí to, že máš 2 implementace authenticatoru, jednu aktivuješ tím, že máš v configu sekci
security
a druhou, protože máš u tvého App\Model\UserManagerimplements Authenticator
, buď tedy zruš toimplements ...
, nebo celou sekcisecurity:
z configu.
Děkuji. Po zrušení implements v UserManager to házelo další chyby, tak jsem místo toho smazala security v configu. Akorát na to bylo napojeno celé přihlášení, které nefunguje, tak si s tím ještě zkusím pohrát.
- kotrvecko
- Člen | 20
kotrvecko napsal(a):
Lexi napsal(a):
Už to vidím, nette se nelíbí to, že máš 2 implementace authenticatoru, jednu aktivuješ tím, že máš v configu sekci
security
a druhou, protože máš u tvého App\Model\UserManagerimplements Authenticator
, buď tedy zruš toimplements ...
, nebo celou sekcisecurity:
z configu.Děkuji. Po zrušení implements v UserManager to házelo další chyby, tak jsem místo toho smazala security v configu. Akorát na to bylo napojeno celé přihlášení, které nefunguje, tak si s tím ještě zkusím pohrát.
Takže po smazání security v config.neon mám stále chybu odkazující na $container:
Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘
not found.
…\eds-www\nette-blog\app\bootstrap.php:20 source
Nette\Configurator->createContainer()
<?php
10: $configurator->setTimeZone('Europe/Prague');
11: $configurator->setTempDirectory(__DIR__ . '/../temp');
12:
13: $configurator->createRobotLoader()
14: ->addDirectory(__DIR__)
15: ->register();
16:
17: $configurator->addConfig(__DIR__ . '/config/config.neon');
18: $configurator->addConfig(__DIR__ . '/config/config.local.neon');
19:
20: $container = $configurator->createContainer();
21:
22: return $container;
?>
- Altimit
- Člen | 82
to je v base app po nainstalování a já v tom problém nevidím..
Spíše toto: Chlape nepiš html do presenteru na to máš šablony..
viz toto:
<?php
namespace App\Presenters;
use Nette;
use Nette\Application\UI\Form;
class SignPresenter extends Nette\Application\UI\Presenter
{
<ul class="navig">
<li><a n:href="Homepage:">Články</a></li>
{if $user->loggedIn}
<li><a n:href="Sign:out">Odhlásit</a></li>
{else}
?>
podle mně se musíš podívat jak se to všechno píše.. tudíž projet
dokumentaci, podívat se když tak na zdejší fórum.
pokud chceš mít tady tohle tak to se píše do html a.k.a.
souborů .latte
<nav class="z-depth-4 cyan" role="navigation">
<div class="nav-wrapper container">
<ul class="hide-on-med-and-down">
<li><a class="waves-effect" href="/">Domů</a></li>
<li><a class="waves-effect" href="{$presenter->link(':Front:Home:aboutus')}">O Projektu</a></li>
<li><a class="waves-effect" href="{$presenter->link(':Front:Blog:default')}">Novinky</a></li>
{if $user->loggedIn}
<ul class="right hide-on-med-and-down">
{if $user->isInRole('admin')}<li><a class="waves-effect" href="#">Administrace</a></li>{else}{/if}
{if $user->isInRole('teacher')}<li><a class="waves-effect" href="{$presenter->link(':Teacher:Home:default')}">Učitelská sekce</a></li>{else}{/if}
<li><a class="waves-effect" href="{$presenter->link(':Class:Home:default')}">Třída</a></li>
<li><a class="waves-effect" href="#">Účet</a></li>
<li><a class="waves-effect" href="{$presenter->link(':Front:Sign:out')}">Odhlásit</a></li>
</ul>
{else}
<ul class="right hide-on-med-and-down">
<li><a href="{$presenter->link(':Front:Sign:up')}">Registrovat</a></li>
<li><a href="{$presenter->link(':Front:Sign:in')}">Přihlásit</a></li>
</ul>
{/if}
</ul>
<ul id="nav-mobile" class="side-nav" style="transform: translateX(-100%);">
<li><a id="logo-container" href="/" style="text-align:center;" class="cyan-text accent-4">Školní zápisy</a></li>
<li class="divider"></li>
<li>{control menu}</li>
<li><a href="/">Domů</a></li>
<li><a href="{$presenter->link(':Front:Home:aboutus')}">O Projektu</a></li>
<li><a href="{$presenter->link(':Front:Blog:default')}">Novinky</a></li>
<li class="divider"></li>
{if $user->loggedIn}
<li><a href="{$presenter->link(':Class:Home:default')}">Třída</a></li>
<li><a href="#">Účet</a></li>
<li><a href="{$presenter->link(':Front:Sign:out')}">Odhlásit</a></li>
{else}
<li><a href="{$presenter->link(':Front:Sign:in')}">Přihlást</a></li>
<li><a href="{$presenter->link(':Front:Sign:up')}">Registrovat</a></li>
{/if}
</ul>
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
</div>
</nav>
toto mám v @menu.latte
- kotrvecko
- Člen | 20
ViPErCZ napsal(a):
No píše to, že to nevidí tuto třídu: Class App\Model\UserManager
Zkus vymazat ještě cache jestli tato chyba stále zůstane.
Ahoj, zkusila jsem vymazat cache v temp / cachce / Nette.Configurator, ale problém je stále stejný.
Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
Na fóru jsem našla jen řešení vymazat v config.neon řádek v services: App\Model\UserManager a App\Forms\SignInFormFactory, což mi nepomohlo. Zkusila jsem vrátit všechny kroky z článku Autentifikace, ale už se té chyby nemůžu zbavit. Ráda bych porkačovala dál a zkusila vlastní autentifikátor, ale co s tou chybou?
- Jan Mikeš
- Člen | 771
No někde v configu registruješ službu App\Model\UserManager
ale robot loader ji nedokáže najít, protože jsi tu třídu smazala.
Zkontrolu všechny .neon configy, jestli tam tu třídu nemáš zaregistrovanou,
nebo jestli jiná zaregistrovaná služba tuto třídu nevyžaduje jako
závislost. (konstruktory, inject..).
Pokud jsi si jistá, že třídu nehledáš, smazej pro jistotu ještě jednou
cache (nestačí smazat Nette.Configurator, ale celou složku cache
v adresáři temp
).
Je velmi důležité číst chybové hlášky a pochopit co znamenají, pak
můžeš systematicky postupovat a chybu hledat.
Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
Jak jsem popisoval na začátku, Nette vytvořilo službu s názvem
27_App_Model_UserManager
, v této službě se používá třída
App\Model\UserManager
ale Nette ji nemůže najít. Takže buď
můžeš zrušit vytváření této služby, nebo si vytvořit (zpětně
vrátit) tuto třídu.
- kotrvecko
- Člen | 20
Lexi napsal(a):
No někde v configu registruješ službu
App\Model\UserManager
ale robot loader ji nedokáže najít, protože jsi tu třídu smazala.
Zkontrolu všechny .neon configy, jestli tam tu třídu nemáš zaregistrovanou, nebo jestli jiná zaregistrovaná služba tuto třídu nevyžaduje jako závislost. (konstruktory, inject..).
Pokud jsi si jistá, že třídu nehledáš, smazej pro jistotu ještě jednou cache (nestačí smazat Nette.Configurator, ale celou složkucache
v adresářitemp
).
Je velmi důležité číst chybové hlášky a pochopit co znamenají, pak můžeš systematicky postupovat a chybu hledat.
Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
Jak jsem popisoval na začátku, Nette vytvořilo službu s názvem27_App_Model_UserManager
, v této službě se používá třídaApp\Model\UserManager
ale Nette ji nemůže najít. Takže buď můžeš zrušit vytváření této služby, nebo si vytvořit (zpětně vrátit) tuto třídu.
Ahoj Lexi, ráda tě tu vidím. Jelikož mám málo času, tak jsem přistoupila k radikálnímu řešení a smazala celý projekt a jdu od začátku. Tohle však nemůžu dělat pořád, když už budu s projektem dál. Jak píšeš, musím se naučit pochopit chybové hlášky. Autentifikaci v quickstartu už vynechám a zkusím udělat vlastní autentifikátor podle článku Přihlašování a oprávnění. Snad nenarazím na stejnou chybu s UserManagerem.
Když už tě tu mám, tak mi určitě poradíš s požadavky z checker, protože nechci narážet na zbytečné chyby. Vykřičník mám u Fileinfo extension, PDO SQLite extension, Memcache extension, Fileinfo extension or mime_content_type() a Intl extension. Jak to můžu opravit? :-)
- Mysteria
- Člen | 797
Musíš si povolit potřebná rozšíření pro PHPčko. Konfiguraci najdeš
v souboru PHP.ini (bude tam, kam jsi si nainstaloval PHP).
Zajímá tě tahle část, kdy středník na začátku řádku znamená, že je
rozšíření zakázáno:
;extension=php_bz2.dll
extension=php_curl.dll
extension=php_fileinfo.dll
extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_gmp.dll
;extension=php_intl.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_ldap.dll
extension=php_mbstring.dll
;extension=php_exif.dll ; Must be after mbstring as it depends on it
;extension=php_mysql.dll
extension=php_mysqli.dll
;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client
extension=php_openssl.dll
;extension=php_pdo_firebird.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_odbc.dll
;extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
;extension=php_pgsql.dll
;extension=php_pspell.dll
;extension=php_shmop.dll
extension=php_ftp.dll
Stačí smazat středníky před požadovanými rozšířeními, na které Checker upozorňuje a restartovat web server.
- Jan Mikeš
- Člen | 771
@kotrvecko na windowsu je to s instalací trošku komplikovanější, každopádně jak jsem psal, bez memcache se 100% obejdeš a intl obsahuje sadu funkcí pro práci s cizojazyčnými funkcemi atd. takže pokud se nechystáš například konvertovat azbuku pomocí webalize() tak ti toto rozšíření chybět nebude.
- n.u.r.v.
- Člen | 485
Lexi napsal(a):
@kotrvecko memcache extension pravděpodobně potřebovat nebudeš, takže zrovna tuhle extension můžeš ignorovat. Fileinfo ti pomůže při uploadování souborů a PDO SQLite je pro sqlite databáze (to se může hodit, některé samostatné balíčky sqlite využívají).
Nevyžaduje náhodou nette PDO SQLite pro cache? Tedy je to „povinné“?