2. Object-relational mapping (ORM, O/RM, and O/R mapping) in computer software is a programming technique for converting data between incompatible type systems in object-oriented programming languages. This creates, in effect, a "virtual object database" that can be used from within the programming language. There are both free and commercial packages available that perform object-relational mapping, although some programmers opt to create their own ORM tools.
3. Loose coupling: Given two lines of code, A and B, they are coupled when B must change behavior only because A changed. Content coupling (high) is when one module modifies or relies on the internal workings of another module (e.g. accessing local data of another module). Therefore changing the way the second module produces data (location, type, timing) will lead to changing the dependent module. High cohesion: They are cohesive when a change to A allows B to change so that both add new value. Functional cohesion (best) is when parts of a module are grouped because they all contribute to a single well-defined task of the module Loose coupling and High Coupling
4.
5. Ways to achive “Low Cohesion” and “High coupling” Classes.... first approach class Orders { public function __construct($orderId) { $sql = “select o.order_id,.... from order o inner join o.order_product op on... Inner join op.product p on... inner join o.customers c on. where o.order_id = $orderId. } } class Customer { public function getFullName(){} public function getRating(){} } Class Product { public function getPrice(){} }
6.
7. class Order { public function __construct($orderId) { $sql = “select o.order_id,.... from order o where o.order_id = $orderId” } public function getOrderProducts() { $sql = “select op.order_product_id,.... from order_product op where order_id = $this->orderId” } public function getCustomer() { $sql = “select c.customer_id,.... from customer c where c.customer_id = $this->customerId” } } Ways to achive “Low Cohesion” and “High coupling”
8. class Order { public function __construct($orderId) { $sql = “select o.order_id,.... from order o where o.order_id = $orderId” } public function getOrderProducts() { $this->_orderProducts = new OrderProductCollection($this->orderId); } public function getCustomer() { $this->_customer = new Customer($this->customerId); } } Or even better... Ways to achive “Low Cohesion” and “High coupling”
9.
10. $queryBuilder = $em ->createQueryBuilder(); ->select('o') ->from('Entitiesrders', 'o') ->innerJoin('o.ordersProducts', 'op') ->innerJoin('o.customers', 'c') ->where($queryBuilder->expr()->in('o.ordersId', '?1')) ->setMaxResults(1) ->setParameter(1, '5030492') ->getQuery(); $order = $query->getSingleResult(); This will generate an efficent code: SELECT ..... FROM orders o0_ INNER JOIN orders_products o1_ ON o0_.orders_id = o1_.orders_id INNER JOIN customers c2_ ON o0_.customers_id = c2_.customers_id WHERE o0_.orders_id IN (?) LIMIT 1 Ways to achive “Low Cohesion” and “High coupling” Welcome to Doctrine 2: DQL language
11.
12. How to access the data: echo $order->getCustomer()->getFirstName(); echo $order->getCustomer()->getFullName(); echo $order->getAddressDeliveryStreet(); foreach( $order->getOrdersProducts() as $orderProduct ) { echo $orderProduct->getOrdersProductsId(); echo $orderProduct->getProductName(); } Doctrine create and inject (Hydrate) the data into $order, $customer $orderProducts (collection). We still have decouple and choesive objects Doctrine 2
13. We sill can do: $queryBuilder = $em ->createQueryBuilder(); ->select('o') ->from('Entitiesrders', 'o'); And access, but sql no as efficent...: “ SELECT o0.... FROM orders o0_ WHERE o0_.orders_id IN (?) LIMIT 1” echo $order->getCustomer()->getFirstName(); “ SELECT t0.... FROM customers t0 WHERE t0.customers_id = ?” echo $order->getCustomer()->getFullName(); echo $order->getAddressDeliveryStreet(); $orderProducts = $order->getOrdersProducts(); “ SELECT t0... FROM orders_products t0 WHERE orders_id = ?” foreach( $orderProducts as $orderProduct) { echo $orderProduct->getOrdersProductsId(); echo $orderProduct->getProductName(); } Doctrine 2
14. Also we have magic finder methods throw the repositories: $em->getRepository(“Entitiesrder”)->find() Or ->findByCustomerId() Doctrine 2
15. We meet the Doctrin Entities... <?php namespace Entities; /** * @Entity @Table(name="orders") */ class Orders { /** * @Id @Column(type="integer", name="orders_id") * @GeneratedValue(strategy="AUTO") */ private $ordersId; /** * @Column(type="integer", name="customers_id") */ private $customersId; /** * @ManyToOne(targetEntity="Customers") * @JoinColumn(name="customers_id", referencedColumnName="customers_id") */ private $customers; public function getOrdersId() { return $this->ordersId; } public function setOrderId($orderId) { $this->ordersId = $ordersId; } Doctrine 2
16. They don't follow the Active Record pattern like Zend_Table or Doctrine: “ Active record is an approach to accessing data in a database. A database table or view is wrapped into a class. Thus, an object instance is tied to a single row in the table. After creation of an object, a new row is added to the table upon save. Any object loaded gets its information from the database. When an object is updated the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view.”
17. Data Mapper The Data Mapper is a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other. With Data Mapper the in-memory objects needn't know even that there's a database present; they need no SQL interface code, and certainly no knowledge of the database schema. (The database schema is always ignorant of the objects that use it.) Since it's a form of Mapper (473), Data Mapper itself is even unknown to the domain layer $order = new Order; $order->setCustomerId(3); $order->setDeliveryAddress('....'); $em->persist($order); $em->flush();