Architektura aplikace nad Doctrine 2

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

Po přečtení tohoto článku jsem se rozhodl, že se pokusím vytvořit web pomocí Doctrine 2. Nejsem si ale jistý, jestli jsem architekturu z článku pochopil správně, takže by jsem byl rád, pokud by mi zde někdo zkontroloval můj výtvor (jedná se o registraci uživatelů).

Entita

<?php

use \Doctrine\ORM\Mapping as ORM,
	\Nette\Object;

/**
 * @ORM\entity(repositoryClass="UsersRepository")
 * @ORM\table(name="users")
 */
class Users extends Object
{
	/**
	 * @ORM\id
	 * @ORM\column(type="integer", length=11)
	 * @ORM\generatedValue
	 */
	private $id;

	/**
	 * @ORM\column(type="string", length=32, unique=true)
	 */
	private $username;

	/**
	 * @ORM\column(type="string", columnDefinition="CHAR(128)")
	 */
	private $password;

	public function getId()
	{
		return $this->id;
	}

	public function getUsername()
	{
		return $this->username;
	}

	public function setUsername($value)
	{
		$this->username = $value;
		return $this;
	}

	public function getPassword()
	{
		return $this->password;
	}

	public function setPassword($value)
	{
		$this->password = $value;
		return $this;
	}
}
?>

Service

<?php

use \Nette\Object;

class UserService extends Object
{

	public function calculateHash($password, $salt = null)
	{
		return hash('sha512', $password . $salt);
	}
}
?>

Facade

<?php

use \Nette\Object,
    \Doctrine\ORM\EntityManager;

class RegisterFacade extends Object
{
	private $entityManager;
	private $userService;
	private $users;

	public function __construct(EntityManager $entityManager, \UserService $userService)
	{
		$this->entityManager = $entityManager;
		$this->userService = $userService;
		$this->users = new Users;
	}

	public function saveUser(array $data)
	{
		if($this->entityManager->getRepository('Users')->findOneByUsername($data['username']))
		{
			throw new \BadUsernameException;
		}

		$this->users->setUsername($data['username'])
			    ->setPassword($this->userService->calculateHash($data['password']));
		$this->entityManager->persist($this->users);
		$this->entityManager->flush();
		return $this->users;
	}
}
?>

Config.neon

	services:
		database: @doctrine.entityManagers.default
		register: RegisterFacade(@database, @userService)
		userService: UserService

Pár otázek:

  • Facade má být service nebo factory?
  • Je chytré kontrolovat zda uživatel existuje tím, že vytáhnu z databáze všechny uživatele se stejným jménem, které zadal uživatel a pokud někoho naleznu, tak vyhodím výjimku (tu poté odchytávám v komponentě)?
  • Jak mohu generovat proxy třídy?

Omlouvám se za tak dlouhý příspěvek a všem předem děkuji za odpovědi.

Filip Procházka
Moderator | 4668
+
0
-

Takže pár drobností – pokud chceš dělat OOP, musíš především co nejlépe (logicky) pojmenovávat třídy.

  1. UsersUser
  2. UserServicePasswordGenerator (service nemusí být v názvu service)
  3. RegisterFacade::saveUser()RegisterFacade::registerUser()

Nastuduj si autowiring

services:
        registerFacade: RegisterFacade()
        passwordGenerator: PasswordGenerator()

Je dobré používat konstruktor v entitách

class User extends Nette\Object
{
	// ...

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

        // ...
}

Je sice pravděpodobné, že budeš uživatele vytvářet max 1 za http request, ale není dobré se na to spoléhat.

class RegisterFacade extends Object
{
        private $entityManager;

        public function __construct(EntityManager $entityManager)
        {
                $this->entityManager = $entityManager;
        }

	private function isUsernameTaken()
	{
		// Téhle metodě by bylo dobré v jiné třídě
		// a ani není moc vesele implementovaná,
		// ale chvíli ti bude stačit :)

		return (bool)$this->entityManager
			->getRepository('User')
			->findOneByUsername($data['username']);
	}


        public function registerUser(array $data)
        {
                if ($this->isUsernameTaken()) {
                        throw new \BadUsernameException;
                }

		$user = new User($data['username']);
                $user->password = $this->passwordGenerator->calculateHash($data['password']);

                $this->entityManager->persist($user);
                $this->entityManager->flush();

                return $user;
        }
}