Silverstripe站点搜索DataObjects作为页面 - 第2部分教程

时间:2012-05-23 00:50:38

标签: php search silverstripe

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

我实现了像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;
    }           
}

1 个答案:

答案 0 :(得分:0)

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