页面的Silverstripe模型管理员

时间:2014-08-18 17:52:19

标签: silverstripe swipestripe

我正在使用Silverstripe Swipestripe模块进行在线商店。由于客户拥有的产品数量,当他们想要对产品进行更改(这种情况经常发生)时,通过网站树导航到每个单独的产品是不切实际的,所以我要这样做。喜欢使用modeladmin列出所有产品,并允许他们按名称/股票代码搜索产品。

我认为这可以像DataObjects一样解决(并且搜索似乎表明人们已经完成了这一点),但是当我在ModelAdmin视图中导航到产品时,我得到:

  

致命错误:在非对象中调用成员函数stat()   第3192行的/path/to/folder/wwwroot/framework/model/DataObject.php

<?php
class ProductAdmin extends ModelAdmin
{ 
    private static $managed_models = array('Product'); 
    private static $url_segment = 'product'; 
    private $menu_title = 'Products';

}

有趣的是,页面类的页面和其他扩展可以正常工作。

以下是Product类的代码:

class Product extends Page {

    /**
     * Flag for denoting if this is the first time this Product is being written.
     * 
     * @var Boolean
     */
    protected $firstWrite = false;

    /**
     * DB fields for Product.
     * 
     * @var Array
     */
    private static $db = array(
        'Price'     => 'Decimal(19,4)',
        'Currency'  => 'Varchar(3)',
        'StockCode' => 'Varchar(255)',
        'Stock'     => 'Int',
        'Featured'  => 'Boolean',
        'YouTubeID' => 'Varchar(255)'

    );

    /**
     * Actual price in base currency, can decorate to apply discounts etc.
     * 
     * @return Price
     */
    public function Amount() {

        // TODO: Multi currency
        $shopConfig = ShopConfig::current_shop_config();

        $amount = new Price();
        $amount->setAmount($this->Price);
        $amount->setCurrency($shopConfig->BaseCurrency);
        $amount->setSymbol($shopConfig->BaseCurrencySymbol);

        //Transform amount for applying discounts etc.
        $this->extend('updateAmount', $amount);

        return $amount;
    }

    /**
     * Display price, can decorate for multiple currency etc.
     * 
     * @return Price
     */
    public function Price() {

        $amount = $this->Amount();

        //Transform price here for display in different currencies etc.
        $this->extend('updatePrice', $amount);

        return $amount;
    }

    /**
     * Has many relations for Product.
     * 
     * @var Array
     */
    private static $has_many = array(
        'Attributes' => 'Attribute',
        'Options' => 'Option',
        'Variations' => 'Variation'
    );

    /**
     * Defaults for Product
     * 
     * @var Array
     */
    private static $defaults = array(
        'ParentID' => -1,
        'Stock'     => 999
    );

    /**
     * Summary fields for displaying Products in the CMS
     * 
     * @var Array
     */
    private static $summary_fields = array(
        'Amount.Nice' => 'Price',
        'Title' => 'Title'
    );

    private static $searchable_fields = array(
        'Title' => array(
            'field' => 'TextField',
            'filter' => 'PartialMatchFilter',
            'title' => 'Name'
        )
    );

    /**
     * Set firstWrite flag if this is the first time this Product is written.
     * 
     * @see SiteTree::onBeforeWrite()
     * @see Product::onAfterWrite()
     */
    public function onBeforeWrite() {
        parent::onBeforeWrite();
        if (!$this->ID) $this->firstWrite = true;

        //Save in base currency
        $shopConfig = ShopConfig::current_shop_config();
        $this->Currency = $shopConfig->BaseCurrency;
    }

    /**
     * Unpublish products if they get deleted, such as in product admin area
     * 
     * @see SiteTree::onAfterDelete()
     */
    public function onAfterDelete() {
        parent::onAfterDelete();

        if ($this->isPublished()) {
            $this->doUnpublish();
        }
    }

    /**
     * Set some CMS fields for managing Products
     * 
     * @see Page::getCMSFields()
     * @return FieldList
     */
    public function getCMSFields() {

        $shopConfig = ShopConfig::current_shop_config();
        $fields = parent::getCMSFields();

        //Product fields
        $fields->addFieldToTab('Root.Main', new PriceField('Price'), 'Content');
        $fields->addFieldToTab('Root.Main', new TextField('StockCode'), 'Price');
        $fields->addFieldToTab('Root.Main', new TextField('Stock'), 'Price');
        $fields->addFieldToTab('Root.Main', new CheckBoxField('Featured'), 'Content');
        $fields->addFieldToTab('Root.Images', new TextField('YouTubeID', 'YouTube Video ID (Taken from the end of the video url. ie https://www.youtube.com/watch?v=ABC123 would be ABC123)'));

        //Replace URL Segment field
        if ($this->ParentID == -1) {
            $urlsegment = new SiteTreeURLSegmentField("URLSegment", 'URLSegment');
            $baseLink = Controller::join_links(Director::absoluteBaseURL(), 'product/');
            $url = (strlen($baseLink) > 36) ? "..." .substr($baseLink, -32) : $baseLink;
            $urlsegment->setURLPrefix($url);
            $fields->replaceField('URLSegment', $urlsegment);
        }

        if ($this->isInDB()) {

            //Product attributes
            $listField = new GridField(
                'Attributes',
                'Attributes',
                $this->Attributes(),
                GridFieldConfig_BasicSortable::create()
            );
            $fields->addFieldToTab('Root.Attributes', $listField);

            //Product variations
            $attributes = $this->Attributes();
            if ($attributes && $attributes->exists()) {

                //Remove the stock level field if there are variations, each variation has a stock field
                $fields->removeByName('Stock');

                $variationFieldList = array();
                foreach ($attributes as $attribute) {
                    $variationFieldList['AttributeValue_'.$attribute->ID] = $attribute->Title;
                }
                $variationFieldList = array_merge($variationFieldList, singleton('Variation')->summaryFields());

                $config = GridFieldConfig_HasManyRelationEditor::create();
                $dataColumns = $config->getComponentByType('GridFieldDataColumns');
                $dataColumns->setDisplayFields($variationFieldList);

                $listField = new GridField(
                    'Variations',
                    'Variations',
                    $this->Variations(),
                    $config
                );
                $fields->addFieldToTab('Root.Variations', $listField);
            }
        }

        //Ability to edit fields added to CMS here
        $this->extend('updateProductCMSFields', $fields);

        if ($warning = ShopConfig::base_currency_warning()) {
            $fields->addFieldToTab('Root.Main', new LiteralField('BaseCurrencyWarning', 
                '<p class="message warning">'.$warning.'</p>'
            ), 'Title');
        }

        return $fields;
    }

    /**
     * Get the URL for this Product, products that are not part of the SiteTree are 
     * displayed by the {@link Product_Controller}.
     * 
     * @see SiteTree::Link()
     * @see Product_Controller::show()
     * @return String
     */
    public function Link($action = null) {

        if ($this->ParentID > -1) {
            return parent::Link($action);
        }
        return Controller::join_links(Director::baseURL() . 'product/', $this->RelativeLink($action));
    }

    /**
     * A product is required to be added to a cart with a variation if it has attributes.
     * A product with attributes needs to have some enabled {@link Variation}s
     * 
     * @return Boolean
     */
    public function requiresVariation() {
        $attributes = $this->Attributes();
        return $attributes && $attributes->exists();
    }

    /**
     * Get options for an Attribute of this Product.
     * 
     * @param Int $attributeID
     * @return ArrayList
     */
    public function getOptionsForAttribute($attributeID) {

        $options = new ArrayList();
        $variations = $this->Variations();

        if ($variations && $variations->exists()) foreach ($variations as $variation) {

            if ($variation->isEnabled()) {
                $option = $variation->getOptionForAttribute($attributeID);
                if ($option) $options->push($option); 
            }
        }
        $options = $options->sort('SortOrder');
        return $options;
    }

    /**
     * Validate the Product before it is saved in {@link ShopAdmin}.
     * 
     * @see DataObject::validate()
     * @return ValidationResult
     */
    public function validate() {

        $result = new ValidationResult(); 

        //If this is being published, check that enabled variations exist if they are required
        $request = Controller::curr()->getRequest();
        $publishing = ($request && $request->getVar('action_publish')) ? true : false;

        if ($publishing && $this->requiresVariation()) {

            $variations = $this->Variations();

            if (!in_array('Enabled', $variations->map('ID', 'Status')->toArray())) {
                $result->error(
                    'Cannot publish product when no variations are enabled. Please enable some product variations and try again.',
                    'VariationsDisabledError'
                );
            }
        }
        return $result;
    }

}

任何人都可以建议我在这里做错了什么,或者另外一种方法来做我想要达到的目标吗?

干杯

1 个答案:

答案 0 :(得分:1)

以防任何人仍然遇到同样的问题。 因此,如果您已为swipestripe安装了Product Categories模块,则会发生这种情况。 原因是该模块中ProductCategory.php文件中的ProductCategory_Extension类中的私有静态$ searchable_fields。只需注释掉该字段即可。 这是因为dataobject类尝试将类别作为一个类 - 这显然不存在。

如果我有时间,我会解决它并推送到github。只是想在这里更新,以便其他人不要浪费时间去理解为什么它不起作用。