我正在尝试更新其他人的代码,该代码使用XMLHttpRequest设置从服务器获取产品信息,以用于某些SilverStripe模板。我想从 Product 中获取 url(( 函数.php这样我就可以使用它来获取产品数据对象的 url 并将其发送到 Google Analytics。但是,简单地将其附加到现有的add_fields数据是行不通的 - url 函数不会被检索。
我对XMLHttpRequests不是很熟悉,所以我对在这里做什么一无所知。
以下是获取产品数据的 JavaScript 代码:
document.addEventListener("DOMContentLoaded", function(event) {
var productCatalogService = (function() {
var endpoint = "/api/v1/Product/";
return {
'getProductById': function(id, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', endpoint + id + ".json?add_fields=NutritionalInformationLabelURL,SortOrder,BeautyShotURL,url,Recipe"); //url function is not grabbed
xhr.onload = function() {
if (xhr.status === 200) {
callback && callback(JSON.parse(xhr.responseText));
}
else {
console.error('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send();
}
};
})();
var utils = (function() {
return {
'removeClass': function(node, className) {
node.className = node.className.replace(className, '');
return node;
},
'addClass': function(node, className) {
node.className = node.className.replace(className, '');
node.className += " " + className;
},
'hasClass': function(node, className) {
return node.className.indexOf(className) >= 0;
}
}
})();
var changeProduct = function(product) {
var name = document.querySelector('.product-name'),
subname = document.querySelector('.product-subname'),
tagline = document.querySelector('.product-tagline'),
description = document.querySelector('.product-description'),
beautyShot = document.querySelector('.beauty-shot'),
nutritionFacts = document.querySelector('.ingredients-list'),
mobileNutritionLabel = document.querySelector('.mobile-nutrition-label img'),
nutritionLabel = document.querySelector('.nutritional-label img'),
recipeName = document.querySelector('.recipe-name'),
recipeDescription = document.querySelector('.recipe-description'),
recipeContainer = document.querySelector('.recipe-container');
name.innerHTML = product.Name;
subname.innerHTML = product.SubName;
description.innerHTML = product.Description;
tagline.innerHTML = product.Tagline;
beautyShot.src = product.BeautyShotURL;
if(product.NutritionalInformationLabelURL){
nutritionLabel.src = product.NutritionalInformationLabelURL;
mobileNutritionLabel.src = product.NutritionalInformationLabelURL;
}
if(product.NutritionFacts){
nutritionFacts.innerHTML = product.NutritionFacts;
if(utils.hasClass(nutritionFacts, 'hidden')) {
utils.removeClass(nutritionFacts, 'hidden');
}
} else {
utils.addClass(nutritionFacts, 'hidden');
}
// var pagePath = product.url();
console.log(product.url); //returns undefined
typeof(ga) !== "undefined" && ga('send', 'pageview', {
'page': location.pathname, //want to use the url() function in Product.php here
'title': product.PageTitle
});
};
NodeList.prototype.forEach = Array.prototype.forEach;
var products = document.querySelectorAll('.carousel-products .product');
products.forEach(function(product) {
product.onclick = function() {
var productId = product.getAttribute('data-product-id');
productCatalogService.getProductById(productId, function(product) {
console.log(product);
changeProduct(product); //add recipe data to be pulled in here (fields are above)
});
};
});
});
产品.php
<?php
class Product extends DataObject implements Pageable, Searchable {
private static $api_access = true;
private static $db = [
'Name' => 'varchar(255)',
'SubName' => 'varchar(255)',
'Tagline' => 'varchar(255)',
'Description' => 'HTMLText',
'WhereToBuy' => 'varchar(500)', // external link
'NutritionFacts' => 'HTMLText',
'PageTitle' => 'varchar(250)',
'MetaKeywords' => 'Text',
'MetaDescription' => 'Text',
'SortOrder' =>'Int'
];
private static $has_one = [
'BeautyShot' => 'Image',
'ThumbImage' => 'Image',
'NutritionalInformationLabel' => 'Image',
'Category' => 'Category',
];
private static $summary_fields = [
'GridThumbnail' => 'Photo',
'Name' => 'Name'
];
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', new TextField("Name", "Name"));
$fields->addFieldToTab('Root.Main', new TextField("SubName", "SubName"));
$fields->addFieldToTab('Root.Main', new TextField("Tagline", "Tagline"));
$fields->addFieldToTab("Root.Main", new HtmlEditorField("Description", "Description"));
$fields->addFieldToTab('Root.Main', new TextField("WhereToBuy", "WhereToBuy"));
$fields->addFieldToTab("Root.Main", new HtmlEditorField("NutritionFacts", "NutritionFacts"));
$fields->addFieldToTab("Root.Main", new UploadField("BeautyShot", "BeautyShot"));
$fields->addFieldToTab("Root.Main", new UploadField("ThumbImage", "ThumbImage"));
$fields->addFieldToTab("Root.Main", new UploadField("NutritionalInformationLabel", "NutritionalInformationLabel"));
$fields->addFieldToTab('Root.SEO', new TextField("PageTitle", "PageTitle"));
$fields->addFieldToTab('Root.SEO', new TextareaField("MetaKeywords", "MetaKeywords"));
$fields->addFieldToTab('Root.SEO', new TextareaField("MetaDescription", "MetaDescription"));
$fields->removeByName('SortOrder');
return $fields;
}
public function getGridThumbNail() {
if ($this->BeautyShot()->exists()) {
return $this->BeautyShot()->SetWidth(100);
}
return '(no image)';
}
public function getBeautyShotURL() {
return $this->BeautyShot()->URL;
}
public function getNutritionalInformationLabelURL() {
if ($this->NutritionalInformationLabel()->Exists()) {
return $this->NutritionalInformationLabel()->URL;
} else {
return "";
}
}
public function getCouponImageURL() {
if ($this->CouponImage()->Exists()) {
return $this->CouponImage()->URL;
} else {
return "";
}
}
public function getProductFullName(){
return $this->Name." ".$this->SubName;
}
public function AbsoluteLink() {
return Director::absoluteURL($this->url());
}
private function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
// lifted from Artisa
public function MetaTags() {
$tags = "";
$generator = trim(Config::inst()->get('SiteTree', 'meta_generator'));
if (!empty($generator)) {
$tags .= "<meta name="generator" content="" . Convert::raw2att($generator) . "" />n";
}
$charset = Config::inst()->get('ContentNegotiator', 'encoding');
$tags .= "<meta http-equiv="Content-type" content="text/html; charset=$charset" />n";
if($this->MetaDescription) {
$tags .= "<meta name="description" content="" . Convert::raw2att($this->MetaDescription) . "" />n";
}
if($this->MetaKeywords) {
$tags .= "<meta name="keywords" content="" . Convert::raw2att($this->MetaKeywords) . "" />n";
}
if(Permission::check('CMS_ACCESS_CMSMain')
&& in_array('CMSPreviewable', class_implements($this))
&& !$this instanceof ErrorPage
&& $this->ID > 0
) {
$tags .= "<meta name="x-page-id" content="{$this->ID}" />n";
$tags .= "<meta name="x-cms-edit-link" content="" . $this->CMSEditLink() . "" />n";
}
$this->extend('MetaTags', $tags);
return $tags;
}
public function canView($member = null){
return true;
}
public function canEdit($member = null) {
return true;
}
public function canCreate($member = null) {
return true;
}
public function slug()
{
return Utilities::friendlyName($this->Name);
}
public function Link()
{
return $this->url();
}
public function getTitleFields() {
return ['Name', 'SubName'];
}
public function getContentFields() {
return ['Description'];
}
public static function getSearchFilter() {
return [];
}
}
// Handles Products and categories
class ProductCsvBulkImporter extends CsvBulkLoader {
protected function processRecord($record, $columnMap, &$results, $preview = false) {
$categoryName = $record['Main Category'];
$productName = $record['Product ID'];
$productSubName = $record['Product Type'];
$productTagline = $record['Product Label'];
$productDescription = $record['Product Description'];
$productKeywords = $record['Keyphrase'];
$category = Category::get()
->filter(['Name' => $categoryName])
->first();
if (!$category) {
$category = new Category();
$category->Name = $categoryName;
$category->write();
}
$product = Product::get()
->filter(['Name' => $productName])
->first();
if (!$product) {
$product = new Product();
}
$product->PageTitle = sprintf("%s %s", $productName, $productSubName);
$product->Name = $productName;
$product->SubName = $productSubName;
$product->Tagline = $productTagline;
$product->Description = $productDescription;
$product->MetaKeywords = $productKeywords;
$product->CategoryID = $category->ID;
$product->write();
return $product->ID;
}
}
我不知道现在设置的代码是否是最佳实践,因为我没有这样做,所以如果有错误,我不能确定。
有没有办法将 url(( 函数从 Product.php 附加到 .json?add_fields ajax 响应?
正如您在Product
类中看到的那样,url()
方法private
,因此您无法在该类之外访问它:
private function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
如果将其更改为:
public function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
它可能会起作用...这就是我根据您提交的代码所能说的全部内容。您应该知道,该url()
方法可能是私有的 - 很可能它仅在Product
类内部使用。
如果它仍然不起作用,请尝试像这样复制该函数:
public function getUrl() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
。然后在 JS 代码中你可以像这样使用它:
console.log(product.Url);
如您所见,您在 JS 代码中有这样的调用:product.BeautyShotURL
,但 Product
类中的实际方法称为 getBeautyShotURL()
,因此它应该与 product.Url
一起使用(这可能也很难工作:product.getUrl
(