SilversStripe 3:仅草稿中的未捕获异常

SilversStripe 3: Uncaught Exception in draft only

在 CMS 中查看草稿预览模式时使用 SilverStripe 3 我收到以下错误:

[User Error] Uncaught Exception: Object->__call(): the method 'featuredimage' does not exist on 'PortfolioPage'

这只发生在草稿模式下,不会发生在发布模式下。我对为什么感到困惑。 它在前端很好并且做了它应该做的但在草稿中抛出了错误。

PortfolioPage.ss

<div class="content-container unit size3of4 lastUnit">
    <article>
        <div class="content">
            $Content
            <div id="container">
                <% loop $DescendantFeaturedImages %>
                <% if $FeaturedImage %>
                <div class="item $Parent.URLSegment">
                    <a href="$Link" title="$Parent.Title - $Title">
                        <img src="$FeaturedImage.URL" width="100%" />
                        <div id="mask">
                            <span class="TitleContainer">
                                <h4>$Parent.Title</h4>
                                <p>$Title</p>
                            </span>
                        </div>
                    </a>
                </div>
                <% end_if %>
                <% end_loop %>
            <div>
        </div>
    </article>
    $Form
    $PageComments
</div>

PortfolioPage.php

class PortfolioPage extends Page {
}

class PortfolioPage_Controller extends Page_Controller {

    public function init() {
        parent::init();
        Requirements::css( 'gallery/css/gallerystyles.css' );
    }

    function DescendantFeaturedImages() {
        $featuredImages = array();

        foreach ( $this->Children() as $child ) {
            foreach ( $child->Children() as $grandChild ) {
                $image = $grandChild->FeaturedImage();
                if ( $image ) {
                    array_push( $featuredImages, $grandChild );
                }
            }
        }

        shuffle( $featuredImages );

        return ArrayList::create( $featuredImages );
    }
}

@3dgoo 说得对,由于 $grandChild 没有名为 FeaturedImage 的函数而引发错误。如果它没有在您的页面类型的祖先中的任何 classes 上定义(作为您自己的函数在从 has_one 关系生成的一个上),将抛出该错误。查看调用堆栈,您可以看到它是一个 PortfolioPage 对象,即 $grandChild.

这种情况仅在草稿上发生的一个原因是草稿网站上的网站树与发布的树不一样。

要避免此特定页面类型出现此错误,您需要在 PortfolioPage class 上定义一个名为 FeaturedImage 的函数(或 has_one 关系)。

要避免在所有页面类型上出现此错误,您可以执行以下任一操作:

  1. 检查FeaturedImage函数是否存在
  2. 使 FeaturedImage 函数存在于一个共同的父对象上 class

检查函数是否存在

要检查函数是否存在,最好使用内置的hasMethod函数。此函数不仅检查手动定义的方法,它还可以正确处理通过 DataExtension.

添加的方法

您的代码看起来更接近于此:

function DescendantFeaturedImages() {
    $featuredImages = array();

    foreach ( $this->Children() as $child ) {
        foreach ( $child->Children() as $grandChild ) {
            if ($grandChild->hasMethod('FeaturedImage')) {
                $image = $grandChild->FeaturedImage();
                if ( $image ) {
                    array_push( $featuredImages, $grandChild );
                }
            }
        }
    }

    shuffle( $featuredImages );

    return ArrayList::create( $featuredImages );
}

在公共父级上定义函数 class

大多数时候,您编写的页面类型和来自不同模块的页面类型将从 Page class.

继承

假设您打算 FeaturedImage 直接成为图像的 has_one,就是这样:

class Page extends SiteTree {

    // ... any other statics you defined here ...

    private static $has_one = array(
        'FeaturedImage' => 'Image'
    );

    // ... any other functions or bits of code below here ...
}

如果您的 PortfolioPage 打算成为供其他人使用的模块,您不想让他们在自己的 Page class 中手动定义它, 你会想要使用 DataExtension.

class PageExtension extends DataExtension {

    // ... any other statics you defined here ...

    private static $has_one = array(
        'FeaturedImage' => 'Image'
    );

    // ... any other functions or bits of code below here ...
}

然后只需将扩展名包含在您的 YML 文件中即可:

Page:
  extensions:
    - PageExtension