php - SilverStripe 3.6.2 - 按下拉选择对分页数据对象进行排序会触发 404 错误

标签 php jquery pagination silverstripe

几年前,我设置了一个新闻文章页面的分页列表,这些页面根据下拉字段选择按年份排序:SilverStripe - Create pagination based on dropdown selection

我现在正在尝试做同样的事情,但这一次,新闻文章是数据对象。否则,其他一切都一样。

问题是我这次无法让它工作,我不知道为什么。我遵循相同的步骤,但当我从下拉列表中选择年份时,我会进入网站上的 404 页面,并且在 Chrome 的“网络”选项卡中,该网址有一个 404 状态: enter image description here

我可以看到年份值没有传递到页面的代码进行处理,但我不确定为什么它在我正在处理的另一个 SilverStripe 网站上确实有效并且仍然有效。我链接到的旧帖子。

这是我现在拥有的代码:

;(function($) {
   $(function(){
        // hide form actions, as we want to trigger form submittal
        var newsYearFilterForm = $("#Form_YearFilterForm");
        // automatically when dropdown changes
        newsYearFilterForm.find(".Actions").hide();

        // bind a change event on the dropdown to automatically submit
        newsYearFilterForm.on("change", 'select[name="Year"]', function(e){
            newsYearFilterForm.submit();
        });

        // handle pagination clicks
        $("body").on("click", "a.pagination", function (e) {
            e.preventDefault();
           // $("#ArticleList").addClass("loading");
            $.get(
                $(this).attr("href"),
                function(data, status, xhr){
                    $("#ArticleList").replaceWith($(data));
                }
            );

            return false;
        });
    });
})(jQuery);

NewsLandingPage.php

<?php

class NewsLandingPage extends Page
{

    private static $description = 'News Landing page.';

    private static $db = array();

    private static $has_one = array();

}

class NewsLandingPage_Controller extends Page_Controller
{

    private static $allowed_actions = array(
        'renderNewsItem',
        'YearFilterForm',
        'year',
    );

    public function init()
    {
        parent::init();
    }

    private static $url_handlers = array(
        '$NewsItem!' => 'renderNewsItem',
    );

    public function getAllNews()
    {
        $newsList = NewsItem::get()->sort('NewsDate', 'DESC');
        return new PaginatedList($newsList, $this->getRequest());
    }

    public function renderNewsItem(SS_HTTPRequest $request)
    {
        $newsItemName = $request->param('NewsItem');
        if ($newsItemName != "") {
            $newsItem = NewsItem::get()->filterAny(array(
                'NewsItemSlug' => $newsItemName
            ))->first();

            if ($newsItem) {
                $arrayData = array(
                    'NewsItem' => $newsItem,
                );

                return $this->renderWith(array('NewsArticle', 'Page'), new ArrayData($arrayData));
            } else {
                return $this->httpError(404);
            }
        }

    }

    public function handleYearRequest(SS_HTTPRequest $request)
    {
        $year = $request->param('ID');
        $data = array(
            'Year' => $year,
            'PaginatedReleases' => $this->PaginatedReleases($year)
        );

        if ($request->isAjax()) {
            // in case of an ajax request, render only the partial template
            return $this->renderWith('ArticleList', $data);
        } else {
            // returning an array will cause the page to render normally
            return $data;
        }
    }

    //creates a form to filter through news releases by year
    public function YearFilterForm()
    {
        // get an array of all distinct years
        $list = SQLSelect::create()
            ->addFrom('NewsItem')
            ->selectField('YEAR("NewsDate")', 'Year')
            ->setOrderBy('Year', 'DESC')
            ->execute()->column('Year');

        // create an associative array with years as keys & values
        $values = array_combine($list, $list);

        // our fields just contain the dropdown, which uses the year values
        $fields = FieldList::create(array(
            DropdownField::create(
                'Year',
                '',
                $values,
                $this->getRequest()->param('ID')
            )->setHasEmptyDefault(true)
                ->setEmptyString('Show all')
                ->setAttribute('data-urlpattern', $this->Link('year') . '/YYYY')
        ));

        $actions = new FieldList(
            FormAction::create('doFilter', 'Submit')
        );

        return Form::create($this, 'YearFilterForm', $fields, $actions);
    }

    public function year()
    {
        return $this->handleYearRequest($this->request);
    }

    public function index()
    {
        return $this->handleYearRequest($this->request);
    }

    //redirects to the proper url depending on which year is selected for sorting news
    public function doFilter($data, $form)
    {
        if (empty($data['Year'])) {
            return $this->redirect($this->Link());
        } else {
            return $this->redirect($this->Link('year/' . $data['Year']));
        }
    }

    //created a paginated list of news released by year
    public function PaginatedReleases($year = null)
    {
        $list = NewsItem::get()->sort('NewsDate', 'DESC');
        if ($year) {
            $list = $list->where(array('YEAR("NewsDate") = ?' => $year));
        }

        return PaginatedList::create($list, $this->getRequest())->setLimitItems(10);
    }

}

NewsItem.php

class NewsItem extends DataObject{
    private static $db = array(
        'NewsName'              => 'Varchar(255)',
        'NewsItemSlug'              => 'Varchar(250)',
        'NewsDate'              => 'SS_Datetime',
        'NewsLocation'          => 'Varchar(255)',
        'NewsArticle'           => 'HTMLText',
        'NewsArticleSummary'    => 'HTMLText',
        'SortOrder'             => 'Int',

    );

    private static $summary_fields = array(
        'NewsName',
        'NewsDate',
        'NewsItemSlug',
    );

    private static $has_one = array(
        'NewsImage'             => 'Image',
        'NewsUrlForHomePage'    => 'SiteTree',
        'Page'                  => 'Page'
    );


    public function onBeforeWrite() {
        parent::onBeforeWrite();
        if ($this->NewsItemSlug == ""){
            $linkName = $this::getLinkName();

            if ($linkName == ""){
                $linkName = str_replace(array(" ",":","%","$","#","@","!","^","&","*","(",")","'",";","<",">","/","?","[","]","{","}","\\","|","`","~","=","+","’",",","."),"-",strtolower(str_replace("&","and",str_replace(".","",$this->NewsName))));
            }


            $this->NewsItemSlug = $linkName;
        } else {
            $this->NewsItemSlug = str_replace(array(" ",":","%","$","#","@","!","^","&","*","(",")","'",";","<",">","/","?","[","]","{","}","\\","|","`","~","=","+","’",",","."),"-",strtolower(str_replace("&","and",str_replace(".","",$this->NewsItemSlug))));
        }
    }
    public function getLinkName() {
        if ($this->NewsItemSlug != "" && !is_null($this->NewsItemSlug)){
            return $this->NewsItemSlug;
        }
        return str_replace(" ","-",strtolower(str_replace("&","and",$this->NewsName)));
    }
    public function LinkingMode() {
        return Controller::curr()->getRequest()->param('ID') == $this::getLinkName() ? 'current' : 'link';
    }
    public function Link() {
        $newsLandingPage = NewsLandingPage::get()->first();

        $linkName = $this::getLinkName();

        if ($linkName){
            return $newsLandingPage->Link($linkName);
        } else {
            return false;
        }
    }

    public function canView($member = null){
        return true;
    }

    public function canEdit($member = null) {
        return true;
    }

    public function canCreate($member = null) {
        return true;
    }

    public function getCMSFields() {
        $fields = parent::getCMSFields();

        $fields->removeFieldFromTab("Root.Main","PageID");
        return $fields;
    }
}

class NewsItemAdmin extends ModelAdmin {
    private static $managed_models = array(
        'NewsItem',
    );
    private static $url_segment = 'NewsItems';
    private static $menu_title = 'News';
}

NewsLandingPage.ss

<% include BreadCrumbs %>
<div class="container container-intro-copy" style="background-color:#fff;opacity:1.0;">
    <h1 class="intro-copy h1">$H1</h1>
    <div class="intro-copy">$Content</div>
    $YearFilterForm
    <% include NewsList %>
</div>

新闻列表.ss

<div id="ArticleList" class="container careers-list">
    <div class="row">
        <% loop  $PaginatedReleases %>
            <div class="career-item col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-12 item bio-detail aos-init aos-animate" data-aos="fade-up" data-aos-delay="200" style="margin-top:30px;">
                <div class="box-for-resources top-box-style">
                    <div class="box-resources-left"><img src="$NewsImage.URL" class="image-resources-cmmm"></div>
                    <div class="box-resources-right">

                        <h3 class="name left" style="color:#002f65 !important; float: left; clear: both;">$NewsName</h3>
                        <p class="box-resource-copy text-date"><em>$NewsDate.FormatI18N('%B %d, %Y') ($NewsLocation)</em></p><br />
                        <div class="careers-copy">$NewsArticleSummary</div><br />
                        <a href="$Link">Read Article</a>
                    </div>
                </div>
            </div>
        <% end_loop %>
    </div>
</div>

新闻页面默认成功加载所有文章,并且每篇文章的链接都正常工作。下拉表单根据文章的范围提供了正确的年份列表。

最佳答案

我认为您的 url_handlers 和您在 Controller 上调用的操作存在冲突。

'$NewsItem!' => 'renderNewsItem',

上面的行匹配 renderNewsItem 的所有操作。例如。 yoursite.test/controller/YearFilterForm 也将与此匹配...

您应该向显示新闻项的处理程序添加一些静态部分。所以你的url_handlers将是:

'show/$NewsItem!' => 'renderNewsItem',

然后您必须相应地调整您的 NewsItem->Link 方法。 我还建议您使用 URLSegmentFilter 来创建您的 slugs...例如。

public function onBeforeWrite() {
    parent::onBeforeWrite();
    // only rebuild the slug when news-name has changed
    if ($this->isChanged('NewsName', DataObject::CHANGE_VALUE)) {
        $filter = URLSegmentFilter::create();
        $t = $filter->filter($this->NewsName);

        // Fallback to generic name if path is empty (= no valid, convertable characters)
        if (!$t || $t == '-' || $t == '-1') {
            $t = "news-{$this->ID}";
        }

        $this->NewsItemSlug = $t;
    }
}

关于php - SilverStripe 3.6.2 - 按下拉选择对分页数据对象进行排序会触发 404 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48269864/

相关文章:

javascript - Yii 和 Javascript 表单提交

php - 如何组合 3 个 MySQL 表插入

javascript - 段落文字如何显示文字打字效果

php - Jquery Onclick 将数据发送到新打开的窗口

javascript - 如何使用 Javascript 根据类中的元素填充选择表单(即下拉列表)

php - Codeigniter 'Message: Undefined index: site_lang' 首次加载时出现问题

Javascript实时访客信息

jquery - 如何从表中选择两列数据?

java - 如何使用spring对MongoDB进行分页?

javascript - Angular 2 : TypeError: core_1. NgModule 不是函数