Forum
Problem Adding Comments to Product Page
I have a product detail page which pulls a particular template seen below. I would like to include a comments function for reviews, but given that it is a function - it doesn't work in the template. I can't remove the function from the template and inject it afterward, because it's part of a tab system on the product description page and requires pulling perch:shop tags for data from the template. How can I include this comments section without causing a php error?
<perch:categories id="category" set="products" label="Category">
<a href="/<perch:category id="catPath">"><perch:category id="catTitle" /></a>
</perch:categories>
<div style="max-width: 1200px">
<h1><perch:shop id="title" type="text" label="Title" required="true" order="2" /></h1>
</div>
<perch:shop id="slug" type="slug" editable="true" indelible="true" label="Slug" for="title sku" order="10" divider-before="Meta data" suppress="true" />
<section id="product-listing">
<div id="product-images">
<div id="sku-block">SKU: <perch:shop id="sku" type="text" label="SKU" required="true" order="1" /></div>
<perch:shop id="image" type="image" label="Main Product Image" order="4" width="800" height="800" suppress="true"/>
<a class="gallery" href="<perch:shop id="image" type="image" width="600">"><img id="main-image" src="<perch:shop id="image" type="image" width="430" height="430" crop="true" />" alt="<perch:shop id="title" type="text" /> image"/></a>
<perch:shop id="image" type="image" width="80" height="80" density="1.6" crop="true" suppress="true" />
<perch:repeater id="additional-images" label="Additional Images">
<perch:before>
<div id="img-gallery">
<ul>
</perch:before>
<li>
<a class="gallery" href="<perch:shop id="extra-img" type="image" label="Additional Photo" width="600" required="false" />"><img src="<perch:shop id="extra-img" type="image" width="90" height="90" crop="true" />" alt="Additional Product Photo" /></a>
</li>
<perch:after>
</ul>
</div>
<script>
jQuery('a.gallery').colorbox();
</script>
</perch:after>
</perch:repeater>
</div>
<aside id="buy-info">
<h3>Description:</h3>
<p><perch:shop id="description" type="textarea" label="Short Description" editor="textile" order="3" markitup="true" size="s" /></p>
<perch:repeater id="highlights" label="Product Highlights">
<perch:before>
<h3>Product Highlights:</h3>
<ul class="info-list">
</perch:before>
<li><perch:shop id="highlight" type="text" label="Focus Feature" required="false" /></li>
<perch:after>
</ul>
</perch:after>
</perch:repeater>
<hr />
<span class="price">
<perch:member has-tag="dealer">
<perch:shop id="trade_price" type="shop_currency_value" label="Dealer Price" size="s" min="0" step="any" runway="true" />
<perch:else:member />
<perch:shop id="on_sale" type="checkbox" value="1" label="Use Sale Price" suppress="true" />
<perch:if id="on_sale" value="1">
<perch:shop id="sale_price" type="shop_currency_value" label="Sale Price" size="s" min="0" step="any" />
<perch:else />
<perch:shop id="price" type="shop_currency_value" label="Price" size="s" min="0" step="any" />
</perch:if>
</perch:member>
</span>
<h3><perch:shop id="stock_status" type="shop_stock_status" label="Stock Status" divider-before="Stock" required="true" /></h3>
<perch:shop id="stock_level" type="number" label="Stock Level" size="s" suppress="true" />
<perch:shop id="stock_location" type="shop_stock_location" label="Count Stock" suppress="true" />
<perch:shop id="max_in_cart" type="number" label="Max Quantity in Cart" size="s" suppress="true" />
<perch:form id="add_to_cart" app="perch_shop" action="/bag">
<perch:input id="product" type="hidden" env-autofill="false" value="<perch:shop id="productID" type="hidden" env-autofill="false" />" />
<perch:input type="submit" value="Add to Bag" class="buybutton" />
<perch:input id="qty" value="1" type="number" min="0" placeholder="1" class="quantity" />
</perch:form>
<perch:shop id="catalog_only" type="shop_catalog_only" label="Catalog Only" type="hidden" suppress="true" />
<perch:shop id="tax_group" type="shop_tax_group" label="Tax Group" required="true" suppress="true" />
<perch:shop id="status" type="shop_status" label="Status" suppress="true" />
<perch:shop id="brand" type="shop_brand" label="Brand" allowempty="true" suppress="true" />
<perch:shop id="requires_shipping" type="shop_requires_shipping" label="Requires Shipping" divider-before="Shipping" suppress="true" />
<perch:shop id="weight" type="number" label="Shipping weight" size="s" suppress="true" />
<perch:shop id="width" type="number" label="Width" size="s" suppress="true" />
<perch:shop id="height" type="number" label="Height" size="s" suppress="true" />
<perch:shop id="depth" type="number" label="Depth" size="s" suppress="true" />
<div class="sharethis-inline-share-buttons"></div>
</aside>
<div id="details" class="box-node">
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'Overview')" id="defaultOpen">Overview</button>
<button class="tablinks" onclick="openTab(event, 'Specs')">Specs</button>
<button class="tablinks" onclick="openTab(event, 'Included')">In The Box</button>
<button class="tablinks" onclick="openTab(event, 'Reviews')">Reviews</button>
</div>
<div id="Overview" class="tabcontent">
<perch:shop id="overview" type="textarea" label="Overview" editor="ckeditor" html="true" size="s" />
</div>
<div id="Specs" class="tabcontent">
<table id="specs">
<tr>
<th>Weight:</th>
<td><perch:shop id="weight" /></td>
</tr>
<tr>
<th>Width:</th>
<td><perch:shop id="width" /></td>
</tr>
<tr>
<th>Height:</th>
<td><perch:shop id="height" /></td>
</tr>
<tr>
<th>Depth:</th>
<td><perch:shop id="depth" /></td>
</tr>
</table>
</div>
<div id="Included" class="tabcontent">
<perch:repeater id="included-list" label="In the Box">
<perch:before>
<ul class="info-list">
</perch:before>
<li><perch:shop id="included-qty" type="text" format="#:0" maxlength="3" label="Quantity Included" required="true" /> - <perch:shop id="in-the-box" type="text" label="Included Item" required="true" /></li>
<perch:after>
</ul>
</perch:after>
</perch:repeater>
</div>
<div id="Reviews" class="tabcontent">
<?php
perch_comments_form('<perch:shop id="sku" type="text" />', '<perch:shop id="title" type="text" />', array(
template => 'review_form.html'
));
perch_comments('<perch:shop id="sku" type="text" />', array(
template => 'review.html'
));
?>
</div>
</div>
</section>
<script>
function openTab(evt, tabName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
}
document.getElementById("defaultOpen").click();
</script>
Do it the other way around - generate the comments first, then pass the result into the product template.
My trouble with that was I would need to pull the SKU and title of the product from the shop template and then pass it back into the comments function as a variable for the ID and name tags. If I run the comments function first, apply the contents to a variable, and pass it into the shop product function, I wouldn't be able to see it in code to add the shop tags before it was processed by the product template.
There's a few ways you can deal with that. One might be to use an
each
callback to add the comments.Another is to use a combination of
skip-template
andreturn-html
to get both the data about the product and the templated HTML. Include a placeholder string in your template, then replace it out before displaying.Something roughly along the lines of:
Thanks, that makes a lot of sense to use str_replace. I seem to be misunderstanding the arrays passed into the $product var when comments are called. Perch is throwing an error in debug saying that the
[0]
and['sku']
are undefined. I would define the sku, but I thought that was the purpose of using it passed into the $product without a template?My Page:
Hello Kevin,
You can always print your array, check what you have and adjust your code accordingly:
If
$product[0]
is undefined, it might be becauseperch_shop_product()
could not find a product with the slug you passed to it.I see how it would make sense to check for using a particular user entered SKU, but given that this product was displaying fine before this modification with just perch_shop_product() I think it's more my misunderstanding of what Drew was doing in that particular portion of his answer. This has been my testing SKU page for several days working fine, so it has to be something with the new pass through for comments.
The
skip-template
option returns the product content in an array. Thereturn-html
option returns the templated product content.$product
here is an array. Whatskip-template
returns would normally be in$product[0]
. Whatreturn-html
returns would be in$product['html']
.If
perch_shop_product()
finds your product,$product[0]
should not be undefined.So, does
$productSlug = perch_get('s')
get you the product slug?It seems that perch_get('s'); is not pulling the slug as you said; it simply outputs a blank value. But when perch_shop_product(); is called, it works just fine. Is the variable being passed to the page from the previous link a different method? There are no errors or content when I just get and echo the results.
What does your product page URL look like? And if you are using Runway, what does your route look like?
The product page URL is
https://www.site.com/product/slug-goes-here
. I am using Runway, so my routes for the page are:products/[slug:catPath]
andproducts/[slug/slug:catPath]
. I was able to use standard PHP to grab the URL and trim it to a variable for the template to load just to see if the rest of the code worked with a slug, but it seems to break the comments, repeaters, and members checks.Ok. First lets tackle the basics:
perch_get()
: https://docs.grabaperch.com/functions/utilities/perch-get/If you have a page
product.php
and a product URL isexample.com/product?unicorn=not-real
,perch_get('unicorn')
returnsnot-real
.If you want to display the same page as
example.com/product/not-real
, your route for that page would beproduct/[slug:unicorn]
. Nowperch_get('unicorn)
still returnsnot-real
.If your page is
https://www.site.com/product/slug-goes-here
, your route should beproduct/[slug:s]
to be able to get the slug withperch_get('s')
. This is the equivalent tosite.com/product?s=slug-goes-here
.Now let's look at your pages and routes
The routes you listed looks like are used for product listing on the page
/products
. What page do you want to display the product details on? Same page?I read the documentation on perch_get(), but wasn't sure if that meant the product routes were adding queries to every page before rewrite.
The page that lists the categories is /products. The current page I'm working on is the /product page, which displays a single product's details.
In that case, you should add a route to
/product
. Addingproduct/[slug:s]
should do the trick. Then you can useperch_get('s')
to get the product slug.Oh hang on a second, I apologize - I was looking at the wrong page with my phone instead of on desktop when I copied the routes. The current route for the product display page I'm working on is already
product/[slug:s]
. Which is why when I used standard PHP to pull the slug off the URL and assign it to the variable, it grabbed the page. I'm not sure why perch_get('s'); isn't getting the same result.I see that the page is loading with my standard PHP variable of the URL slug with the comments, but for some reason my prices are not listening to the members conditionals, and the buy button and quantity fields are being displayed blank.
https://interfitphoto.com/product/interfit-s1-acbattery-powered-hss-ttl-flash/
Ok so the route is actually working. If you look at your debug message, you'll see:
If you open your browser dev tools, you will find your
perch:form
andperch:members
tags are not rendered.I would actually use Drew's other suggestion:
And in your product template you can display the comments form and the comments like so:
That works! The only strange thing is that perch_get('s'); still doesn't seem to work. I have been using basic PHP to get the slug:
As always, thank you so much for your help!