Even if you give a Customer the methods addToCart() and removeFromCart(), you would still have to have some logic in ShoppingCart to have these methods actually do the state change when an item is added or removed. IMO, the actor in this case is much better represented by a reference to the owning Customer and/or viceversa, e.g.
$cart = new ShoppingCart;
$cart->setOwner(new Customer);
$cart->addItem(new Item('Apples'));
$cart->checkout();
You could approach this from the customer as well, e.g.
$customer = new Customer;
$customer->setShoppingCart(new ShoppingCart);
$customer->addItemToShoppingCart(new Item('Apples'));
$customer->checkout();
But the method name addItemToShoppingCart already implies that the Customer acts on a ShoppingCart, so inside you are likely doing
$this->getShoppingCart()->addItem($item);
If ShoppingCart was a composite element of Customer for which we wanted to hide implementation details, we could use something like that, but since the ShoppingCart is IMO not an essential part of a Customer this method shouldnt be on Customer. It's nothing but a convenience proxy.
You could create a Decorator for the Customer to handle the Shopping Behavior. This would decouple the concern/responsibility of How-To-Shop from the Customer, e.g. something like
class ShoppingDecorator
{
protected $actor;
protected $cart;
protected function __construct($actor) { ... }
public function getCart() { ... };
public function addToCart() { ... }
...
}
This would also allow you to apply the Shopping Behavior to other actors that might need this behavior.
The CustomerActsOnCart approach sounds somewhat like the Mediator Pattern. Not sure if it's a feasible approach though.