2013-03-18 17 views
5

Badam i dużo czytam o pracy z oddzielnymi warstwami w PHP, aby stworzyć łatwy do utrzymania i czytelny kod. Jednak widzę dużo kodu, w którym encja i dostęp do bazy danych jest umieszczony w jednej klasie. Na przykład:php DAL - osobna jednostka i baza danych?

class User{ 
    public $id; 
    public $username; 
    public $database; 

    function add(){ 
      $database->query .... 
    } 
} 

Uważam to raczej dziwne, bo tu jesteś mieszania klasy użytkownik z elementów bazy danych, która sprawia, że ​​trudniej utrzymać.

Lubię pracować tak:

  • oddzielna baza klasa klasa klasa
  • użytkownik
  • userData

Działa to tak:

$database = new Database(); 
$database->openConnection(); 
$dataUser = new DataUser($db); 
$user = new User(1,"myname"); 
$dataUser->saveUser($user); 

Więc zastanawiam się, czy ja pracuję właściwą drogę, czy jest to pierwszy sposób na lepszy sposób tworzenia kodu? Uważam, że sposób może być bardzo łatwy w utrzymaniu, ponieważ masz oddzielną jednostkę i oddzielną klasę bazy danych do obsługi akcji bazy danych.

+0

+1 miłe pytanie :) –

+1

+1 też za miłe pytanie ... –

Odpowiedz

1

łatwe w utrzymaniu, ponieważ trzeba odrębnego podmiotu i oddzielną klasę bazy

Wydaje się, mówisz, że chcesz odejść od podejścia Active Record do podejścia Data Mapper/Entity/Repository. To dobry kierunek, aby wprowadzić się, ponieważ wymaga lepszej separacji obaw. Można zbudować ten sam, ale warto przyjrzeć się rozwiązań takich jak Doctrine gdzie to pozwala zrobić coś wzdłuż linii:

$product = new Product(); 
$product->setName($newProductName); 
$entityManager->persist($product); 

Podmiot $product jest tylko (Object Plain Old PHP) POPO że zawiera dane rekordów i nie jest świadomy ich trwałości, a gdy wymagana jest trwałość, jest przekazywana do menedżera podmiotu, aby zająć się przechowywaniem.

+0

Dzięki, chcę tylko oddzielić elementy, aby móc je pobrać jako obiekt, a nie jako tablicę z danymi na przykład. Zajrzę do Doktryny. – randomizer

1

Osobiście uważam, że abstrakcja UserData z User jest prawdopodobnie przesadzona. Jak w tym przypadku, UserData będzie prawdopodobnie bardzo podobna do ProductData na przykład - są one nadal będzie zawierać add($data), find($id) itp

W twoim przypadku, User jest modelem w podejściu MVC i jest całkowicie akceptowalne, aby zawierało logikę składowania/pobierania bazy danych. Najprawdopodobniej jednak się dowiesz, że ponownie tworzysz te same metody DB w klasie User, które masz w innych modelach. Tutaj możesz zacząć przyglądać się implementacji ORM. W związku z tym, że wspólne metody dostępu do bazy danych są zdefiniowane w klasie abstrakcyjnej, wszystkie modele następnie rozszerzają się i zastępują w razie potrzeby.

+0

Czytałem ten temat jeszcze raz i nie rozumiem twojej ostatniej linii. Czy to nie jest normalne, że moje Userdata, ProductData, itp. Zawierają się, powiedzmy, funkcję "zapisz", "znajdź" i "usuń", ponieważ muszą wykonać zapytanie do innej tabeli. Nie mam tutaj korzyści z klasy abstrakcyjnej, użyłbym klasy abstrakcyjnej, na przykład, stwórz mój adapter bazy danych, aby był możliwy do użycia we wszystkich moich klasach xData. – randomizer

1

co zrobić:

Moje modele nie są Podmioty związane z bazy danych (gdy nie używam doktryny), więc nie ma metody „Active Record”. Obiekt nie wie, jak pobrać jego zależności (na przykład użytkownik może mieć n komentarzy, mój model nie wie, jak uzyskać komentarze).

class User{ 
private $name; 
private $password; 
// getter and setters 
} 

mam usługi, które posiadają pewną logikę biznesową, która może pobierać modele od dostawców, usługa może mieć wielu dostawców.

class UserService{ 
    function __construct(IUserProvider $userProvider){ 
     $this->userProvider = $userProvider 
    } 
    function getUsers(){ 
     // return an array of user objects 
     return $this->userProvider->getUsers(); 

    } 
} 

wreszcie mam dostawcy danych, który wie, jak zwrócić dane teleadresowe z bazy danych, plik tekstowy, plik JSON usługa:

class UserProvider implements IUserProvider{ 
     function __construct(Connection $connection){ 
     $this->connection = $connection; 
     } 
     function getUsers(){ 
     return $this->toUsers($this->connection->fetchAssoc("Select * from users")); 
     } 
     function toUsers(array $datas){ 
      // convert user records to an array of User 
      (...) 
      return $users; 
     } 
} 

następnie interfejs

interface IUserProvider{ 
    /**@return array an array of User */ 
    function getUsers(); 
} 

jeśli potrzebuję uzyskać komentarze użytkownika, to moja usługa komentarzy wie, w jaki sposób pobrać komentarze od użytkownika. Aby uzyskać użytkownika i jego komentarze, potrzebuję 2 żądań do bazy danych. jeden z UserProvider, drugi z CommentProvider.

tak mam 3 warstw:

  • moje warstwy aplikacji (użytkownicy wyświetlacz, odpowiadać na żądania cokolwiek ...)
  • mój warstwa serwis (który ma pracować z interfejsem wiersza poleceń i nie jest świadomy mojej aplikacji internetowych, z wyjątkiem kodowania haseł, które zwykle zbindowanych ram używam i ACL spożywcze może ...)
  • mój warstwy dostępu do danych, które nie wie nic na temat innych warstw,

Jedynym sposobem, w jaki komunikują się moje warstwy, jest przechodzenie modeli z warstwy na warstwę.

Wszystkie moje klasy są zbudowane za pomocą kontenera wtryskowego zależności, więc okablowanie nie stanowi problemu.

Oto exemple z aplikacji zrobiłem, to otwarte źródło: https://github.com/Mparaiso/silex-bookmarkly

Wszelkie myśli mile widziane.