Как обрабатывать метаописание/ключевые слова в приложении Zend Framework 2?

Страница по умолчанию title, определенная в файле макета, может быть расширена (PREPEND/APPEND) или заменена (SET) заголовком, характерным для текущего представления.

Я также ожидал такого поведения для HeadMeta. помощник просмотра. Теперь я не могу найти правильный способ «расширить» стандартные descrition/keywords, которые я определил в файле макета.

Вместо этого я могу добавить дополнительный тег meta с append(...)/appendName(...) (аналогично добавлению файла стиля или скрипта с помощью HeadLink или HeadScript). Но это не имеет смысла для тегов descrition и keywords meta.

Есть ли рекомендуемый подход для решения этой проблемы? Как обрабатывать теги description/keywords meta?


person automatix    schedule 30.04.2013    source источник


Ответы (2)


Вот быстрый и грязный обходной путь, который я сейчас использую (для чистого решения вместо уродливого обходного пути необходимы изменения в структуре):

Помощник представления HeadMeta

<?php
namespace MyNamespace\View\Helper;

use stdClass;
use Zend\View;
use Zend\View\Exception;
use Zend\View\Helper\HeadMeta as ZendHeadMeta;
use Zend\View\Helper\Placeholder\Container\AbstractContainer;

class HeadMeta extends ZendHeadMeta {

    const DELIMITER = ' - ';

    /**
     * @see \Zend\View\Helper\HeadMeta::__invoke()
     */
    public function __invoke($content = null, $keyValue = null, $keyType = 'name', $modifiers = array(), $placement = AbstractContainer::APPEND) {
        parent::__invoke($content, $keyValue, $keyType, $modifiers, $placement);
        return $this;
    }

    /**
     * @see \Zend\View\Helper\HeadMeta::append()
     */
    public function append($value) {
        if ($value->name == 'description') {
            $this->updateDescription($value, AbstractContainer::APPEND);
        } else if ($value->name == 'keywords') {
            $this->updateKeywords($value, AbstractContainer::APPEND);
        } else {
            parent::append($value);
        }
    }

    /**
     * @see \Zend\View\Helper\HeadMeta::prepend()
     */
    public function prepend($value) {
        if ($value->name == 'description') {
            $this->updateDescription($value, AbstractContainer::PREPEND);
        } else if ($value->name == 'keywords') {
            $this->updateKeywords($value, AbstractContainer::PREPEND);
        } else {
            parent::prepend($value);
        }
    }

    // Not working correctly!
    // Can cause a
    // Fatal error: Maximum function nesting level of '100' reached, aborting!
    /**
     * @see \Zend\View\Helper\HeadMeta::set()
     */
    public function set($value) {
        if ($value->name == 'description') {
            $this->updateDescription($value, AbstractContainer::SET);
        } else if ($value->name == 'keywords') {
            $this->updateKeywords($value, AbstractContainer::SET);
        } else {
            parent::set($value);
        }
    }

    /**
     * If a description meta already exsists, extends it with $value->content,
     * else creates a new desctiprion meta.
     * @param \stdClass $value
     * @param string $position
     */
    public function updateDescription(\stdClass $value, $position = AbstractContainer::SET) {
        $descriptionExists = false;
        foreach ($this->getContainer() as $item) {
            if ($this->isDescription($item)) {
                switch ($position) {
                    case AbstractContainer::APPEND:
                        $descriptionString = implode(static::DELIMITER, array($item->content, $value->content));
                        break;
                    case AbstractContainer::PREPEND:
                        $descriptionString = implode(static::DELIMITER, array($value->content, $item->content));
                        break;
                    case AbstractContainer::SET:
                    default:
                        $descriptionString = $value->content;
                        break;
                }
                $item->content = $descriptionString;
                $descriptionExists = true;
            }
        }
        if (!$descriptionExists) {
            switch ($position) {
                case AbstractContainer::APPEND:
                    parent::append($value);
                    break;
                case AbstractContainer::PREPEND:
                    parent::prepend($value);
                    break;
                case AbstractContainer::SET:
                default:
                    parent::set($value);
                    break;
            }
        }
    }

    /**
     * If a keywords meta already exsists, extends it with $value->content,
     * else creates a new keywords meta.
     * @param \stdClass $value
     * @param string $position
     */
    public function updateKeywords(\stdClass $value, $position = AbstractContainer::SET) {
        $keywordsExists = false;
        foreach ($this->getContainer() as $item) {
            if ($this->isKeywords($item)) {
                switch ($position) {
                        case AbstractContainer::APPEND:
                            $keywordsString = implode(', ', array($item->content, $value->content));
                            break;
                        case AbstractContainer::PREPEND:
                            $keywordsString = implode(', ', array($value->content, $item->content));
                            break;
                        case AbstractContainer::SET:
                        default:
                            $keywordsString = $value->content;
                            break;
                }
                $item->content = $keywordsString;
                $keywordsExists = true;
            }
        }
        if (!$keywordsExists) {
            parent::append($value);
        }
    }

    /**
     * @return description meta text
     */
    public function getDescription() {
        $description = null;
        foreach ($this->getContainer() as $item) {
            if ($this->isKeywords($item)) {
                $description = $item->content;
                break;
            }
        }
        return $description;
    }

    /**
     * @return keywords meta text
     */
    public function getKeywords() {
        $keywords = null;
        foreach ($this->getContainer() as $item) {
            if ($this->isKeywords($item)) {
                $keywords = $item->content;
                break;
            }
        }
        return $keywords;
    }

    /**
     * Checks, whether the input $item is an approproate object for $this->container
     * and wheter it's a description object (its name is "description")
     * @param stdClass $item
     * @throws Exception\InvalidArgumentException
     * @return boolean
     */
    public function isDescription(stdClass $item) {
        if (!in_array($item->type, $this->typeKeys)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Invalid type "%s" provided for meta',
                $item->type
            ));
        }
        return $item->name == 'description';
    }

    /**
     * Checks, whether the input $item is an approproate object for $this->container
     * and wheter it's a keywords object (its name is "keywords")
     * @param stdClass $item
     * @throws Exception\InvalidArgumentException
     * @return boolean
     */
    public function isKeywords(stdClass $item) {
        if (!in_array($item->type, $this->typeKeys)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Invalid type "%s" provided for meta',
                $item->type
            ));
        }
        return $item->name == 'keywords';
    }

}

/module/Application/view/layout/layout.phtml

<?php
$this->headMeta()->appendName(
    'description',
    $this->translate('default description')
);
$this->headMeta()->appendName(
    'keywords',
    implode(', ', array(
        $this->translate('default keyword 1'),
        $this->translate('default keyword 2'),
        $this->translate('default keyword 3'),
    ))
);
echo $this->headMeta();
?>

просмотреть сценарий

<?php
$this->headMeta()->setName('keywords', implode(
    ', ',
    array(
        $this->translate('view specific keyword 1'),
        $this->translate('view specific keyword 2'),
        $this->translate('view specific keyword 3'),
    )
));
$this->headMeta()->setName('description', 'view specific description');
?>
person automatix    schedule 01.05.2013
comment
Ваше решение работает, но, пожалуйста, добавьте небольшую заметку о том, что помощник должен быть правильно прикреплен к модулю. Например, следующая строка должна существовать в module.config.php 'view_helpers' => array( 'invokables' => array( 'headMeta' => '\YourModule\View\Helper\HeadMeta' ) - person zelibobla; 29.11.2014
comment
Получил работу! Сначала я добавил комментарий @zeliboba (с завершающей скобкой;), но затем получил ошибку: Неустранимая ошибка PHP: неперехваченное исключение 'Zend\\ServiceManager\\Exception\\ServiceNotFoundException' с сообщением 'Zend\\View\\HelperPluginManager ::createFromInvokable: не удалось получить мету заголовка (псевдоним: headMeta) через вызываемый класс MyModule\\View\\Helper\\HeadMeta; класс не существует ' - что было решено путем создания новой карты классов для модуля с помощью ./bin/classmap_generator.php - person Petter Soderlund; 21.10.2015

Ссылка на мой ответ здесь: Как изменить мета теги в макете Zend Framework

Вот что сработало для меня. В файле макета вы должны убедиться, что метатеги отображаются. На этапе он пуст, но вы будете отмечать, где будут выводиться метатеги. Единственным недостатком этого метода будет то, что, похоже, нет способа иметь метатег по умолчанию, поэтому вам придется добавлять метатег в каждый файл представления.

В файле макета

<?php echo $this->headMeta(); ?>

В файле представления .phtml

$this->headMeta("test description text", "description");
person ChrisBorg    schedule 07.03.2014
comment
Вопрос в том, как заменить ранее определенный метатег. В вашем примере ранее определенная мета не существует, поэтому вы даете нерелевантный ответ. - person zelibobla; 29.11.2014