Data Mapper, Model, Repository

129 views Asked by At

SOLUTION

Please make sure to read the whole topic, and at the end read the solution, which i'll try to explain. I've kind of created my own ORM (Object Related Mapping) which solves the problem of models with joined table. Let's take the example that I've provided down below.

Model (Cart)

<?php

namespace Eshop\Model;

class CartModel
{
    private int   $quantity;
    private int   $customer_id;
    private array $products; //You are saving here your Product Model 


    /**
     * @param ProductModel[]
     * @return array
    */
    public function getProducts(): array
    {
        return $this->products;
    }

    /**
     * @param ProductModel[] $products
     */
    public function setProducts(array $products): void
    {
        $this->products = $products;
    }

    /**
     * @param ProductModel $productsModel
     */
    public function setProduct(ProductModel $productsModel): void
    {
        $this->products[] = $productsModel;
    }

Repository

    public function getCartItems(int $customerId): array|bool
    {
        $tableName = $this->setTableName(); // Cart Table
        $statement = $this->connection->prepare("SELECT cart.quantity, cart.customer_id, product.productid, product.name, product.imagepath, product.price FROM `$tableName` as cart LEFT JOIN product as product ON product.productid = cart.product_id WHERE cart.customer_id=:customerId AND cart.ordered=0;");
        $statement->execute(['customerId' => $customerId]);
        $rows = $statement->fetchAll();
        $cartModel= new CartModel(); 
        foreach($rows as $row){
          $productModel = new ProductModel() 
          $productModel->setName($row['name])
          $productModel->setPrice($row['price])
          $cartModel->setProduct($productModel) 
         }
        return $cartModel
    }

Now we have a Product Model stored inside array.

View

Store the repository inside controller (I used $userCart variable)

<?php 

  foreach($userCart->getProducts() as $userCart){
     //Now you are able to use getters and setters of ProductModel 
     echo $userCart->getName();
     echo $userCart->getPrice();
}

?>


Original Post

I am using MVC Pattern, and so far I have Repository (where all SQL statements happens, and PDO stuff), I have Controller which renders the repository to the View, and I have Model with private properties, and getters / setters, where the Objects are fetched.

So far, I used FETCH_CLASS and stored everything inside one Model, and then on View I called the getter methods to display it. But I need to use now some kind of Data Mapper, which is going to allow me to store information to model manually (because I have Joins in statements, and want to store for example Cart Data that comes from Cart Table to Cart Model, and Product Data that comes from Product Table to Product Model.

Repository

Like I said, I've used FETCH_CLASS but in this case I need another solution

    public function getCartItems(int $customerId): array|bool
    {
        $tableName = $this->setTableName(); // Cart Table
        $statement = $this->connection->prepare("SELECT cart.quantity, cart.customer_id, product.productid, product.name, product.imagepath, product.price FROM `$tableName` as cart LEFT JOIN product as product ON product.productid = cart.product_id WHERE cart.customer_id=:customerId AND cart.ordered=0;");
        $statement->execute(['customerId' => $customerId]);
        return $statement->fetchAll();
    }

Model (Cart)

<?php

namespace Eshop\Model;

class CartModel
{
    private int   $quantity;
    private int   $customer_id;
    private array $products;


    /**
     * @param ProductModel[]
     * @return array
    */
    public function getProducts(): array
    {
        return $this->products;
    }

    /**
     * @param ProductModel[] $products
     */
    public function setProducts(array $products): void
    {
        $this->products = $products;
    }

    /**
     * @param ProductModel $productsModel
     */
    public function setProduct(ProductModel $productsModel): void
    {
        $this->products[] = $productsModel;
    }

    /**
     * @return int
     */
    public function getQuantity(): int
    {
        return $this->quantity;
    }

    /**
     * @param int $quantity
     */
    public function setQuantity(int $quantity): void
    {
        $this->quantity = $quantity;
    }

    /**
     * @return int
     */
    public function getCustomerId(): int
    {
        return $this->customer_id;
    }

    /**
     * @param int $customer_id
     */
    public function setCustomerId(int $customer_id): void
    {
        $this->customer_id = $customer_id;
    }

    /**
     * @return int
     */
    public function getOrdered(): int
    {
        return $this->ordered;
    }

    /**
     * @param int $ordered
     */
    public function setOrdered(int $ordered): void
    {
        $this->ordered = $ordered;
    }
}

Model (Product)

<?php

namespace Eshop\Model;

/** Getters and Setters for Model */
class ProductModel
{
    /** Product Table */
    private int    $productid;
    private string $name;
    private string $description;
    private float  $price;
    private string $imagepath;



    /**
     * @return int
     */
    public function getProductid(): int
    {
        return $this->productid;
    }

    /**
     * @param int $productid
     */
    public function setProductid(int $productid): void
    {
        $this->productid = $productid;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * @param string $description
     */
    public function setDescription(string $description): void
    {
        $this->description = $description;
    }

    /**
     * @return float
     */
    public function getPrice(): float
    {
        return $this->price;
    }

    /**
     * @param float $price
     */
    public function setPrice(float $price): void
    {
        $this->price = $price;
    }

    /**
     * @return string
     */
    public function getImagepath(): string
    {
        return $this->imagepath;
    }

    /**
     * @param string $imagepath
     */
    public function setImagepath(string $imagepath): void
    {
        $this->imagepath = $imagepath;
    }
    
}

Cart Controller

/**
     * Cart System
     */
    public function cart(): void
    {
        //The Message and Total Price are false until...
        $messages = false;
        $totalPrice = false;

        //Get product from customer's cart
        $customerCartItems = $this->cartService->getCartForCustomer();


        //If there is nothing in cart, print out the message
        if ($customerCartItems === false) {
            $messages = $this->cartService->getMessages();
        } else {
            // Else Get Total Price in cart
            $totalPrice = $this->cartService->getTotalPrice();
        }

        //Render to view
        $this->render('cart', ['cartUser' => $customerCartItems, 'messages' => $messages, 'totalPrice' => $totalPrice]);
    }

View

FETCH_CLASS was used on ProductModel, so I've easily return the values with getters. But in this case, I can't.

    <?php foreach ($cartUser as $cartItem) { ?>
                    <tr>
                        <td>
                            <img class="cart-images" src="<?php echo $cartItem->getImagepath(); ?>">
                        </td>
                        <td>
                            <p><?php echo $cartItem->getName(); ?></p>
                        </td>
                        <td>

Any Idea?

0

There are 0 answers