SEOBehavior добавление сео информации к модели

Выкладываем свои наработки
Ответить
taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

SEOBehavior добавление сео информации к модели

Сообщение taral14 »

Заметил что в многих таблицах приходится добавлять поля metaTitle, metaKeywords, metaDescription. Также прописывать валидацию этих полей. Решил поэкспериментировать и вынести их в отдельную таблицу. И написал поведение для прозрачной работы с ними. Предположим что у нас есть модель новостей с полями id, title, content. Подключаем поведение

Код: Выделить всё

class News extends CActiveRecord {
...
    public function behaviors() {
        'SEOBehavior' => array(
                'class' => 'SEOBehavior',
                'route' => 'news/view',
        ),
    }
...
 
Параметр route уникальный ключ для данной модели. Я назвал его route поскольку использую его еще и для других целей. Теперь мы можем сделать так

Код: Выделить всё

$news=News::model()->findByPk(1);

$news->metaTitle='test';
$news->save();

echo $news->metaTitle;

$_POST=array('metaTitle'=>'test');
$news->attributes=$_POST;
$news->save();

echo CHtml::activeTextField($news, 'metaTitle');
 
Вообщем можно работать как с обычными полями.
Схема таблицы seo

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `tbl_seo` (
  `route` varchar(64) NOT NULL,
  `params` varchar(128) NOT NULL,
  `metaTitle` varchar(500) DEFAULT NULL,
  `metaKeywords` varchar(500) DEFAULT NULL,
  `metaDescription` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`route`,`params`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
Вложения
SEOBehavior.rar
SEOBehavior
(997 байт) 191 скачивание

Nafania
Сообщения: 1227
Зарегистрирован: 2011.01.31, 13:12

Re: SEOBehavior добавление сео информации к модели

Сообщение Nafania »

Я для себя сделал компонент целиком, который подгружается через beforeControllerAction.
Таким образом можно задать эти параметры вообще для любой страницы, а не только для тех, к которым подключено поведение.

taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: SEOBehavior добавление сео информации к модели

Сообщение taral14 »

Именно по этой причине я назвал параметр route. metaTitle, metaKeywords, metaDescription можно добавить на любую страницу через beforeControllerAction. И на любую страницу они настраиваются отдельно в админке. Я про это не писал поскольку цель поведения другая. Оно же делает удобным редактирование и добавление мета информации на конкретную модель. К примеру параметр route в примере я выставил в news/view. Поведение заполнит параметр params как id=12. Таким образом я в beforeControllerAction news/view узнаю как контроллер/метод а params как получу с $_GET

Nafania
Сообщения: 1227
Зарегистрирован: 2011.01.31, 13:12

Re: SEOBehavior добавление сео информации к модели

Сообщение Nafania »

Если интересно, то мой компонент.
Можно ваше поведение и мой компонент использовать совместно.

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `pages_meta` (
  `page_title` varchar(255) NOT NULL,
  `page_description` varchar(255) NOT NULL,
  `page_keywords` varchar(255) NOT NULL,
  `route` varchar(255) NOT NULL,
  `params` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 
Добавить в Controller.php

Код: Выделить всё

    public function beforeRender()
    {
    $PagesMetaData = new PagesMetaData();
    $PagesMetaData->checkUrl($this->getRoute(), $this->getActionParams());

    return true;
    } 
и положить в components PagesMetaData.php

Код: Выделить всё

<?php
class PagesMetaData {
    public $defaultDescription;
    public $defaultKeywords;
    public $defaultTitle;

    private $_pagesData;
    private $_pageTitle;
    private $_pageDescription;
    private $_pageKeywords;
    private $_baseTitle;

    public function __construct () {
        $this->getBaseName();
        $this->loadData();        
    }

    private function getBaseName () {
        $name=ucfirst(basename(Yii::app()->controller->getId()));
        if(Yii::app()->controller->getAction()!==null && strcasecmp(Yii::app()->controller->getAction()->getId(),Yii::app()->controller->defaultAction))
        $this->_baseTitle=Yii::app()->name.' - '.ucfirst(Yii::app()->controller->getAction()->getId()).' '.$name;
        else
        $this->_baseTitle=Yii::app()->name.' - '.$name;
    }

    private function loadData () {
        $this->_pagesData = Yii::app()->cache->get('pagesMeta');

        if( $this->_pagesData === false ) {
        $sql = 'SELECT * FROM {{_pages_meta}}';
        $pagesMeta = Yii::app()->db->createCommand($sql)->queryAll();

        $this->_pagesData = array();
        foreach ( $pagesMeta AS $page ) {
            $params = array();
            $append = '';
            if ( !empty($page['params']) ) {
            if ( $page['route'] == '*' && $page['params'] == '*' ) {
                $this->_pagesData['*'] = $page;
                continue;
            }
            elseif ( $page['params'] == '*' ) {
                $append = '*';
            }
            else {
                $_params = explode(',', $page['params']);
                if ( sizeof($_params) ) {
                foreach ( $_params AS $param ) {
                    list($key, $value) = explode('=', $param);
                    $params[$key] = $value;
                }
                }
            }
            }
            $url = Yii::app()->createUrl($page['route'], $params);
            $this->_pagesData[$url . $append] = $page;
        }

        Yii::app()->cache->set('pagesMeta', $this->_pagesData, 3600);
        }

        if ( isset($this->_pagesData['*']) ) {
        $this->defaultDescription = $this->_pagesData['*']['page_description'];
        $this->defaultKeywords = $this->_pagesData['*']['page_keywords'];
        $this->defaultTitle = $this->_pagesData['*']['page_title'];
        }
    }

    public function checkUrl ( $route, $actionParams ) {
        $url = Yii::app()->createUrl($route, $actionParams);
        $page = '';

        if ( isset($this->_pagesData[$url]) ) {
        $page = $this->_pagesData[$url];
        }

        $route = Yii::app()->createUrl($route);
        if ( isset($this->_pagesData[$route . '*']) && empty($page) ) {
        $page = $this->_pagesData[$route . '*'];
        }

        if ( $page ) {
        $this->_pageDescription = $page['page_description'];
        $this->_pageKeywords = $page['page_keywords'];
        $this->_pageTitle = $page['page_title'];

        $this->setMetaTag($this->_pageDescription, 'description');
        $this->setMetaTag($this->_pageKeywords, 'keywords');
        $this->setTitle();
        }
        else {
        $this->setDefaultTags();
        }
    }

    private function setMetaTag ( $tagData, $tagName ) {
        $tagData = $this->prepareMetaTag($tagData);
        if ( $tagData ) {
        Yii::app()->clientScript->registerMetaTag($tagData, $tagName);
        }
    }

    private function setTitle () {
        if ( $this->_pageTitle ) {
        Yii::app()->controller->setPageTitle($this->_pageTitle);
        }
    }

    private function prepareMetaTag ( $tagData ) {
        return str_replace(array('"', '{pageTitle}'), array('"', $this->pageTitle), trim($tagData));
    }

    private function setDefaultTags () {
        if ( $this->defaultTitle && Yii::app()->controller->getPageTitle() == $this->_baseTitle ) {
        Yii::app()->controller->setPageTitle($this->defaultTitle);
        }
    }
}
?>
Есть особенности.
Данные в базе имеют приоритет на текущими данными страницы.
Можно задать один title, keywords, description для всех params одного route, в этом случае надо использовать символ * в params.
Можно задать в params * и в route *, тогда для всех страниц где нет тега title, он будет выведен заданным (как мета теги проверять в наличии я не понял, вроде нельзя).
В тегах keywords и description можно использовать текущий title страницы шаблоном {pageTitle}.

taral14
Сообщения: 236
Зарегистрирован: 2011.02.26, 23:48

Re: SEOBehavior добавление сео информации к модели

Сообщение taral14 »

Спасибо. Интересное решение

Ruganin
Сообщения: 14
Зарегистрирован: 2011.10.20, 15:25

Re: SEOBehavior добавление сео информации к модели

Сообщение Ruganin »

Народ подскажите. Почитал про идеи о сео параметрах описанных здесь. Однако мне требуется еще и сам url загнать в эти параметры, т.е. таблица будет выглядеть примерно так:

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `tbl_seo` (
  `route` varchar(64) NOT NULL,
  `params` varchar(128) NOT NULL,
  `url` varchar(255) NOT NULL,
  `metaTitle` varchar(500) DEFAULT NULL,
  `metaKeywords` varchar(500) DEFAULT NULL,
  `metaDescription` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`route`,`params`),
  UNIQUE KEY `url` (`url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
В url будет записываться чпу образный урл, т.к. формирование урл из тайтла например мне не подходит, т.к. при редактировании его сразу изменится и урл.

Вопрос собственно вот в чем:
Не столкнусь я в последствии с какими нибудь проблемами при таком подходе?

Ответить