Saving the SeoMetadata in the Object

2.0 version
Maintained Unmaintained

Saving the SeoMetadata in the Object

The SeoMetadata can be set on your model classes, so that you can persist it into the database. This option gives admins the possibility to change the SEO data for the object.

In order to save the SeoMetadata in the model, the object should implement the SeoAwareInterface. This requires a getter and a setter for the SeoMetadata:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// src/AppBundle/Document/Page.php
namespace AppBundle\Document;

use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;

class Page implements SeoAwareInterface
{
    protected $seoMetadata;

    // ...
    public function getSeoMetadata()
    {
        return $this->seoMetadata;
    }

    public function setSeoMetadata($metadata)
    {
        $this->seoMetadata = $metadata;
    }
}

Tip

Instead of implementing these methods yourself, you can also use the trait SeoAwareTrait to enable this behavior in your model.

Now you can set some SEO data for this Page using the metadata:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
use AppBundle\Document\Page;
use Symfony\Cmf\Bundle\SeoBundle\SeoMetadata;

$page = new Page();
// ... set some page properties

$pageMetadata = new SeoMetadata();
$pageMetadata->setDescription('A special SEO description.');
$pageMetadata->setTags('seo, cmf, symfony');

$page->setSeoMetadata($pageMetadata);

Doctrine PHPCR-ODM Integration

In order to easily persist the SeoMetadata when using Doctrine PHPCR-ODM, the SeoBundle provides a special SeoMetadata document with the correct mappings. This document should be mapped as a child of the content document.

To be able to use this document, you have to enable the PHPCR persistence:

  • YAML
    1
    2
    3
    4
    # app/config/config.yml
    cmf_seo:
        persistence:
            phpcr: true
    
  • XML
    1
    2
    3
    4
    5
    6
    <!-- app/config/config.xml -->
    <config xmlns="http://cmf.symfony.com/schema/dic/seo">
        <persistence>
            <phpcr />
        </persistence>
    </config>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // app/config/config.php
    $container->loadFromExtension('cmf_seo', [
        'persistence' => [
            'phpcr' => true,
        ],
    ]);
    

Tip

This is not needed if you already enabled PHPCR on the cmf_core bundle. See the CoreBundle docs for more information.

After you have enabled PHPCR, map $seoMetadata as a child:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // src/AppBundle/Document/Page.php
    namespace AppBundle\Document;
    
    use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;
    use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCR;
    
    /**
     * @PHPCR\Document()
     */
    class Page implements SeoAwareInterface
    {
        /**
         * @PHPCR\Child
         */
        protected $seoMetadata;
    
        // ...
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    # src/AppBundle/Resources/config/doctrine/Page.odm.yml
    AppBundle\Document\Page:
        # ...
        child:
            # ...
            seoMetadata: ~
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <!-- src/AppBundle/Resources/config/doctrine/Page.odm.xml -->
    <?xml ver<sion="1.0" encoding="UTF-8" ?>
    <doctrine-mapping
        xmlns="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping
        https://github.com/doctrine/phpcr-odm/raw/master/doctrine-phpcr-odm-mapping.xsd"
    >
        <document name="AppBundle\Document\Page">
            <!-- ... -->
            <child name="seoMetadata" />
        </document>
    </doctrine-mapping>
    

And after that, you can use the Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata document:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// src/AppBundle/DataFixture/PHPCR/LoadPageData.php
namespace AppBundle\DataFixtures\PHPCR;

use AppBundle\Document\Page;
use Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\DataFixtures\FixtureInterface;

class LoadPageData implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        if (!$dm instanceof DocumentManager) {
            $class = get_class($dm);
            throw new \RuntimeException("Fixture requires a PHPCR ODM DocumentManager instance, instance of '$class' given.");
        }

        $page = new Page();
        // ... set some page properties

        $pageMetadata = new SeoMetadata();
        $pageMetadata->setDescription('A special SEO description.');
        $pageMetadata->setTags('seo, cmf, symfony');

        $page->setSeoMetadata($pageMetadata);

        $manager->persist($page);
        $manager->flush();
    }
}

Doctrine ORM

You can also use the Doctrine ORM with the CmfSeoBundle. Use the Symfony\Cmf\Bundle\SeoBundle\SeoMetadata class and map it as an object:

  • Annotations
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // src/AppBundle/Entity/Page.php
    namespace AppBundle\Entity;
    
    use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Entity()
     */
    class Page implements SeoAwareInterface
    {
        /**
         * @ORM\Column(type="object")
         */
        protected $seoMetadata;
    
        // ...
    }
    
  • YAML
    1
    2
    3
    4
    5
    6
    7
    # src/AppBundle/Resources/config/doctrine/Page.orm.yml
    AppBundle\Entity\Page:
        # ...
        fields:
            # ...
            seoMetadata:
                type: object
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- src/AppBundle/Resources/config/doctrine/Page.orm.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
    
        <entity name="AppBundle\Entity\Page">
            <!-- ... -->
            <field name="seoMetadata" type="object" />
        </entity>
    </doctrine-mapping>
    

You can also choose to put the SeoMetadata class into a separate table. To do this, you have to enable ORM support just like you enabled PHPCR enabled above and add a OneToOne or ManyToOne relation between the content entity and the SeoMetadata entity.

Form Type

The bundle also provides a special form type called Symfony\Cmf\Bundle\SeoBundle\Form\Type\SeoMetadataType. This form type can be used in forms to edit the SeoMetadata object:

1
2
3
4
5
6
7
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Cmf\Bundle\SeoBundle\Form\Type\SeoMetadataType;

/** @var FormMapper $formMapper */
$formMapper
    ->add('seoMetadata', SeoMetadataType::class)
;

Caution

The form type requires the BurgovKeyValueFormBundle to be installed and registered.

Note

If you use Doctrine ORM, you need the form option by_reference set to false. If you enabled the ORM backend but not the PHPCR backend, this option is set by default, otherwise you need to explicitly specify it in your ORM forms.

Tip

The SonataPhpcrAdminIntegrationBundle provides an admin extension for the SeoAwareInterface.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.