Přihlašování – You cannot serialize or unserialize PDO instances

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

Zdravím, potřeboval bych poradit. Začínám v nette i PHP a snažím se zprovoznit registraci a přihlašování.
Používám třídu UserManager, po zprovoznění registrace se mi nedařilo registrovaného uživatele přihlásit. Zjistil jsem, že se při registraci se při zadání stejného hesla pokaždé vytvoří jiný hash. Nedokázal jsem najít způsob jak to opravit, tak jsem funkci Password::hash() nahradil funkcí password_hash(). Teď když se snažím přihlásit, tak to vypisuje: You cannot serialize or unserialize PDO instances.

označený je řádek:
$this->getUser()->login($values->username, $values->password);

-- UserManager

	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('Uživatelské jméno neni správné', self::IDENTITY_NOT_FOUND);

		} elseif (!password_verify($password, $row[self::COLUMN_PASSWORD_HASH])) {
			throw new Nette\Security\AuthenticationException('Špatné heslo!.', self::INVALID_CREDENTIAL);

		} elseif (password_needs_rehash($row[self::COLUMN_PASSWORD_HASH],PASSWORD_DEFAULT, $this->options)) {
			$row->update(array(
				self::COLUMN_PASSWORD_HASH => password_hash($password, PASSWORD_BCRYPT, $this->options),
			));
		}

		$arr = $row->toArray();
		unset($arr[self::COLUMN_PASSWORD_HASH]);
		return new Nette\Security\Identity($row[self::COLUMN_ID], $row[self::COLUMN_ROLE], $arr);
	}
public function signInFormSucceeded($form)
    {
        $values = $form->values;
        try {
          //  $this->getUser()->login($values['username'], $values['password']);
            $this->getUser()->login($values->username, $values->password);
            $this->flashMessage('Přihlášení bylo úspěšné.');
            $this->redirect('Homepage:');
        } catch (Nette\Security\AuthenticationException $e) {
            $form->addError($e->getMessage());
        }
    }

Už jsem z toho všeho totál unavený.
Díky za jakýkoliv tip

David Matějka
Moderator | 6445
+
+2
-

Zjistil jsem, že se při registraci se při zadání stejného hesla pokaždé vytvoří jiný hash.

ano, to je spravne chovani. Vytvoreny hash obsahuje i salt. Pro overeni pak nesmis znovu pouzit Password::hash, ale Password::verify.

nahradil funkcí password_hash().

to klidne muzes, chova password_hash a password_verify se chovaji stejne jako ty funkce v nette – dokonce ve vyvojove verzi nette jsou primo pouzity tyto funkce

A k serialize/unserialize

Chybu tam nevidim. Jaky obsah maji promenne, co posilas do Identity? tedy zkus

dump(row[self::COLUMN_ID]);
dump($row[self::COLUMN_ROLE]);
dump($arr);
Windu
Člen | 2
+
0
-

Super, už se mě podařilo přihlásit, problém byl s názvem sloupce COLUMN_ID :-). Nejsem zvyklý pracovat s databází a zohledňovat Case sensitive :D (id != ID) : – – několik_hodin_života

Díky moc!

MKI-Miro
Člen | 261
+
0
-

momentalne skusam implementovat cache ale pri ukladani vysledkov z db mi to hlasi

$category = $this->categoryRepository->findAll();;
            $cache->save("category", $category);
You cannot serialize or unserialize PDO instances

hladam som aj vo fore ale ziadne riesenie som nenasiel

ako to teda robite?

dakujem

Mortisson
Člen | 21
+
0
-

MKI-Miro napsal(a):

momentalne skusam implementovat cache ale pri ukladani vysledkov z db mi to hlasi

$category = $this->categoryRepository->findAll();;
            $cache->save("category", $category);
You cannot serialize or unserialize PDO instances

hladam som aj vo fore ale ziadne riesenie som nenasiel

ako to teda robite?

dakujem

Ta metoda findAll() ti pravděpodobně vrací ActiveRow, nebo jiný PDO objekt a ty serializovat nejdou. Pokud si to do té cache chceš uložit, budeš si muset ty výsledky projet a uložit si je do pole. Pokud jsou to ActiveRow tak si je foreachem projeď a zavolej na každé row metodu toArray() a pak to ulož

MKI-Miro
Člen | 261
+
0
-

nezaberie to este viac casu ako samotne volanie do db?

metoda findAll

public function __construct(Nette\Database\Context $db) {
        $this->database = $db;
    }

    /**
     * Vrací objekt reprezentující databázovou tabulku.
     * @return Nette\Database\Table\Selection
     */
    protected function getTable() {
        // název tabulky odvodíme z názvu třídy
        preg_match('#(\w+)Repository$#', get_class($this), $m);
        return $this->database->table(lcfirst($m[1]));
    }

    /**
     * Vrací všechny řádky z tabulky.
     * @return Nette\Database\Table\Selection
     */
    public function findAll() {
        return $this->getTable();
    }

Editoval MKI-Miro (23. 2. 2017 11:21)

greeny
Člen | 405
+
0
-

Ukládání zabere víc času, ale načítání z cache bude rychlejší v dalších requestech.

MKI-Miro
Člen | 261
+
0
-

skusam to vselijak ale nefunguje mi to

$cache = new Cache($this->storage);

        $authors = $cache->load("authors");
        if ($authors === NULL)
        {
            $authorsArray = array();
            $authors = $this->category_authorRepository->findAll()->order("name ASC")->fetchAll();
            foreach($authors as $author)
            {
                $authorsArray[] = $author;
            }
            $cache->save("authors", $authorsArray);
        }

viete prosim poradit ako nato? dakujem

greeny
Člen | 405
+
+2
-

Psáno z hlavy, ale mělo by to fungovat :)

$cache = new Cache($this->storage);
$authors = $cache->load('authors', function () {
	$authors = $this->category_authorRepository->findAll()->order('name ASC')->fetchAll();
	return array_map(function (ActiveRow $author) {
		return $author->toArray();
	}, $authors);
});
MKI-Miro
Člen | 261
+
0
-

dakujem takto to uz funguje

ale hned ma napada dalsia otazka

ako teraz spravime nieco ako $author->where() ked uz to nie je obejkt ale pole ktore ma v sebe polia

dakujem

CZechBoY
Člen | 3608
+
0
-

@MKI-Miro nijak, musíš udělat novej sql dotaz.