0

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

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

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

我知道有一个教程 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;
    }           
}
4

1 回答 1

0

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

于 2012-05-23T02:36:15.300 回答