Let's get to the root of what you're asking:
I need to simulate $this (whatever model, helper its referring to) so
that this block works. I am without much success.
The addtocart.phtml view is called via this xml declaration in app/design/frontend/base/default/layout/catalog.xml:
<block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
That means that the $this
you're referring to is the model catalog/product_view
. Assuming no rewrites, that should translate to the class file Mage_Catalog_Block_Product_View
, found in app/code/core/Mage/Catalog/Block/Product/View.php.
So, with all of that aside, you want $this
to behave as if it's being called from the block. Assuming you're still using your standalone script called via AJAX, you should replace $this
with $block
- loading that as a new instance of the block model referenced above. This may lead to undesired effects - for instance - $block->getProduct()
won't work.
Edited standalone addtocart.phtml:
Based on your edit, I have updated this answer:
<?php
require_once('/var/www/Staging/public_html/app/Mage.php');
umask(0);
Mage::app();
//ensure that the value is legitimate
if($_POST && is_numeric($_POST['value'])){
$value = $_POST['value'];
}
//pass this in your ajax call for the add button
if($_POST && is_numeric($_POST['product_id'])){
$product_id = $_POST['product_id'];
}
$helper = Mage::helper('core'); //for translation
$block = new Mage_Catalog_Block_Product_View(); // not best practice, but neither are standalones
$product = Mage::getModel('catalog/product')->load($product_id); // no need to use the _ here, it's not protected/private; additonally Mage::registry won't work because you're technically not on a product detail page
$buttonTitle = ''; //you are using this, but it isn't set
?>
<div class="add-to-cart">
<label for="qty"><?php echo $helper->__('Qty:') ?></label>
<input type="text" name="qty" id="qty" maxlength="12" value="<?php echo $block->getProductDefaultQty($product) * 1 ?>" title="<?php echo $helper->__('Qty') ?>" class="input-text qty" />
<button onclick="window.location = '<?php echo Mage::helper('checkout/cart')->getAddUrl($product);?>'" type="button" title="<?php echo $buttonTitle ?>" class="button btn-cart" id='$value'><span><?php echo $buttonTitle ?></span></button>
</div>
Some other thoughts:
You're using $_GET['value']
- don't accept unfiltered input from users. You're placing this directly into the add to cart button. Anyone could munge this to inject scripts and other bad stuff onto a page via the URL. This is called XSS - read more here: http://phpmaster.com/php-security-cross-site-scripting-attacks-xss/
If $_GET['value']
is your vendor, consider using vendor
- it's semantic.
How I would implement this:
So, your approach isn't wrong, per se; it'll work. But here's how I would do it:
- Create a vendor plugin
- Create a custom controller action that takes an argument of
vendor
, using $this->getRequest()->getParams()
- which filters natively for nefarious stuff
- Set the output type of the controller to text/html, set to a blank theme that has no script includes or layout elements (structural blocks, etc.)
Or, instead of rolling your own, use the Unirgy Marketplace plugin which does what you're trying to do - and does it very well!
http://www.unirgy.com//products/umarketplace/magento-multi-vendor-marketplace
So I came up with a solution that works just awesome. I added another controller action and a model to do the Magento Interactions during my ajax calls. So let me show you how it's done, I hope somebody can profit from this sooner or later :)
My new Action:
public function updateAction ()
{
//Instantiate Product Model
$productModel = Mage::getModel('doorconfig/product');
//Get Updated Values from the Model
$currentProduct = $productModel->getProduct($_POST);
$currentProductId = $currentProduct->getId();
$currentProductUrl = $currentProduct->getProductUrl();
$currentPrice = $productModel->getPrice($currentProductId);
$currentType = $this->getRequest()->getPost('doorconfig_type');
$currentSize = $this->getRequest()->getPost('doorconfig_size');
$currentProductBaseImgUrl = $productModel->getDoorBaseImgUrl($currentType,$currentSize);
//Populate Resultarray
$result = array("currentProductId"=>$currentProductId,"currentPrice"=>$currentPrice,"currentProductUrl"=>$currentProductUrl,"currentProductBaseImgUrl"=>$currentProductBaseImgUrl);
//Encode Result in JSON
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
return $result;
}
My model just got most of the business logic from my block, so nothing special to point out about that.
And finally the updated Ajax section which now triggers my new controller action, receives the result as a JSON encode and changes the values in the DOM:
<script type="text/javascript">
var $price = "";
var $baseImgUrl = "";
var $productUrl = "";
var $productId = "";
var $f = $j("#attributeform");
var $formData;
var $currentStoreUrl = "<?php echo $currentStoreUrl ?>";
function ajaxUpdate()
{
$j.ajax({
url: "/doorconfig/index/update",
type: "POST",
data: $formData,
dataType: "json",
success: function(data)
{
$productId = data.currentProductId;
$price = data.currentPrice;
$baseImgUrl = data.currentProductBaseImgUrl;
$productUrl = data.currentProductUrl;
$j("#result").text($price);
$j("#addtocart").attr('href', $currentStoreUrl + "checkout/cart/add?product=" + $productId + "&qty=1");
$j("#productimg").attr('src', $baseImgUrl);
console.log(data);
},
error: function(error)
{
console.log("Error:");
console.log(error);
alert("ERROR");
}
});
};
$j(document).ready(function()
{
$j("#result").text('<?php echo $defaultProductPrice; ?>');
$j("#addtocart").attr('href', '<?php echo $currentStoreUrl . "checkout/cart/add?product=" . $defaultProductId . "&qty=1" ?>');
$j("#moreinfo").attr('href', '<?php echo $defaultProductUrl; ?>');
$j("#productimg").attr('src', '<?php echo $defaultProductImgUrl; ?>');
$j("#attributeform")[0].reset();
$j("form[name=attributeform]").change(function ()
{
$formData = $f.serialize();
ajaxUpdate();
})
});
</script>
If you need any further explanation or wanna improve something please comment :)
Best Answer
Actions in layout xml configs are just a block method call. So if you see construction like
That is equivalent to
Or if block
cart_sidebar
was already created in layout xml