# Wishlist

> A wishlist is a list of products that is not meant to be ordered. Merx’ ProductList class gives you the same list of products as the cart, without the session handling and the checkout of Cart.

[`Cart`](https://merx2.wagnerwagner.de/reference/classes/cart.md) extends [`ProductList`](https://merx2.wagnerwagner.de/reference/classes/product-list.md). Both hold the same [`ListItem`](https://merx2.wagnerwagner.de/reference/classes/list-item.md) objects and share methods like [`total()`](https://merx2.wagnerwagner.de/reference/classes/product-list/total.md) and [`quantity()`](https://merx2.wagnerwagner.de/reference/classes/cart/quantity.md). The difference is that `Cart` stores itself in the visitor’s session and can be ordered, while `ProductList` leaves storage to you. That makes `ProductList` a good starting point for a wishlist, so let’s build one on it.

## Create a list

```php title="/site/controllers/wishlist.php"
<?php

use Wagnerwagner\Merx\ProductList;

return function () {
  $wishlist = new ProductList();

  return [
    'wishlist' => $wishlist,
  ];
};
```

## Add products

[`add()`](https://merx2.wagnerwagner.de/reference/classes/product-list/add.md) takes the id or the UUID of a [product page](https://merx2.wagnerwagner.de/guide/getting-started/adding-products.md), an array, or a [`ListItem`](https://merx2.wagnerwagner.de/reference/classes/list-item.md) object.

```php
// id of a product page
$wishlist->add('products/nice-shoes');

// UUID of a product page
$wishlist->add('page://L1cJEiOOQI3VzljV');

// array, to keep your own data alongside the product
$wishlist->add([
  'key' => 'nice-shoes',
  'page' => 'products/nice-shoes',
  'data' => [
    'added' => date('c'),
  ],
]);
```

> [!NOTE]
> The identifier is `key`, the product page is `page`, and everything else you want to store on the item belongs in `data`. When you leave out `key`, Merx uses the page’s UUID.

## Store the list

`ProductList` does not persist itself. Assuming you have no Kirby user accounts, the visitor’s session is the simplest place to keep the list. Store it the same way the cart does, with [`toSessionArray()`](https://merx2.wagnerwagner.de/reference/classes/list-item.md) per item.

```php title="/site/plugins/wishlist/index.php"
<?php

use Wagnerwagner\Merx\ListItem;
use Wagnerwagner\Merx\ProductList;

function wishlist(): ProductList
{
  $data = kirby()->session()->get('wishlist', []);

  return new ProductList($data);
}

function saveWishlist(ProductList $wishlist): void
{
  kirby()->session()->set(
    'wishlist',
    $wishlist->toArray(fn (ListItem $item) => $item->toSessionArray()),
  );
}
```

Passing the stored array back into `new ProductList()` turns every entry into a `ListItem` object again. Only the page reference is stored, not the price, so prices are read from the product page again on every request. A product that got more expensive while it sat on the wishlist shows its current price.

## Show the list

```php title="/site/templates/wishlist.php"
<?php /** @var \Wagnerwagner\Merx\ProductList $wishlist */ ?>
<ul>
  <?php foreach ($wishlist as $item): ?>
    <li>
      <a href="<?= $item->page?->url() ?>"><?= $item->title ?></a>
      <?= $item->price ?>
      <?php if ($added = $item->data['added'] ?? null): ?>
        <small>added <?= date('j M Y', strtotime($added)) ?></small>
      <?php endif ?>
    </li>
  <?php endforeach ?>
</ul>
<p>Total: <?= $wishlist->total() ?></p>
```

## Move the list into the cart

Because both classes hold the same items, moving a wishlist into the [cart](https://merx2.wagnerwagner.de/reference/classes/cart.md) is a loop over [`add()`](https://merx2.wagnerwagner.de/reference/classes/cart/add.md).

```php
foreach (wishlist() as $item) {
  $site->cart()->add($item);
}
```
