Reputation: 1365
I've created a my first class, a shopping cart class. It's great and does all that I need it to. However, and there is always an however,...
I've read a lot about type hinting and been advised to only pass my shoppingcart class a hinted variable:
$cart = new cart(item $id);
I understand the reason for doing this but I'm confused as to what my item class should do and what methods to use in it if I chose to implement it.
At present my site use MVC-inspired structure to separate the methods/views and controller. My view contains a post form which send item ID to the controller which creates the object and calls the additem method (or other relevant method).
Do you feel that the way I have implemented the site benefit from an item class?
Upvotes: 0
Views: 3618
Reputation: 13348
Type hinting is a way of informing the users of your methods how they should call them. It also allows you, as the one implementing the method, to rely on certain features of the parameters you are being passed.
Here is an example of a shopping cart without type hinting
<?php
class Cart {
protected $items = array();
public function addItem($item) {
$this->items[] = $item;
}
}
$cart = new Cart();
$cart->addItem('My Super Cool Toy');
What you have in $cart
after running the above, is an instance of Cart
with one item, "My Super Cool Toy." However, the Cart
object has no idea what that item is. It doesn't know how it can interact with it or what it can do with it. For example, how would I get the subtotal for the cart above? I can't.
Here's an example with type hinting:
<?php
class Cart {
protected $items = array();
public function addItem(Item $item) {
$this->items[] = $item;
}
public function getSubTotal() {
$total = 0;
foreach ($this->items as $item) {
$total += $item->getPrice();
}
return $total;
}
}
class Item {
protected $name;
protected $price;
public function __construct($name, $price) {
$this->name = $name;
$this->price = $price;
}
public function getName() {
return $this->name;
}
public function getPrice() {
return $this->price;
}
}
$cart = new Cart();
$cart->addItem(new Item('My Super Cool Toy', 10.99));
Now I'm in a whole different situation. I know that my Cart
is full of Item
s. I know that I can getPrice()
of an Item
. I can rely on that being there, because the only way you can call my addItem
method is by giving me an Item
object.
Could the same be done without type hinting? Yes. However, there's no good way to be able to rely on any specific implementation. As the caller, I might give you an Item object. But I might also give you a string, or a number. And if all you have is a string or a number, how are you going to be able to definitively give me a price?
Now let's make it a little bit better
And quickly go into coding to interfaces. Let's say I have to types of toys: RC cars and dolls. Presumably, we play with them differently. One "item" object wouldn't work in this case, since they can do different things. But, they both exhibit the same types of behavior. They're both toys. So let's create an interface for that:
<?php
interface Toy {
public function play();
}
And let's create some concrete classes for our toys:
<?php
class RemoteControlledCar implements Toy {
public function play() {
print "I'm driving a car";
}
}
class Doll implements Toy {
public function play() {
print "GI Joe";
}
}
Now, we're going to store our toys in a toy bin:
<?php
class ToyBin {
protected $toys = array();
public function addToy(Toy $toy) {
$this->toys[] = $toy;
}
public function playWithMyToys() {
foreach ($this->toys as $toy) {
$toy->play();
}
}
}
And look at that, you have successfully programmed correctly. You know you have a Toy Bin full of Toy objects. You don't have to care what kind of toys they are, nor do you have to car how you would interact with them. You just know that you are able to do certain things with them (in this case, play
with them). And because of that, you have an interface that you can rely on.
Why exactly is this better? Interfaces are really the way to go with programming for a couple of reasons
ToyBin
can be play()
ed with. And you don't have to worry about how.Hopefully that helps clear things up.
Upvotes: 7
Reputation: 1777
Following the principles of MVC to the fullest you would expect to see items modelled as a class. Even if this is just a subclassed database record, it provides an easy platform for expansion in the future. However, I would expect to see this typehinted variable of class "item" on a method such as addItem()
rather than neccessarily the constructor of the cart class. Is the implication that your cart will only have one item?
From a design-pattern point of view it makes sense to have a class for your items anyway. You may not have any of these requirements now, but at a later stage you may want to add methods to the item class to:
and so on.
Using PHP object oriented it's generally always a good idea to use type hinting if you can (if the parameter definitely needs to be of a fixed type). And in the case of simple types like integers it's always worth checking for or casting to that type as the first thing you do in your method. It's more secure that way, and by inspecting the errors over time you will learn alot about any bugs that may be in your codebase.
Upvotes: 0