Developed with love by KnpLabs Hire us for your project!
36

SeoBundle

by leogout

A Symfony bundle to generate SEO meta tags.

LeogoutSeoBundle

This bundle provides a simple and flexible API to manage search engine optimization (SEO) tags in your application.
Its main goal is to make it simple for you to manage the most common meta, open graph and twitter card tags
and to let you configure less common ones with ease.

Build Status
Scrutinizer Code Quality

Installation

Install the bundle with the command:

composer require leogout/seo-bundle

Register the bundle in your AppKernel:
php
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
// ...
new Leogout\Bundle\SeoBundle\LeogoutSeoBundle(),
);
}
}

Configuration

These configuration values are the defaults used to render your tags.
See the next section to learn how to override them dynamically.

There are four sections in the config:
* general: The global configuration. Its values are shared among the other as defaults.
* basic: A set of the most common SEO tags.
* og: A set of open graph tags based on http://ogp.me/.
* twitter: A set of twitter card tags based on https://dev.twitter.com/cards/types

See "Configuration reference" to get the whole configuration.

In your config.yml:
yml
leogout_seo:
general:
title: Default title
description: Default description.
image: http://images.com/poneys/12/large # This one is shared by open graph and twitter only
basic:
title: Awesome title
keywords: default, keywords
og:
type: website
url: http://test.com/articles
twitter:
card: summary
site: '@leogoutt'

In your view:
twig
<head>
{{ leogout_seo() }}
</head>

NOTE: You can provide a generator name to the leogout_seo() twig method to render it specifically.
For example, to render the basic seo generator, you can use leogout_seo('basic').

The result:
html
<head>
<title>Awesome title</title>
<meta name="description" content="Default description." />
<meta name="keywords" content="default, keywords" />
<meta name="og:title" content="Default title" />
<meta name="og:description" content="Default description." />
<meta name="og:image" content="http://test.com/articles" />
<meta name="og:type" content="website" />
<meta name="twitter:title" content="Default title" />
<meta name="twitter:description" content="Default description." />
<meta name="twitter:image" content="http://images.com/poneys/12/large" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@leogoutt" />
</head>

NOTE: By default, the SEO generators aren't loaded if you don't require them in the config.
However, if you want to use the associated generators without configuring any default values
(or configuring only the general ones), you can use this notation:

leogout_seo:
   general:
       title: Default title
       description: Default description.
       image: http://images.com/poneys/12/large # This one is shared by open graph and twitter only
   basic: ~
   og: ~
   twitter: ~

Setting values dynamically

You can get the '[basic|twitter|og] as a service to set or override any values.
Each value of the configuration can be overrided using a setter of the following form:
$this->get('leogout_seo.provider.generator')->get(' [basic|twitter|og] ')->set [config field name] ( [value] )

For example, if you want to change title and robots from basic, you can do this:
```php
class DefaultController extends Controller
{
public function indexAction()
{
$this->get('leogout_seo.provider.generator')->get('basic')
->setTitle('Title set in controller')
->setRobots(true, false); // they can be chained

    return $this->render('AppBundle:Default:index.html.twig');
}

}
```

Setting values from a resource

You can configure your own model classes to let the seo generators do all the work thanks to the fromResource() method.
Multiple interfaces are available to help the method guess which setters to call to fill the tags.

This is an exemple for the basic generator:
In your resource:
```php
use Leogout\Bundle\SeoBundle\Seo\Basic\BasicSeoInterface;

class MyResource implements BasicSeoInterface
{
protected $name;
protected $description;
protected $tags = [];

// ...Your logic

// These methods are from BasicSeoInterface and have to
// return a string (or an object with a __toString() method).
public function getSeoTitle()
{
    return $this->name; 
}
public function getSeoDescription()
{
    return $this->description; 
}
public function getSeoKeywords()
{
    return implode(',', $this->tags); 
}

}
```

In your controller:
```php
class MyController extends Controller
{
public function indexAction(Request $request)
{
$myResource = new MyResource();
$myResource
->setName('Cool resource')
->setDescription('Some description')
->addKeyword('hey')
->addKeyword('ho')
->addKeyword('let's go!');

    $this->get('leogout_seo.provider.generator')->get('basic')->fromResource($myResource);

    return $this->render('MyController:Default:index.html.twig');
}

}
```

In your view:
twig
<head>
{{ leogout_seo('basic') }}
</head>

The result:
html
<head>
<title>Cool resource</title>
<meta name="description" content="Some description" />
<meta name="keywords" content="hey,ho,let's go!" />
</head>

There are three main interfaces, one for each generator:
* BasicSeoInterface for basic
* OgSeoInterface for og
* TwitterSeoInterface for twitter

These interfaces extends simpler interfaces which you can inplement instead or additionnally.
For example, if you only have a meta description on your resource, you can implement DescriptionSeoInterface only to provide a description alone.
This is the list of the different interfaces and what they extends:

TitleSeoInterface DescriptionSeoInterface KeywordsSeoInterface ImageSeoInterface
BasicSeoInterface
OgSeoInterface
TwitterSeoInterface

Advanced usage

If the built-in generators don't suit your needs, LeogoutSeoBundle provides a way to create your own SEO generators.
First, you have to create a class that extends the AbstractSeoGenerator class:
```php
use Leogout\Bundle\SeoBundle\Seo\AbstractSeoGenerator;

class MyTagsGenerator extends AbstractSeoGenerator
{
public function setMyTag($content)
{
$this->tagBuilder->addMeta('myTag')
->setType(MetaTag::NAME_TYPE)
->setValue('myAwesomeTag')
->setContent((string) $content);

    return $this;
}

public function getMyTag()
{
    return $this->tagBuilder->getMeta('myTag');
}

}
```

Then, register it as a service and add it a leogout_seo.generator tag and a custom alias.
Don't forget the @leogout_seo.builder dependency:
yaml
services:
app.seo_generator.my_tags:
class: AppBundle\Generator\MyTagsGenerator
arguments: [ '@leogout_seo.builder' ] # This is required
tags: { name: leogout_seo.generator, alias: my_tags }

That's it, now you can use it alongside the others:

In your controller:
```php
class MyController extends Controller
{
public function indexAction(Request $request)
{
$this->get('leogout_seo.provider.generator')->get('my_tags')->setMyTag('cool');

    return $this->render('MyController:Default:index.html.twig');
}

}
```

In your view:
twig
<head>
{{ leogout_seo('my_tags') }}
</head>

Result:
html
<head>
<meta name="myAwesomeTag" content="cool" />
</head>

Configuration reference

leogout_seo:
    general:
        title: Default title
        description: Default description.
        image: http://images.com/poneys/12/large
    basic:
        title: Basic title
        description: Basic description.
        keywords: default, keywords
        canonical: http://test.com
        robots:
            index: false
            follow: false
    og:
        title: Open graph title
        description: Open graph description.
        image: http://images.com/poneys/12/large
        type: website # article, book, profile
        url: http://test.com/articles
    twitter:
        title: Twitter title
        description: Twitter description.
        image: http://images.com/poneys/12/thumbnail
        card: summary # summary_large_image
        site: '@leogoutt' # optionnal

Contributing

If you want to contribute (thank you!) to this bundle, here are some guidelines:

  • Please respect the Symfony guidelines
  • Test everything! Please add tests cases to the tests/ directory when:
    • You fix a bug that wasn't covered before
    • You add a new feature
    • You see code that works but isn't covered by any tests (there is a special place in heaven for you)

Todo

  • Packagist

Thanks

Many thanks to the ARCANEDEV/SEO-Helper who authorized me to take some ideas from their library and to KnpMenuBundle which inspired me for the Providers APIs.

leogout_seo:
general:
title: ~
description: ~
image: ~
basic:
title: ~
description: ~
keywords: ~
robots:
index: true
follow: true
canonical: ~
og:
title: ~
description: ~
image: ~
type: ~
url: ~
twitter:
title: ~
description: ~
image: ~
card: ~
site: ~
  • Added requirements for sf 4.0 + phpunit-bridge 4.0 #7
    By web-flow, 1 year ago
  • Merge pull request #5 from innerspirit/fix-doc
    By web-flow, 1 year ago
  • Completed docs with bug fix
    By web-flow, 1 year ago
  • Fix bad examples and small configurator bug
    By , 1 year ago
  • Updated scrutinizer badge
    By web-flow, 1 year ago
  • Merge pull request #4 from innerspirit/patch-2
    By web-flow, 1 year ago
  • Docs: added installation command
    By web-flow, 1 year ago
  • Added travis and scrutinizer links
    By leogout, 2 years ago
  • Merge pull request #3 from leogout/develop
    By web-flow, 2 years ago
  • Removed the do not use warning
    By leogout, 2 years ago
  • Added twig extension modification to README
    By leogout, 2 years ago
  • Twig extension renders all providers if no alias is provided
    By leogout, 2 years ago
  • Made whole configuration optionnal
    By leogout, 2 years ago
  • Final documentation layout
    By leogout, 2 years ago
  • Better README and typo fixes in classes
    By leogout, 2 years ago
  • Factorisation of generators render() method
    By leogout, 2 years ago
  • Fixed major Scrutinizer issues
    By leogout, 2 years ago
  • Fixed minor Scrutinizer issues
    By leogout, 2 years ago
  • Added custom exception if unexpected seo generator is passed to configurator.
    By leogout, 2 years ago
  • Merge pull request #2 from leogout/new-configuration
    By web-flow, 2 years ago
  • Added new config to README
    By leogout, 2 years ago
  • Made tests more readable
    By leogout, 2 years ago
  • Switching from global phpunit to vendor phpunit
    By leogout, 2 years ago
  • Fixed travis config
    By leogout, 2 years ago
  • Simplification of TitleTag
    By leogout, 2 years ago
  • Added tests for SeoGeneratorPass
    By leogout, 2 years ago
  • Switched to phpunit instead of simple-phpunit
    By leogout, 2 years ago
  • Added abstract seo configurator to hold common config tasks
    By leogout, 2 years ago
  • Added tests for twitter generator + configurator
    By leogout, 2 years ago
  • Added tests to Open graph generator + configurator
    By leogout, 2 years ago