This bundle add SEO capabilities for entities in any SF3 project. So far it handles:
- SEO meta (title, desc, slug with URL rewrite)
- Minimal OpenGraph implementation
- Canonical URL
Installation using composer
$ composer require lch/seo-bundle
SeoBundle allows to generate minimal SEO requirements for specific pages (like homepage) or 'entity' pages (like news page). SEO for 'entity' pages is automatically generated. For specifics pages, follow these steps:
# app/config/config.yml
lch_seo:
specific:
route_name:
tags:
title: Page title # Title of the current page
description: Page description # Desctiption (meta) of the current page
sitemap:
loc: / # URL of page
priority: 1.0 # Priority
other_route_name:
...
To automatically generate SEO for 'entity' pages, follow theses 2 steps:
Add Seoable
to any entity you want to have SEO settings on. This include
- seoTitle
- seoDescription
- slug field
use Lch\SeoBundle\Behaviour\Seoable;
use Lch\SeoBundle\Model\SeoInterface;
class MyEntity implements SeoInterface
{
use Seoable;
...
Implements SeoInterface
and fill 5 methods
getSluggableFields
for getting fields name needed to build slug
/**
* @inheritdoc
*/
public function getSluggableFields()
{
// This assume your entity have a field 'title'
return [
'title'
];
}
getRouteFields
for getting fields name needed to build route
An array is expected here, each key based on following pattern : routeParameter => entityParameter
/**
* @inheritdoc
*/
public function getRouteFields()
{
return [
'slug' => 'slug'
];
}
getRouteName
for allowing URL generation in SEO area (canonical URL, OpenGraph...)
/**
* @inheritdoc
*/
public function getRouteName()
{
// This assume to return the entity show page route
return 'yourproject_yourentity_show';
}
getSeoTitleDefaultValue
for pointing a field to use in case of SEO title empty (to generate default one)
/**
* @inheritdoc
*/
public function getSeoTitleDefaultValue()
{
return $this->title;
}
getOpenGraphData
should return an array with OpenGraph data, such as : So far,SeoInterface
declares following OG constants :
const OG_TITLE = 'title';
const OG_TYPE = 'type';
const OG_URL = 'url';
const OG_IMAGE = 'image';
Array returned example :
/**
* @inheritdoc
*/
public function getOpenGraphData()
{
$openGraphData = [
static::OG_TITLE => $this->title,
static::OG_TYPE => "Open Graph type"
];
// Image check example
if($this->headBandImage instanceof Image) {
$imageData = explode('/web', $this->getHeadBandImage()->getFile());
$openGraphData[static::OG_IMAGE] = array_pop($imageData);
}
return $openGraphData;
}
We assume that a unique constraint/index is set on slug field, or slug fields collection if more than one.
In addition, ton ensure proper form validation, be sure to add @UniqueEntity
constraint, at least on slug
field :
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Class MyEntity
* @package App\Entity\MyEntity
*
* @ORM\Table
* @ORM\Entity
* @UniqueEntity("slug")
*/
class MyEntity implements SeoInterface
{
use Seoable;
...
The bundle provides an SeoType, you can add to entities implementing SeoInterface types
use Lch\SeoBundle\Form\SeoType;
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('seo', SeoType::class, array(
'label' => 'lch.seo.form.label',
'required' => false,
'attr' => [
'no_label' => true,
'force_two_columns_presentation' => true
]
))
;
}
Note: attr
used are detailled with AdminBundle
Then, in the form twigs, add SEO form theme : {{ form_row(form.seo) }}
to ensure fields rendering and logic.
Simply add a seo block in your base.html.twig
in <head>
section
{% block seo %}{% endblock seo %}
Then, override this block on each page you want to display SEO information, with a custom Twig function:
- Specific pages :
{% block seo %}
{{ renderSeoTags(app.request) }}
{% endblock seo %}
Note: app.request
needs to be setting up here to generate SEO according to current route defined in config.yml
- Entity pages :
{% block seo %}
{{ renderSeoTags(entity) }}
{% endblock seo %}
So far, add call to $this->get('lch.seo.tools')->seoFilling()
on controller before persist to ensure data will be set. Will be replaced with doctrine event later