【问题标题】:Silverstripe Site Search for DataObjects as Pages - Part 2 tutorialSilverstripe Site Search for DataObjects as Pages - 第 2 部分教程
【发布时间】:2012-05-23 00:50:37
【问题描述】:

去年年底我用DataObjects as Pages - Part 2Silverstripe做了一个产品站点,站点已经上线,我需要为站点实现站点搜索功能。

我实现了一个像Tutorial 4 - Site Search 这样的搜索功能,但这不适用于产品搜索,因为每个产品都是一个数据对象而不是一个页面。

谁能解释我如何使网站搜索适用于产品?

我知道有一个tutorial 3 DataObject as Pages 我试过了,但它弄乱了我所有现有的产品以及产品的一些额外现有功能。有人建议http://silverstripe.org/all-other-modules/show/6641?start=24,但目前没有成功。

感谢任何有关如何为产品执行搜索功能的帮助。

谢谢。

这是我的Product.php 代码

<?php

class Product extends DataObject
{
    static $db = array(
        'Title' => 'Varchar(255)',
        'Description' => 'HTMLText',
        'Price' => 'Decimal(6,2)',
        'URLSegment' => 'Varchar(255)'
    );

    //Set our defaults
    static $defaults = array(  
        'Title' => 'New Product',
        'URLSegment' => 'new-product'
    );

    static $has_one = array(
        'Image' => 'Image',
        'PDF' => 'File' 
    );

    //Relate to the category pages
    static $belongs_many_many = array(
        'Categories' => 'CategoryPage'
    );

    //Fields to show in ModelAdmin table
    static $summary_fields = array(
        'Title' => 'Title',
        'URLSegment' => 'URLSegment',
        'Price' => 'Price (&pound;)'
    ); 

    //Add an SQL index for the URLSegment
    static $indexes = array(
        "URLSegment" => true
    );  

    //Fields to search in ModelAdmin
    static $searchable_fields = array (
        'Title',
        'URLSegment',
        'Description',
        'Categories.ID' => array(
            'title' => 'Category'
        )
    );


    function getCMSFields()
    {

        $fields = parent::getCMSFields();

        //Main Tab
        $fields->addFieldToTab("Root.Main", new TextField('Title', 'Title'));   
        $fields->addFieldToTab("Root.Main", new TextField('URLSegment', 'URL Segment'));
        $fields->addFieldToTab("Root.Main", new NumericField('Price'));
        $fields->addFieldToTab("Root.Main", new HTMLEditorField('Description'));

        //added below for the ordering
        $Categories = DataObject::get('CategoryPage');
        $map = $Categories->map('ID', 'CheckboxSummary');
        asort($map);
        $fields->addFieldToTab("Root.Categories", new CheckboxsetField('Categories', 'Categories', $map));

        //Images
        $fields->addFieldToTab("Root.Images", new ImageField('Image', 'Image', Null, Null, Null, 'Uploads/category_banners'));

        $fields->addFieldToTab("Root.Files", new FileIFrameField('PDF'));

        return $fields;
    }

    //Set URLSegment to be unique on write
    function onBeforeWrite()
    {      
        // If there is no URLSegment set, generate one from Title
        if((!$this->URLSegment || $this->URLSegment == 'new-product') && $this->Title != 'New Product')
        {
            $this->URLSegment = SiteTree::generateURLSegment($this->Title);
        }
        else if($this->isChanged('URLSegment'))
        {
            // Make sure the URLSegment is valid for use in a URL
            $segment = preg_replace('/[^A-Za-z0-9]+/','-',$this->URLSegment);
            $segment = preg_replace('/-+/','-',$segment);

            // If after sanitising there is no URLSegment, give it a reasonable default
            if(!$segment) {
                $segment = "product-$this->ID";
            }

            $this->URLSegment = $segment;

        }


        // Ensure that this object has a non-conflicting URLSegment value.
        $count = 2;
        while($this->LookForExistingURLSegment($this->URLSegment))
        {

            $this->URLSegment = preg_replace('/-[0-9]+$/', null, $this->URLSegment) . '-' . $count;
            $count++;

        }

        parent::onBeforeWrite();

    }

    //Test whether the URLSegment exists already on another Product
    function LookForExistingURLSegment($URLSegment)
    {

        return (DataObject::get_one('Product', "URLSegment = '" . $URLSegment ."' AND ID != " . $this->ID));

    }


    //Generate the link for this product

    function Link()
    {
        //if we are on a category page return that
        if(Director::CurrentPage()->ClassName == 'CategoryPage')
        {
            $Category = Director::CurrentPage();
        }
        //Otherwise just grab the first category this product is in
        else
        {
            $Category = $this->Categories()->First();
        }  

        //Check we have a category then return the link
        if($Category)
        {
            return $Category->absoluteLink() . 'show/' . $this->URLSegment;      
        }

    }

    //Return the Title as a menu title
    public function MenuTitle()
    {
        return $this->Title;
    }

    function canView() {
        return true;
    }

    public function LinkingMode()   
    {
        //Check that we have a controller to work with and that it is a StaffPage
        if(Controller::CurrentPage() && Controller::CurrentPage()->ClassName == 'CategoryPage')
        {
            //check that the action is 'show' and that we have a StaffMember to work with
            if(Controller::CurrentPage()->getAction() == 'show' && $Product = Controller::CurrentPage()->getCurrentProduct())
            {
                //If the current StaffMember is the same as this return 'current' class
                return ($Product->ID == $this->ID) ? 'current' : 'link';
            }
        }
    }
}

这是我的 CategoryPage.php

<?php

class CategoryPage extends Page
{

    static $has_one = array(
        'CategoryBanner' => 'Image',
        'Photo' => 'Image'  
    );

    static $many_many = array(     
        'Products' => 'Product'
    );

    static $allowed_children = array(
        'none' => 'none'
    );

    function getCMSFields()
    {
        $fields = parent::getCMSFields();       
        $fields->addFieldToTab("Root.Content.Images", new ImageField('Photo'));
        //Banner Images
        $fields->addFieldToTab("Root.Content.Banner", new ImageField('CategoryBanner', 'Banner', Null, Null, Null, 'Uploads/category_banners'));

        return $fields;
    }  

    //important for sidebar showing, this is sitetree stuff - relationship between categories and products 20012012
    public function onBeforeDelete()
    {
        $CurrentVal = $this->get_enforce_strict_hierarchy();
        $this->set_enforce_strict_hierarchy(false);

        parent::onBeforeDelete();

        $this->set_enforce_strict_hierarchy($CurrentVal);
    }  

    public function Children(){
        return $this->Products();
    }
    //added this on 03022011 for the parent page to show on Categories in admin
    function CheckboxSummary(){ 
        return $this->Parent()->Title . ' - ' . $this->Title;
    }
}

class CategoryPage_Controller extends Page_Controller
{

    static $allowed_actions = array(
        'show'
    );

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

        Requirements::css('themes/tutorial/css/products.css');

        //added this to make the gallery js work 10012012
        Requirements::set_write_js_to_body(false); 

        Requirements::javascript("mysite/javascript/jquery-1.4.2.min.js");                Requirements::javascript("mysite/javascript/jquery.cycle.lite.min.js");
        Requirements::javascript("mysite/javascript/toggle_menu.js");           
    }

    //Return the list of products for this category
    public function getProductsList()
    {
        return $this->Products(Null, 'Price ASC');
    }

    //Get's the current product from the URL, if any
    public function getCurrentProduct()
    {
        $Params = $this->getURLParams();
        $URLSegment = Convert::raw2sql($Params['ID']);

        if($URLSegment && $Product = DataObject::get_one('Product', "URLSegment = '" . $URLSegment . "'"))
        {      
            return $Product;
        }
    }

    //Shows the Product detail page
    function show()
    {
        //Get the Product
        if($Product = $this->getCurrentProduct())
        {
            $Data = array(
                'Product' => $Product,
                'MetaTitle' => $Product->Title
            );

            //return our $Data array to use, rendering with the ProductPage.ss template
            return $this->customise($Data)->renderWith(array('ProductPage', 'Page'));        
        }
        else //Product not found
        {
            return $this->httpError(404, 'Sorry that product could not be found');
        }
    }

    //Generate out custom breadcrumbs
    public function Breadcrumbs() {

        //Get the default breadcrumbs
        $Breadcrumbs = parent::Breadcrumbs();

        if($Product = $this->getCurrentProduct())
        {
            //Explode them into their individual parts
            $Parts = explode(SiteTree::$breadcrumbs_delimiter, $Breadcrumbs);

            //Count the parts
            $NumOfParts = count($Parts);

            //Change the last item to a link instead of just text
            $Parts[$NumOfParts-1] = ('<a href="' . $this->Link() . '">' . $Parts[$NumOfParts-1] . '</a>');

            //Add our extra piece on the end
            $Parts[$NumOfParts] = $Product->Title;

            //Return the imploded array
            $Breadcrumbs = implode(SiteTree::$breadcrumbs_delimiter, $Parts);          
        }

        return $Breadcrumbs;
    }           
}

【问题讨论】:

    标签: php search silverstripe


    【解决方案1】:

    如果您正在做任何严肃的搜索,内置的搜索功能(基于 MySQL MyISAM)并不理想。我建议使用 Solr 或 Sphinx,通过 https://github.com/silverstripe/silverstripe-sphinxhttps://github.com/nyeholt/silverstripe-solr 集成到 SilverStripe 中(我将从第一个开始)。这也将索引 DAO。

    【讨论】:

    • 嗨,Xeraa,非常抱歉回复晚了,非常感谢您的回复。我不需要完整的搜索功能,主要目的是通过数据对象搜索产品,以及网站上的一些信息。你认为狮身人面像仍然是要走的路吗?我以前从来没有这样做过,你有一些关于如何开始的链接吗?我也看到有人建议这个silverstripe.org/all-other-modules/show/6641?start=24,但我在实施它时遇到了问题。对于在该领域没有丰富经验的我,您会给我什么指导?非常感谢,再次抱歉耽搁了。谢谢:)
    • 我猜你的意思是silverstripe.org/all-other-modules/show/…?您正在使用 2.4 还是即将推出的 3?在版本 3 中,默认数据库引擎将切换到不支持全文搜索的 InnoDB。您可以切换回 MyISAM,但恕我直言,这不是要走的路。我会使用github.com/nyeholt/silverstripe-solr - 文档从github.com/nyeholt/silverstripe-solr/wiki 开始。我自己并没有真正使用过那个模块,所以我不能指出任何更具体的帮助者。但恕我直言,这是最好的和最面向未来的方法:)
    • 感谢 Xeraa 的跟进,我使用的是 2.4,所以我想我可以试试 silverstripe.org/all-other-modules/show/… 吗?还要感谢关于 solr 的建议,我有点害怕通过使用 solr 来改变服务器,我也在 mo 上开发 wamp。但是,我会尝试您的建议,并让您知道我以后会怎么做。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 2016-06-23
    • 2021-08-10
    • 2014-04-06
    • 2021-01-31
    • 1970-01-01
    • 2015-10-10
    相关资源
    最近更新 更多