XMLHttpRequest - append php function to .json?add_fields aja



我正在尝试更新其他人的代码,该代码使用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 (

最新更新