wagnerwagner/merx

Allow donation or 'pay what you want'

Closed this issue · 11 comments

Hello,

I'm wondering if there would be a way with merx to allow an option where the customer determines the price they want to pay for a particular product? We have one new upcoming product in our store which will be sold a little differently, on a sort of 'donation' system where the customer pays what they want to recieve a book which will be physically shipped. Looking for a per-product solution rather than site wide.

Thanks!

I think what you want to do is already possible with Merx. Usually you add a new product to the cart like this:

$cart->add([
  'id' => 'new-shoes',
]);

The price of the cart item is generated from the product page (in this case, new-shoes). If you add the price directly to the add() method, the price from the product page will be ignored. You can do something like this:

// get the value of the price input
$userPrice = floatval(get('price'));
if ($userPrice >= 5) {
  $cart->add([
    'id' => 'new-shoes',
    'price' => $userPrice,
  ]);
} else {
  // tell user that minimum price is $5
}
rhjp92 commented

Thanks for your help @tobiasfabian - I'm using the merx starterkit so would the best way to do this be inside cart-post.php? I tried overriding the price in that function but that seemed to break it and now the item wont be added to the cart

It would be helpful if you could share the code you used inside the cart-post.php file to override the price. Based on that, I can look into the problem you have.

rhjp92 commented

Say if I do this in cart-post.php

<?php

return [
    'pattern' => 'shop/cart',
    'auth' => false,
    'method' => 'POST',
    'action'  => function () {
        $cart = cart();
        $key = $this->requestBody('id');
        $quantity = $this->requestBody('quantity', 1);
        $price = 5;
        // if item (id) is already in cart, add up quantities.
        if ($cartItem = $cart->get($key)) {
            $quantity = $cartItem['quantity'] + $quantity;
        }
        checkStock(page($key), $quantity);
        $cart->add([
            'id' => $key,
            'quantity' => compact('quantity'),
            'price' => $price
        ]);
        return $this->cart();
    },
];

I have an error message Unsupported operand types: int * array

Thanks @rhjp92 for giving additional details.

It would be good to know where exactly the error occurs - in which file, in which line.
If you have not yet activated the debug mode, you can activate it, then you will get a more detailed error message.

The error message Unsupported operand types: int * array means that at some point an array should be multiplied by an integer, which is not possible.

rhjp92 commented

Thanks for your help and patience tobias!

image

The error is occurring in this line within ProductList.php:

$value['sum'] = (float)($value['price'] * $value['quantity']);

Can you please double check the Request of this POST. Is quantity a number or an array? If present, it has to be a number.

rhjp92 commented

image

Here's the Request, quantity is 1.

I think I’ve found your problem.

This is what you do in your code:
'quantity' => compact('quantity'),

The compact() function creates an array.

You should pass the $quantity variable directly.
To ensure that a float is passed, you can prepend (float) to the variable.

 $cart->add([
  'id' => $key,
  'quantity' => (float)$quantity,
  'price' => (float)$price,
]);
rhjp92 commented

Appreciate your help! From there on was fairly straightforward to implement a donation option on products. Thanks!

Hi both of you :)

I was really happy I stumbled upon your conversation, since I need exactly that function for a social project of mine. Could you maybe give me a hint how the template side looks like? I implemented the same code to the cart-post.php (I'm using the starterkit as well), but whenever I call get('price') on my <input type="number" name="price" id="price"> it returns 0 in the cart.

I tried different names for the variables and the input, I put everything in a form element, but somehow I didn't get it to work.

Any little hint would be super helpful to me, since time is kind of rare to finish this. 😱

Thank you already! 🙏

This is my current cart-post.php

return [
    'pattern' => 'shop/cart',
    'auth' => false,
    'method' => 'POST',
    'action'  => function () {
        $cart = cart();
        $key = $this->requestBody('id');
        $quantity = $this->requestBody('quantity', 1);
        $userPrice = floatval(get('price'));
        // if item (id) is already in cart, add up quantities.
        if ($cartItem = $cart->get($key)) {
            $quantity = $cartItem['quantity'] + $quantity;
        }
        checkStock(page($key), $quantity);
        $cart->add([
            'id' => $key,
            'quantity' => (float)$quantity,
            'price' => (float)$userPrice
        ]);
        return $this->cart();
    },
];