Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 3b16b81

Browse files
committed
Lots of fixes
1 parent 0b45fa3 commit 3b16b81

File tree

3 files changed

+142
-103
lines changed

3 files changed

+142
-103
lines changed

bundles/seo/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ SeoBundle
66

77
introduction
88
seo_aware
9+
extractors

bundles/seo/introduction.rst

Lines changed: 35 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ The simplest use of this bundle would be to just set some configuration to the
4444
page:
4545
title: Page's default title
4646
metas:
47-
names:
47+
name:
4848
description: The default description of the page
4949
keywords: default, sonata, seo
5050
@@ -55,7 +55,7 @@ The simplest use of this bundle would be to just set some configuration to the
5555
'page' => array(
5656
'title' => 'Page's default title',
5757
'metas' => array(
58-
'names' => array(
58+
'name' => array(
5959
'description' => 'default description',
6060
'keywords' => 'default, key, other',
6161
),
@@ -110,12 +110,15 @@ This bundle provides two ways of using this metadata:
110110
#. Using the extractors, to extract the ``SeoMetadata`` from already existing
111111
values (e.g. the title of the page).
112112

113-
You can also use both ways at the same time for the document. In that case,
114-
the persisted ``SeoMetadata`` can be changed by the extractors.
113+
You can also combine both ways, even on the same document. In that case, the
114+
persisted ``SeoMetadata`` can be changed by the extractors, to add or tweak
115+
the current available SEO information. For instance, if you are writing a
116+
``BlogPost`` class, you want the SEO keywords to be set to the tags/category
117+
of the post and any additional tags set by the admin.
115118

116119
Persisting the ``SeoMetadata`` with the document makes it easy to edit for the
117-
admin, while using the extractors makes it perfect to use without doing
118-
anything.
120+
admin, while using the extractors are perfect to easily use values from the
121+
displayed content.
119122

120123
Both ways are documented in detail in seperate sections:
121124

@@ -130,8 +133,8 @@ URLs. The CMF allows you to have several URLs for the same content if you need
130133
that. There are two solutions to avoid penalties with search engines:
131134

132135
* Create a canonical link that identifies the original URL:
133-
``<link rel="canonical" href="/route/org/content">``;
134-
* Define an "original url" and redirect the other to that one.
136+
``<link rel="canonical" href="/route/org/content">``
137+
* Define an "original url" and redirect all duplicate URLs to it.
135138

136139
The ``SeoMetadata`` can be configured with the original URL for the current
137140
page. By default, this bundle will create a canonical link for the page. If
@@ -162,56 +165,25 @@ you want to change that to redirect instead, you can set the
162165
),
163166
);
164167
165-
Defining a Default
166-
------------------
167-
168-
You've learned everything about extracting SEO information from objects.
169-
However, in some cases the object doesn't provide any information or there is
170-
no object (e.g. on a login page). For these cases, you have to configure a
171-
default value. These default values can be configured for the SonataSeoBundle:
172-
173-
.. configuration-block::
174-
175-
.. code-block:: yaml
176-
177-
# app/config/config.yml
178-
sonata_seo:
179-
page:
180-
title: A Default Title
181-
metas:
182-
names:
183-
keywords: default, sonata, seo
184-
description: A default description
185-
186-
.. code-block:: php
187-
188-
// app/config/config.php
189-
$container->loadFromExtension(
190-
'sonata_seo', array(
191-
'page' => array(
192-
'title' => 'A Default Title',
193-
'metas' => array(
194-
'names' => array(
195-
'keywords' => 'default, key, other',
196-
'description' => 'A default description',
197-
),
198-
),
199-
),
200-
),
201-
);
202-
203-
The Standard Title and Description
204-
----------------------------------
168+
Defining a Title and Description Template
169+
-----------------------------------------
205170

206171
Most of the times, the title of a site has a static and a dynamic part. For
207-
instance, "The title of the Page - Symfony". Here "- Symfony" is static and
172+
instance, "The title of the Page - Symfony". Here, "- Symfony" is static and
208173
"The title of the Page" will be replaced by the current title. It is of course
209-
not nice if you need to add this static part to all your titles in documents.
174+
not nice if you had to add this static part to all your titles in documents.
175+
176+
That's why the CmfSeoBundle provides defining a title and description
177+
template. When using these settings, there are 2 placeholders available:
178+
``%content_title%`` and ``%content_description%``. These will be replaced with
179+
the title extracted from the content object and the description extracted from
180+
the content object.
181+
182+
.. caution::
210183

211-
That's why the CmfSeoBundle provides standard titles and descriptions. When
212-
using these settings, there are 2 placeholders available: ``%content_title%``
213-
and ``%content_description%``. This will be replaced with the title extracted
214-
from the content object and the description extracted from the content object.
184+
The default title and description set by the SonataSeoBundle do override
185+
this template. You should make sure that the defaults also follow the
186+
template.
215187

216188
For instance, to configure the titles of the symfony.com pages, you would do:
217189

@@ -243,10 +215,10 @@ For instance, to configure the titles of the symfony.com pages, you would do:
243215
character, otherwise the container will try to replace it with the value
244216
of a container parameter.
245217

246-
This syntax might look familiair if you have used with the Translation
247-
component before. And that's correct, under the hood the Translation component
248-
is used to replace the placeholders with the correct values. This also means
249-
you get Multi Language Support for free!
218+
This syntax might look familiar if you have used the Translation component
219+
before. And that's correct, under the hood the Translation component is used
220+
to replace the placeholders with the correct values. This also means you get
221+
Multi Language Support for free!
250222

251223
For instance, you can do:
252224

@@ -315,6 +287,11 @@ And then configure the translation messages:
315287
title: "%content_title% | Default title"
316288
description: "Default description. %content_description%"
317289
290+
.. tip::
291+
292+
You don't have to escape the percent characters here, since the
293+
Translation loaders know how to deal with them.
294+
318295
For changing the default translation domain (messages), you should use the
319296
``cmf_seo.translation_domain`` setting:
320297

bundles/seo/seo_aware.rst

Lines changed: 106 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ the ``SeoMetadata``::
3030
}
3131
}
3232

33-
Now you can set some SEO data for this ``Page`` using the metadata. For
34-
instance inside a data fixture::
33+
Now you can set some SEO data for this ``Page`` using the metadata::
34+
35+
$page = new Page();
36+
// ... set some page properties
37+
38+
$pageMetadata = new SeoMetadata();
39+
$pageMetadata->setDescription('A special SEO description.');
40+
$pageMetadata->setTags('seo, cmf, symfony');
41+
42+
$page->setSeoMetadata($pageMetadata);
3543

3644
// src/Acme/SiteBundle/DataFixture/PHPCR/LoadPageData.php
3745
namespace Acme\SiteBundle\DataFixtures\PHPCR;
@@ -59,23 +67,14 @@ instance inside a data fixture::
5967
}
6068
}
6169

62-
.. tip::
63-
64-
While this examples shows a Doctrine PHPCR ODM data fixture, the bundle
65-
works fully storage agnostic. You can use it with every storage system you
66-
like.
67-
68-
Persisting the SeoMetadata with Doctrine
69-
----------------------------------------
70+
Doctrine PHPCR-ODM Integration
71+
------------------------------
7072

71-
Since Doctrine doesn't allow you to persist an object as a database field,
72-
there is a problem. The bundle provides a solution to solve this by providing
73-
a Doctrine Listener. This listener will serialize the metadata object when
74-
persisting it and it'll unserialize the metadata when the object is fetched
75-
from the database.
73+
In order to easily persist the SeoMetadata when using Doctrine PHPCR-ODM, the
74+
SeoBundle provides a special ``SeoMetadata`` document with the correct
75+
mappings. This document should be mapped as a child of the content document.
7676

77-
In order to use this listener, you should activate either ``orm`` or ``phpcr``
78-
as persisting layer for the SeoBundle:
77+
To be able to use this document, you have to enable the PHPCR persistence:
7978

8079
.. configuration-block::
8180

@@ -85,18 +84,13 @@ as persisting layer for the SeoBundle:
8584
cmf_seo:
8685
persistence:
8786
phpcr: true
88-
# when using the ORM:
89-
# orm: true
9087
9188
.. code-block:: xml
9289
9390
<!-- app/config/config.xml -->
9491
<config xmlns="http://cmf.symfony.com/schema/dic/seo">
9592
<persistence>
9693
<phpcr />
97-
<!-- when using the ORM:
98-
<orm />
99-
-->
10094
</persistence>
10195
</config>
10296
@@ -106,45 +100,105 @@ as persisting layer for the SeoBundle:
106100
$container->loadFromExtension('cmf_seo', array(
107101
'persistence' => array(
108102
'phpcr' => true,
109-
// when using the ORM:
110-
// 'orm' => true,
111103
),
112104
));
113105
114-
This will automatically enable the listener. If you don't want to enable the
115-
listener, but you want to enable a persistence layer, you can set the
116-
``metadata_listener`` option to ``false``:
106+
.. tip::
107+
108+
This is not needed if you already enabled PHPCR on the ``cmf_core``
109+
bundle. See :doc:`the CoreBundle docs <../core/persistence>` for more
110+
information.
111+
112+
After you've enabled PHPCR, map your seoMetadata as a child:
117113

118114
.. configuration-block::
119115

116+
.. code-block:: php-annotations
117+
118+
// src/Acme/SiteBundle/Document/Page.php
119+
namespace Acme\SiteBundle\Document;
120+
121+
use Symfony\Cmf\Bundle\SeoBundle\Model\SeoAwareInterface;
122+
use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCR;
123+
124+
/**
125+
* @PHPCR\Document()
126+
*/
127+
class Page implements SeoAwareInterface
128+
{
129+
/**
130+
* @PHPCR\Child
131+
*/
132+
protected $seoMetadata;
133+
134+
// ...
135+
}
136+
120137
.. code-block:: yaml
121138
122-
# app/config/config.yml
123-
cmf_seo:
124-
persistence:
139+
# src/Acme/SiteBundle/Resources/config/doctrine/Page.odm.yml
140+
Acme\SiteBundle\Document\Page:
141+
# ...
142+
child:
125143
# ...
126-
metadata_listener: false
144+
seoMetadata: ~
127145
128146
.. code-block:: xml
129147
130-
<!-- app/config/config.xml -->
131-
<config xmlns="http://cmf.symfony.com/schema/dic/seo"
132-
metadata-listener="false"
148+
<!-- src/Acme/SiteBundle/Resources/config/doctrine/Page.odm.xml -->
149+
<?xml version="1.0" encoding="UTF-8" ?>
150+
<doctrine-mapping
151+
xmlns="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping"
152+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
153+
xsi:schemaLocation="http://doctrine-project.org/schemas/phpcr-odm/phpcr-mapping
154+
https://github.com/doctrine/phpcr-odm/raw/master/doctrine-phpcr-odm-mapping.xsd"
133155
>
134-
<persistence>
156+
<document name="Acme\SiteBundle\Document\Page">
135157
<!-- ... -->
136-
</persistence>
137-
</config>
158+
<child fieldName="seoMetadata" />
159+
</document>
160+
</doctrine-mapping>
138161
139-
.. code-block:: php
162+
And after that, you can use the
163+
``Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata`` document::
140164

141-
// app/config/config.php
142-
$container->loadFromExtension('cmf_seo', array(
143-
'persistence' => array(
144-
// ...
145-
),
146-
'metadata_listener' => false,
147-
));
165+
// src/Acme/SiteBundle/DataFixture/PHPCR/LoadPageData.php
166+
namespace Acme\SiteBundle\DataFixtures\PHPCR;
167+
168+
use Acme\SiteBundle\Document\Page;
169+
use Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata;
170+
use Doctrine\Common\Persistence\ObjectManager;
171+
use Doctrine\Common\DataFixtures\FixtureInterface;
172+
173+
class LoadPageData implements FixtureInterface
174+
{
175+
public function load(ObjectManager $manager)
176+
{
177+
$page = new Page();
178+
// ... set some page properties
179+
180+
$pageMetadata = new SeoMetadata();
181+
$pageMetadata->setDescription('A special SEO description.');
182+
$pageMetadata->setTags('seo, cmf, symfony');
183+
184+
$page->setSeoMetadata($pageMetadata);
185+
186+
$manager->persist($page);
187+
$manager->flush();
188+
}
189+
}
190+
191+
Doctrine ORM
192+
------------
193+
194+
You can also use the Doctrine ORM with the CmfSeoBundle. You can just use the
195+
``Symfony\Cmf\Bundle\SeoBundle\Model\SeoMetadata`` class and map it as an
196+
object.
197+
198+
You can also choose put the ``SeoMetadata`` class into a seperate table and
199+
adding a relation between the ``SeoMetadata`` class and the content entity. To
200+
do this, you have to enable ORM support just like you enabled PHPCR enabled
201+
above.
148202

149203
Form Type
150204
---------
@@ -159,3 +213,10 @@ Besides providing a form type, the bundle also provides a Sonata Admin
159213
Extension. This extension adds a field for the ``SeoMetadata`` when an admin
160214
edits an objec that implements the ``SeoAwareInterface`` in the Sonata Admin
161215
panel.
216+
217+
.. note::
218+
219+
The bundles requires the `BurgovKeyValueFormBundle`_ when using the sonata
220+
admin. Make sure you install and enable it.
221+
222+
.. _`BurgovKeyValueFormBundle`: https://github.com/Burgov/KeyValueFormBundle

0 commit comments

Comments
 (0)