5
\$\begingroup\$

I built a small store site for learning purposes. I loaded my 'products' from the db into a Products class. I used a method from this class to display the products in HTML. Of course, the HTML contains 'Add to Cart' buttons which POST the product ID and quantity when a button is clicked. The result is that the POSTed ID and quantity are sent to the Cart class. This works, but it seems like I should be sending a product object to my cart instead of just two values that will be stored in an array.

I'm not sure how to do that, given that product information needs to be POSTed non-objectively. And I'm not sure if it would be better.

class Products
{

private $products; 

function __construct($data)
{

    $this->products = $data;

}   

public function showProduct($id, $price, $type)
{
        echo "<div id='$id' class='product'>";
        echo $type."<br/>";
        echo $price."<br/>";            
        echo "Quantity: <input class='quantity' name='quantity' value='1' type='text'/><br/>";
        echo "<button onclick='add($id);'>Add to Cart</button>";
        echo "</div>";      
}

public function showAll()
{
    foreach ($this->products as $id => $product) {

        $this->showProduct($id, $product->price, $product->type);
    }

}   



}

And the Cart class:

class Cart
{
public $items = array();

function __construct() {

    if (isset($_SESSION['cart'])) { $this->items = $_SESSION['cart']; } else { $_SESSION['cart'] = ''; }
}

private function update() {

    $_SESSION['cart'] = $this->items;
}   

public function add($id, $quantity) {

    $this->items[] = array('id'=>"$id", 'quantity'=>"$quantity");
    $this->update();

}
}

I'm not sure that I was able to get the objects from these classes to interact with each other properly.

Also, in this situation, since I need to use $_SESSION to keep the cart inventory persistent, I'm not sure why I need a Cart class at all. It seems a little superfluous, but I have a nagging feeling that it shouldn't be.

\$\endgroup\$
2
\$\begingroup\$

I would have done it in the following way:

<?php
    class Product {
        private $id;
        private $type;
        private $price;


        public function __toString() {
            return  "your way to display the Product object ie: <p> The id is: $this->getId </p> ";
        }


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


        public function setId($id)
        {
            $this->id = $id;
        }

        public function getType()
        {
            return $this->type;
        }

        public function setType($type)
        {
            $this->type = $type;
        }

        public function getPrice()
        {
            return $this->price;
        }

        public function setPrice($price)
        {
            $this->price = $price;
        }

    }

    class Cart {
        private $products;
        private $id;

        public function getProducts()
        {
            return $this->products;
        }


        public function addProduct(Product $product)
        {
            $this->products[] = $product;
        }


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


        public function setId($id)
        {
            $this->id = $id;
        }

        /**
         * Returns the sum off all products prices
         * array_reduce docs: http://php.net/manual/en/function.array-reduce.php
         */
        public function total(){
            return array_reduce($this->getProducts(), function($carry, $product){
                return $carry + $product->getPrice();
            });
        }

    }

It's important to note here that you are managing objects, so you will need some Object Relational Mapper to persist objects on a DB, such as Doctrine.

You need to separate concerns in a MVC architecture, the logic of your domain the 'M' of MVC (in this case the shopping cart) reside in a object model (Product + cart) . Then you need the 'C' here you tell the cart that you want to add a new product:

class Controller {
        public function someAction(){
            $product = new Product();
            $product->setId(1);
            $product->setPrice(100.00);
            $product->setType(3); //Id of the type

            $cart = new Cart;
            $cart->addProduct($product);

            $cart->total(); //Will return 100.00
            //Logic to obtain twig engine
            return $twig->render('Template', ['cart' => $cart]); //returns HTML
        }
    }

And finally the V of the MVC there is where you build your HTML:

Using a template engine like Twig:

     <html>
        <body>
        Total: {{cart.total()}}
           <ol>
              {% for product in cart.products %}
                 <li>{{product}}</li>
              {% else %}
                 <li>Empty cart</li>
              {% endfor %}
           </ol>
        </body>
    </html>

Of course building this architecture on your own could be really complicated there is when frameworks like symfony kick in http://symfony.com/. It's just a personal recommendation.

Also, take a look at OOP patterns. They will make your life easier and you will learn how to program good architectures for models.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.