Jump to content

Can I write a better Foreach loop to have different output?


Marco Ro
 Share

Recommended Posts

Hi, I try to make the choice of the products through the combination of two variations.  But I have some problem doing this.

Whit this code the two foreach give me back all the singular combination. Though, the value of the products are the same for both choices.

I must be able to find the value from the combination of the two variants, color + angle = product.

 This is my code now:

 <?php
    if ($page->variations->count) {
          $addcart = "<form method='post' class='padloper-cart-add-product' action='" . $config->urls->root . "padloper/add/'>";
          $addcart .= "<p>Colors</p>";
          $addcart .= "<div class='append-buttons'>";
          foreach ($page->variations as $p){
          $addcart .= "<input class='{$p->color_choose->title}' type='radio' name='product_id' id='{$p->color_choose->title}' value='{$p->id}'>" . "<label class='{$p->color_choose->title}' for='{$p->color_choose->title}'></label>" . "</input>";
        }
          $addcart .= "</div>";
          $addcart .= "<div>";
          $addcart .= "<span id='ask'></span>";
          $addcart .= "</div>";
        if ($p->angle_choose->title)
          {$addcart .= "<br /><select>";
          foreach ($page->variations as $p) {
          $addcart .= "<option name='product_id' value='{$p->id}'>{$p->angle_choose->title}</option>";
          }
          $addcart .= "</select>";}
          $addcart .= "<div class='value-button' id='decrease' onclick='decreaseValue()' value='Decrease Value'>-</div>";
          $addcart .= "<input type='number' id='number' value='1' name='qty'/>";
          $addcart .= "<div class='value-button' id='increase' onclick='increaseValue() 'value='Increase Value'>+</div>";
          $addcart .= "<br /><input class='btn-cart' type='submit' name='pad_submit' value='" . __("Add to cart") . "' /></form>";
        } else {
          $addcart = $modules->get("PadRender")->addToCart($page, $askQty = true);
        }
     ?>
    <?php echo $addcart ?>

This give me this output:

<form method="post" class="padloper-cart-add-product" action="/playwood/padloper/add/">
  <p>Colors</p>
  <div class="append-buttons">
    <input class="green" type="radio" name="product_id" id="green" value="1143"><label class="green" for="green"></label>
    <input class="green" type="radio" name="product_id" id="green" value="1141"><label class="green" for="green"></label>
    <input class="green" type="radio" name="product_id" id="green" value="1142"><label class="green" for="green"></label>
    <input class="blue" type="radio" name="product_id" id="blue" value="1139"><label class="blue" for="blue"></label>
    <input class="blue" type="radio" name="product_id" id="blue" value="1144"><label class="blue" for="blue"></label>
    <input class="blue" type="radio" name="product_id" id="blue" value="1145"><label class="blue" for="blue"></label>
    <input class="army" type="radio" name="product_id" id="army" value="1140"><label class="army" for="army"></label>
    <input class="army" type="radio" name="product_id" id="army" value="1146"><label class="army" for="army"></label>
    <input class="army" type="radio" name="product_id" id="army" value="1147"><label class="army" for="army"></label>
  </div>
  <div>
    <span id="ask"></span>
  </div><br>
  <select>
    <option name="product_id" value="1143">90°</option>
    <option name="product_id" value="1141">105°</option>
    <option name="product_id" value="1142">150°</option>
    <option name="product_id" value="1139">90°</option>
    <option name="product_id" value="1144">105°</option>
    <option name="product_id" value="1145">150°</option>
    <option name="product_id" value="1140">90°</option>
    <option name="product_id" value="1146">105°</option>
    <option name="product_id" value="1147">150°</option>
  </select>
  <div class="value-button" id="decrease" onclick="decreaseValue()" value="Decrease Value">-</div>
  <input type="number" id="number" value="1" name="qty">
  <div class="value-button" id="increase" onclick="increaseValue() " value="Increase Value">+</div>
  <br><input class="btn-cart" type="submit" name="pad_submit" value="Add to cart">
</form>

 

I need 1 input radio for each color and 1 option for the angle.

I can do somethings like this? what I can do?

Thank you.

Link to comment
Share on other sites

As far as I understand you'd like to have 3 input radios ( one for each color green/blue/army) and 3 options too (90°.105°.150°) right?

This is not happening because your $page->variations are 9 indeed, as per their id's.

Also, I found very confusing to have unnecessary html inside a php block where just a foreach loop could be sufficient, but it's a personal preference I suppose.

  • Like 1
Link to comment
Share on other sites

Hi @3fingers Thank you for your reapply.

Yes you are right about what I would like. But I have to make 1 product for every combination in the backend and the products are 9. The good things it's that I could select these 9 products using just the singole variation input, the 3 input radios an 1 select with 3 option. and that give me back the the value to which it corresponds and send it to the cart. 

Yes probably it's not about how write the foreach loop (I don't know), if there aren't a solution with the api. The foreach loop in all cases it will always give me a input for each value. Maybe it's about how make the products variation in the backend. but I don't really know how setup the fields in the backend.  

About the confusing, yeah could be, I'm not so advance! I need add style and js iteration and in this way works:)

 

 

Link to comment
Share on other sites

Hi Marco (ciao Marco, compaesano ;)),

I'm supposing you're following padloper docs (I never used it), but I suggest you to follow this nice categorization of contents by kongondo, to grasp some concepts :

https://processwire.com/talk/topic/3579-tutorial-approaches-to-categorising-site-content/ 

As I said, I never used Padloper so I don't know its api in details, but I would go for Fieldtype Page for product variations (color, angle, etc...).

  • Like 3
Link to comment
Share on other sites

@3fingers ciao! Thank you for the link. I had already read it before started to work, it helped me to better understand how pw works. 

With Padloper the variable system works similar but a little different from the categorization, I mean, you have to build the products variation like you add the category, but if you have two variation you have to create 1 products for each combination. like you have 2 sub_category. 

  • ( category)               Shop          
  • (subcategory)                 Product         
  • (Variation)                             Red XL  
  • (variation)                              Red S 
  • (variation)                              Blue XL

 Now that i think this maybe I can Make a Sub_Sub_category ummm...

  • ( category)               Shop          
  • (subcategory)                Product         
  • (Variation)                             Red
  • (Sub_Variation)                           XL
  • (Sub_Variation)                           S
  • (variation)                              Blue 

I will try to this! Not sure it's possible but will see. Thank you!!

 

@elabx hola! thank you for the link. yes this look nice system, easier and more beautiful but look like give me the same one value for every products. 
Anyway it's nice solution I will show to my boss :).  Thank you!

Link to comment
Share on other sites

29 minutes ago, MarcoPLY said:

look like give me the same one value for every products.

No. You enter your own values for every single variation. For instance, you can enter price, SKU, quantity for the following combinations of the same thing

  1. Blue, Small
  2. Blue, Large
  3. Etc

Variations can contain two or more attributes, e.g. Blue (colour), Small (size), Short Sleeves (arms), Plain (style) 

Link to comment
Share on other sites

Hi @kongondo I like your modules. I don't understand if I can choose a product  with a combination of 2 input?  

I mean, I make all the variation 

  1. Blue, S       =  ID
  2. Blue, L       =  ID 2
  3. Red, S        =  ID 3
  4. Red, L        =  ID 4

Then can I make only one input for Color and one Input for Size?  and when I add the product to the cart, depending on the choices, I sent the id connected to the combination. Can I do this?  or I need anyway to add a custom js to process this? 

Link to comment
Share on other sites

1 hour ago, MarcoPLY said:

Then can I make only one input for Color and one Input for Size? 

I don't understand this. What input is this? The module works like this:

A. Define Field/Inputfield

  1. Create and edit a Field of type Variations
  2. In the field settings, create the custom inputs that will be needed for each product variation irrespective of its attributes. For instance, price, quantity, sku, etc. Currently, you can only do this in the field settings which means non-superusers cannot create custom inputs. This will change in future releases
  3. Save

B. Define Attributes (and their values) and Build Variations

  1. Create attributes and their values. These are independent of each other and of products. Meaning, you can reuse, e.g. Size attribute  with other attributes, e.g. Colour
  2. Each attribute has one or more values. E.g. the attribute Size can have Small, Medium, Large, etc. The attribute Colour can have Blue, Orange, Yellow, etc values.
  3. You then build variations. E.g., build the variations for a Product called "ProcessWire T-shirt"
  4. You give the variations (definition basically) a name
  5. You then add attributes you want, e.g. Color and Size. However, not all the values of these attributes will be available automatically. So, you need the next step
  6. You then select the values of the attributes you want. For instance, for size, you might want all the available sizes, so you add them all
  7. For Color, let's say you only want two colours, so you add Yellow and Blue
  8. Save and link that variation to your product page and you are done. You get a table with a combination of all of your available Sizes and Colours for the given product (un-editable) as well as input for the custom inputs you created in A., i.e. Price, Quantity, SKU etc.
  9. Each individual variation (i.e. one row in your table of variations) has its own ID. Just simple 1,2,3,4 etc.
  10. In our example, a row would consist of color,size, price, quantity,SKU. The price, quantity and SKU are inputs where you specify the respective values in relation to that particular variation.
2 hours ago, MarcoPLY said:

and when I add the product to the cart, depending on the choices, I sent the id connected to the combination. Can I do this?  or I need anyway to add a custom js to process this? 

Frontend implementation is up to you. You use the available combinations as returned to you by the Inputfield to build the markup for product selection. You will need custom JS to send values back to the server. Have a look at the documentation here. You have access to each combination/variation ID as follows:

$out = "";
$variations = $page->variations;// returns a VariationsArray which is a WireArray derived object
foreach($variations as $variation) {
	$out .= 
		"<input type='hidden' value='{$variation->id}'>" .// variation/combination ID
		"<p>Colour: {$variation->colour}</p>" .
		"<p>Size: {$variation->size}</p>" .
		"<p>Price: {$variation->price}</p>";
}

echo $out;

 

  • Like 2
Link to comment
Share on other sites

Thank you for your reapply @kongondo. If I have understand well what you say is similar like you show in your video.
I see the different between your module and Padlopar, and I like your module. 

My problem is about the frontend. In the way my output is:

  • Input ( Color, Size )
  • Input ( Color, Size )
  • Input ( Color, Size )
  • Input ( Color, Size )
  • ...

But I have like 10 colors and 3 size. So, I will have 30 different products combination. On the frontend 30 inputs are to much to show on the page, ok I can use select with options, but it isn't friendly interface.  

What I would like to do is have 10 inputs for choose the color and 3 inout for the size. in this way the interface is more friendly. 

 

I try to make a two differente loops for color and size, but what I did in the first post of corse don't works. do you think there is a way?

This is the situation with the code in the first post: 
What I would like to do is have one input for a each color, and 1 input for each angle.

5a9820ab84ba7_Schermata2018-03-01alle16_47_12.png.8c4ebf9dc6f82e46a656f7fa539a7916.png

 

 

Link to comment
Share on other sites

1 hour ago, MarcoPLY said:

But I have like 10 colors and 3 size. So, I will have 30 different products combination. On the frontend 30 inputs are to much to show on the page, ok I can use select with options, but it isn't friendly interface.  

What I would like to do is have 10 inputs for choose the color and 3 inout for the size. in this way the interface is more friendly. 

Now I understand you clearly. You are right, 30 inputs are not great, even with selects. I see several options all of which involve JavaScript for the friendly front-end side of things

  1. Together with the inputs you currently have above (your colour and angle inputs), add hidden markup, maybe a <ul> list with the values for each combination, e.g. <li data-colour='green' data-angle='90' data-some-value-for-this-combination='abc'>green-90</li>, etc. On click add to cart, if both colour and angle have selections, use JavaScript/jQuery to get the <li> whose data-colour == "selected colour" AND data-angle == "selected angle". You then update your cart depending on the selected combination, e.g. using its data-some-value-for-this-combination, which could be its ID. @note: if the some-value is a price, you only use it for visual feedback to the user. Prices should be determined server side
  2. Something similar to above except we send the selected combination server-side immediately using Ajax so that we return and display the value of "some-value-for-this-combination"

I had another option but I have forgotten it in the course of typing, hehe!

OK, server-side, you need somewhere to stay your combinations and their values. I don't know how you are storing this but it should be pretty straightforward to find your product using value of data-colour and data-angle. If you have the different colours and angles stored as pages, then the markup should ideally have the respective page IDs and send these back using Ajax. E.g., rather than green, you would have data-colour="1234" and data-angle="5468". 

Hope the above make sense. 

  • Like 2
Link to comment
Share on other sites

Maybe a bit an aside from what you are trying to achieve but, for me, the simplest solution would be using Snipcart custom-fields (of course this is something somewhat unrelated from PadLoper and its various payments gateways integration, it is a different approach as a whole).

I would create 10 Fields of type Page for colours, and other 3 for angles or whatever (it could be accomplished also with 2 Select Options Fieldtype).

You don't even need to insert those fields inside every product page, they could live under whatever "setting" page you want.

You iterate and then you echo them as options on frontend on the product page. The user can then choose which combination of the 30 would have for his product and, at checkout stage, you pass those options as custom fields and alter the product price based on those criteria.

As I said it is a completely different approach, but I would probably follow that route. :)

  • Like 1
Link to comment
Share on other sites

@kongondo thank you! both solution could works. probably the second could be nice, because I also will have friendly backend.

Maybe I can make the products like you say, separated. 1 page for colors and the 3 angles. but I want try to make then like variation, with a specific class (like a category) and then echo the 2 foreach filter by the category.  Then I have to understand how with Ajax send to the cart like 1 single product.  

Do you think could works? The critical part will be the foreach and send via ajax, I'm not sure I can do it but I try! :) 
Thank you!!

@3fingers thank you. this could be an away. I read about Snipcart. We have thinked to integrate an outside process of cart and checkout, instead of using Padloper. But honestly Padloper is very great and ductile tools. It's possible do more or less everything, with a bit of experience. Only the checkout isn't very the best, I will like change the progress step and it isn't easy to do. But all the Cart part it's very nice! and shipping, tax and payment process are easy to setup and above all integrated with pw. 

 

Update.
This works, filter the input and I can see only the one have the variation color and the variation angle. 

foreach ($page->variations as $p){
          if ($p->color_choose->title){
            $addcart .= "<input class='{$p->color_choose->title}' type='radio' name='product_id' id='{$p->id}' value='{$p->id}'>" .
                        "<label class='{$p->color_choose->title}' for='{$p->id}'></label>" . "</input>";
        }
      }
$addcart .= "<br /><select>";
foreach ($page->variations as $ps) {
        if ($ps->angle_choose->title) {
            $addcart .= "<option name='product_id' value='{$ps->id}'>{$ps->angle_choose->title}</option>";
            }
          }
$addcart .= "</select><br>";

But I don't know how send via ajax this two info in one product. :( 
At moment I use the example I read in the documentation: https://www.padloper.pw/documentation/making-it-ajax/
In this way in the cart arrive only the Color choose.

Or 

The solution cloud be to hook ___addProduct in card-add-product. somethings like this: 

 

Edited by MarcoPLY
update
Link to comment
Share on other sites

7 hours ago, MarcoPLY said:

Update.
This works, filter the input and I can see only the one have the variation color and the variation angle. 

Maybe the code can be cleaned up a little? E.g. no need for two loops. I've also cleaned up the HTML a little bit (e.g. id=color_page_id rather than id=page_id), given the select an ID so you can space it out as needed instead of using a <br>, etc  :-) . It also needs a name attribute.

$colors = '';
$angles = '';
foreach ($page->variations as $p){
	// add colors
	if ($p->color_choose->title){
		$colors .=
			"<input class='{$p->color_choose->title}' type='radio' name='product_id_color' id='color_{$p->id}' value='{$p->id}'>" .
				"<label class='{$p->color_choose->title}' for='color_{$p->id}'></label>" . 
			"</input>";
	}
	
	// add angles
	if ($p->angle_choose->title) {
		$angles .=
		"<option value='{$ps->id}'>{$ps->angle_choose->title}</option>";
		}
	}
}

$angles = "<select id='angles' name='product_id_angle'>{$angles}</select>";

// add colors and angles markup to $addcart
$addcart .= $colors . $angles;

 

Edited by kongondo
error in name attribute
  • Like 1
Link to comment
Share on other sites

5 hours ago, MarcoPLY said:

But I don't know how send via ajax this two info in one product. :( 
At moment I use the example I read in the documentation: https://www.padloper.pw/documentation/making-it-ajax/
In this way in the cart arrive only the Color choose.

This is most likely because you had bad HTML in your markup. Your angles <select> does not have a name attribute; instead you put the name attribute in the <option>. See my code above with the refactored code.

Edited by kongondo
  • Like 1
Link to comment
Share on other sites

I link your code! yes it's cleaner. Thank you.

I see missing the name='product_id' to the <select> but when I add it to the code, the cart pass only the angle product. (like pass the last value)
The solution could find a way to adding multiple products in one time, or pass two products inside to the 
product_id but I don't know it's possible.

 

Link to comment
Share on other sites

1 hour ago, MarcoPLY said:

I see missing the name='product_id' to the <select> but when I add it to the code, the cart pass only the angle product. (like pass the last value)
The solution could find a way to adding multiple products in one time, or pass two products inside to the 
product_id but I don't know it's possible.

Oops, that was my mistake. the radio input and select were sharing a name, product_id. I have renamed them to product_id_color and product_id_angle respectively. This does not solve your problem though. If you want to combine the values of product_id_color and product_id_angle, you need JavaScript. You can either create a hidden input product_id whose value  is dynamically changed to be the combined values of product_id_color and product_id_angle or on form submit, do the combination then. This assumes you cannot do the combination server-side. That combined value could look like 1234_5678 where 1234 is the value of the color and 5678 is the value of the angle. Server-side, you split/explode the string at "_". I could write some JavaScript later (for the values combination) if you are struggling with that.

On the server-side, how are you handling things? Where is the form being submitted? Are you using Padloper? What post input does your system expect, product_id? We can help better if we have this info. Or maybe you mentioned this already and I missed it?

Edited by kongondo
clarity
  • Like 1
Link to comment
Share on other sites

yes this is true, I think I need do this with javascript.

yes I use Padloper, I followed all the documentation, and have made all the pages like is in the tutorial. Also using the ajaxified for the cart buttons. After I changed the cart-view templates quite a lot, but don't have tuched the cart-add-product.

This is my ajax:

    // jQuery example of how to make add to cart buttons ajaxified
    $( ".padloper-cart-add-product" ).submit(function( event ) {

      event.preventDefault();
      var $form = $(this);
      var url = $form.attr("action");

      // Send the data using post
      var posting = $.post(url, $form.serialize());
      var timer = 4000;
      posting.done(function(data) {
        if (data.errors) {
          var str = '';
          $.each(data.errors, function(i, val) {
            str = str + val;
          });
          $("<div id='colorchoose'></div>").appendTo("#ask").html("Please choose a color").delay(4000).fadeOut(timer);
        } else {
          $("#cart-trigger").find("#totalQty").html(data.totalQty).end();
          $("<div id='conferm'></div>").appendTo("#contact").html("<span>Your products is Add!<br>check your cart <a href='" +rooturl+ "cart'>here</a> or keep to shopping</span>").delay(4000).fadeOut(timer);
        }
      });
    });

 

This is my cart-add-product that it's ugual to the original in the documentation 

<?php namespace ProcessWire; ?>
<form method="post" class="padloper-cart-add-product" action="<?= $config->urls->root ?>padloper/add/">
  <?php
    if ($askQty) echo "<input type='number' name='qty' value='1'/>";
    if ($redirectUrl) echo "<input type='hidden' name='redirect' value='$redirectUrl'/>";
    if ($variationId) echo "<input type='hidden' name='variation_id' value='$variationId'/>";
    echo "<input type='hidden' name='product_id' value='{$product->id}'/>";
  ?>
  <input class='btn-cart' type='submit' name='pad_submit' value='<?= __("Add to cart") ?>' />
</form>

 

In the backend at moment I have make the product with: 1 variation for the Color and 1 variation for the Angle. 
I add more or less your php code and this give me this output:

<form method="post" class="padloper-cart-add-product" action="/playwood/padloper/add/">
  <p>Colors</p>
  <div class="append-buttons">
    <input class="green" type="radio" name="product_id" id="color_1143" value="1143"><label class="green" for="color_1143"></label>
    <input class="blue" type="radio" name="product_id" id="color_1139" value="1139"><label class="blue" for="color_1139"></label>
    <input class="army" type="radio" name="product_id" id="color_1140" value="1140"><label class="army" for="color_1140"></label>
    <br>
    <select id="angles" name="product_id">
      <option value="1935">90°</option>
      <option value="1936">105°</option>
      <option value="1937">150°</option>
    </select><br>
  </div>
  <div><span id="ask"></span></div>
  <div class="value-button" id="decrease" onclick="decreaseValue()" value="Decrease Value">-</div>
  <input type="number" id="number" value="1" name="qty"><div class="value-button" id="increase" onclick="increaseValue() " value="Increase Value">+</div>
  <br>
  <input class="btn-cart" type="submit" name="pad_submit" value="Add to cart">
</form>

 

You say true I have to use js for combine the two values and send it in the cart like a single product_id, also because they have some pad_price tax and shipping. Maybe it is enough send only the two variable titles color and angle name. I think... but not sure how do it. 

Thank you kongondo for your help! 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...