Dotaz ohledně změny údajů uživatele – okamžitá změna
- tatyalien
- Člen | 239
V nette zatím jen pár dní zkouším různé věci, rozchodil jsem si acl a teď zkouším rozchodit změny údajů přihlášeného uživatele a nějak se v tom ztrácím.. Uživatel se mě do databáze zapíše (změny), ale potřeboval bych to, aby se to projevilo rovnou i na přihlášeném uživateli…
Presenter:
<?php
final class Admin_EditUserPresenter extends Admin_SecuredPresenter
{
protected function createComponentEditName($name)
{
/* získání dat o uživateli */
$user = NEnvironment::getUser();
$this->template->user = ($user->isLoggedIn()) ? $user->getIdentity() : null;
/* pro kontrolu v šabloně $loggedUser->isAllowed('Admin_PagePresenter', $user->roles) */
$userPole = NEnvironment::getUser()->getIdentity()->getData();
$user_id = $user->getIdentity()->getId();
$user_name = $userPole[0];
$user_email = $userPole[1];
$user_password = $userPole[2];
$msg = 'Jméno musí obsahovat VELKÁ a malá písmena!';
$form = new NAppForm($this, $name);
/* nastaveni identifikace ve form */
$form->getElementPrototype()->id = 'editace-jmena';
$form->addText('email', 'E-mail')
->setDefaultValue($user_email)
->addRule(NForm::FILLED, "Vyplňte email.")
->addRule(NForm::EMAIL, 'Vyplňte platný email');
->addRule(callback('app\models\UserModel', 'existujeEmailVdb'),
"Tento email je již použit, prosím zvolte jiný email.", $user_id);
$form->addText('name', 'Jméno:')
->setDefaultValue($user_name)
->addRule(NForm::FILLED, 'Prosím zadajte jméno.')
//->addRule(array('CustomFormValidators','isInDatabase'), "Zadejte unikátní e-mail")
->addRule(NForm::MIN_LENGTH, 'Jméno musí mít minimálně %d znaků', 4)
->addRule(NForm::REGEXP, $msg, '/[A-Z]+/')
->addRule(NForm::REGEXP, $msg, '/[a-z]+/')
->addRule(callback('app\models\UserModel', 'existujeJmenoVdb'),
"Toto jméno je již použito, prosím zvolte jiné jméno.", $user_id);
$form->addProtection('Prosím odešlet přihlašovací údaje znovu (vypršela platnost tzv. bezpečnostního tokenu).');
$form->addSubmit('send', 'Uložit');
// tlačítko přeskočí veškerou validaci
$form->addSubmit('delete', 'Vymazat')->setValidationScope(NULL);;
$form->onSubmit[] = array($this, 'editNameSubmitted');
return $form;
}
public function editNameSubmitted($form)
{
/* pokud je vše vyplněno, pokusím se uložit změny uživatele */
try {
if($form['delete']->isSubmittedBy()) {
// vrátím se zpět na editaci
//$this->flashMessage('Vyresetování formuláře!');
$this->redirect(":Admin:EditUser:default");
} else {
// akce co se má udělat
$values = $form->getValues();
// // EditUser models/UserEditaceModel
$editace = new EditUser;
$editace->name = $values['name'];
$editace->email = $values['email'];
// zjištění ID uživatele
$user = NEnvironment::getUser();
$user_id = $user->getIdentity()->getId();
// editace v DB
$editace->edit($editace, $user_id);
$this->redirect(':Admin:EditUser:save');
}
}
/* Jakou exception sem dát? */
catch (NIOException $e) {
$form->addError($e->getMessage());
}
}
...
?>
Zde nevím jakou exception volat, ale to není to nejhorší..
Model (models/UserEditaceModel):
<?php
class EditUser extends DibiRow
{
public function __construct($arr = array())
{
parent::__construct($arr);
}
public function edit(EditUser $data, $id)
{
return dibi::query('UPDATE [users] SET', (array) $data, 'WHERE [id]=%i', $id);
}
public function save(EditUser $data)
{
return dibi::query('INSERT INTO [users]', (array) $data);
}
}
?>
Data propisující do šablony řeším pomocí BasePresenter:
<?php
abstract class BasePresenter extends NPresenter
{
protected function beforeRender()
{
$this->template->viewName = $this->view;
$this->template->root = dirname(APP_DIR);
$user = NEnvironment::getUser();
$this->template->user = ($user->isLoggedIn()) ? $user->getIdentity() : NULL;
/* pro kontrolu v šabloně $loggedUser->isAllowed('Admin_PagePresenter', $user->roles) */
$this->template->loggedUser = $user;
// pokud je uživatel přihlášený, dodám si údaje do šablony
if ($user->isLoggedIn()) {
$userPole = $user->getIdentity()->getData();
$this->template->user_id = $user->getIdentity()->getId();
$this->template->user_name = $userPole[0];
$this->template->user_email = $userPole[1];
$this->template->user_password = $userPole[2];
} else {
$this->template->user_id = '';
$this->template->user_name = '';
$this->template->user_email = '';
$this->template->user_password = '';
}
$a = strrpos($this->name, ':');
if ($a === FALSE) {
$this->template->moduleName = '';
$this->template->presenterName = $this->name;
} else {
$this->template->moduleName = substr($this->name, 0, $a + 1);
$this->template->presenterName = substr($this->name, $a + 1);
}
}
}
?>
- RadH
- Člen | 23
Zkus v metodě editNameSubmitted použít po editaci uživatele následující kód:
<?php
// editace v DB
$editace->edit($editace, $user_id)
if (dibi::getAffectedRows()) {
if ($user->identity instanceof IIdentity) {
$user->identity->name = $values['name'];
$user->identity->email = $values['email'];
}
}
?>
U exception bych zachytával DibiException. Rozhodně bych nevypisoval $e->getMessage(), ale na produkci vypsal info o neúspěchu uložení do DB, v debug módu si $e->getMessage() vypsat můžeš pro lepší lazení.
Jinak tento kód ti vyvolá Fatal Error pokud není uživatel přihlášen a není vytvořena identita a uživatel dostane hlášení „Call to a member function getId() on a non-object“.
<?php
// Muze vyvolat Fatal Error
$user = Environment::getUser();
$user_id = $user->getIdentity()->getId();
?>
na začátek editNameSubmitted zpracování bych dal test na identitu:
<?php
$user = NEnvironment::getUser();
if ($user->identity instanceof IIdentity) {
// zpracovat form
} else {
$this->flashMessage('Měnit údaje smí pouze přihlášený uživatel.', 'warning');
$this->redirect(':Admin:EditUser:default');
}
?>
- tatyalien
- Člen | 239
Tak jsem to testnul:
if ($user->identity instanceof IIdentity)
A stejně se nic nezměnilo, když si ale vypšíu před redirectem:
<?php
$this->flashMessage("|".$user->identity->name."|".$user->identity->email."|");
?>
Dostanu změněné údaje, ale nepromítne se to do přihlášeného uživatele (v db je vše ok).
Ohledně Fatal Error to vím, ale to by mělo být kryté tím, že přístup na Admin_EditUserPresenter je podmíněný přihlášeným uživatelem, pokud není, je přesměrován na přihlášení. Má to tedy cenu to tam dodávat?
Editoval tatyalien (14. 1. 2011 9:50)
- RadH
- Člen | 23
Nekoukl jsem se do beforeRender, ty tam máš číselné klíče k datům, to je trochu nešikovné, protože z nich není přesně poznat co v kterém je.
Lepší je při přihlášení v metodě authenticate uložit do dat identity pole se jmennými klíči např.:
<?php
array(
'name' => 'Jméno',
'email' => 'muj@email.cz',
'password' => 'XXX',
)
?>
Pak v metodě beforeRender() v BasePresenter uprav přiřazení proměnných pro template třeba takto:
<?php
if ($user->isLoggedIn()) {
$this->template->user_id = $user->getId();
$this->template->user_name = $user->identity->name;
$this->template->user_email = $user->identity->email;
$this->template->user_password = $user->identity->password;
} else {
....
}
?>
Proč dáváš do template user_password?
- tatyalien
- Člen | 239
Oki, jdu to přepsat a testnout.
Ad: user_password. Na starjech webech co jsem dělal jsem si vždy při
přihlášení uživatele uložil věci do session a při změně údajů to
kontroloval oproti nim, pkud uživatel zadával stejné data, hodil jsem mu
text, že data odpovídají záznamům uloženým v db, tak není potřeba
provádět změny.
Tady myslím to pak odendám, protože co jsem koukal v jednom případě, tak
dám jen kontrolu, pokud se rovná staré heslo s novým…
Tak po testu vše fachá, díky moc ;)
Stačilo tam pak dát jen:
<?php
$user = NEnvironment::getUser();
$user_id = $user->getId();
// uložení
$editace->edit($editace, $user_id);
// aktualizace načtených dat
$user->identity->name = $values['name'];
$user->identity->email = $values['email'];
?>
Editoval tatyalien (14. 1. 2011 10:23)
- tatyalien
- Člen | 239
RadH: Aha chápu, tak poupraveno :-)
<?php
$editace->edit($editace, $user_id);
// info
if (dibi::getAffectedRows()) {
$user->identity->name = $values['name'];
$user->identity->email = $values['email'];
$this->flashMessage("uživatel editován.");
$this->redirect(':Admin:EditUser:save');
} else {
$this->flashMessage("Data není potřeba ukládat, odpovídají datům uloženým v DB.");
$this->redirect(':Admin:EditUser:default');
}
?>
- tatyalien
- Člen | 239
Teď nevím jak to myslíš,
já se odazuji v prezenteru na akci z models/UserEditaceModel
Kde je:
<?php
class EditUser extends DibiRow
{
public function __construct($arr = array())
{
parent::__construct($arr);
}
public function edit(EditUser $data, $id)
{
return dibi::query('UPDATE [users] SET', (array) $data, 'WHERE [id]=%i', $id);
}
public function save(EditUser $data)
{
return dibi::query('INSERT INTO [users]', (array) $data);
}
?>
V Nette jsem začátečník / lama, pokud to dělám blbě, je lepší mě nakopnout teď, než časem…
- RadH
- Člen | 23
Tvá metoda edit v modelu už sama o sobě vrací dibi::getAffectedRows() (INSERT a UPDATE v dibi query vracejí affectedRows).
Tak test po uložení
<?php
$editace->edit($editace, $user_id);
// info
if (dibi::getAffectedRows()) {
....
?>
nahraď tímto
<?php
if ($editace->edit($editace, $user_id)) {
....
?>