druidvav/page-metadata-bundle
Composer 安装命令:
composer require druidvav/page-metadata-bundle
包简介
README 文档
README
Symfony bundle for managing page titles, meta tags, canonical URLs, Open Graph and Twitter metadata, breadcrumbs, and Schema.org JSON-LD from one request-scoped metadata object.
Requirements
- PHP 7.4 or later
- Symfony 5, 6, or 7
- Twig 2.7 or later
Installation
composer require druidvav/page-metadata-bundle
When Symfony Flex is not available, register the bundle manually:
// config/bundles.php return [ // ... Druidvav\PageMetadataBundle\DvPageMetadataBundle::class => ['all' => true], ];
Render the metadata in the document head and breadcrumbs where they belong in the page body:
<head> {{ page_meta() }} </head> <body> {{ page_breadcrumbs() }} </body>
page_meta() renders the title, standard meta tags, canonical link, Open Graph and Twitter tags, and structured data.
Configuration
base_url is required. All other sections are optional:
# config/packages/dv_page_metadata.yaml dv_page_metadata: base_url: '%env(DEFAULT_URI)%' title: default: 'Example' delimiter: ' - ' locale: null translation_domain: null meta: description: null keywords: null opengraph: site_name: 'Example' type: website image: '/default-cover.jpg' twitter_image: '/default-cover.jpg' twitter_site: '@example' breadcrumbs: listId: '' listClass: '' itemClass: '' linkRel: '' locale: null translation_domain: null viewTemplate: '@DvPageMetadata/breadcrumbs/bootstrap.html.twig' structured_data: enabled: true breadcrumbs: true nodes: { }
base_url is the canonical site root shared by metadata features that need to turn a path into an absolute URL. Values with and without a trailing slash are accepted; PageMetadata::setBaseUrl() strips trailing slashes before storing the value. A missing or empty value is rejected. Relative metadata paths such as /cover.jpg and structured-data identifiers such as /#organization are resolved against this URL; absolute URIs are left unchanged.
The locale and translation_domain configuration keys are retained by the bundle configuration. Set the active translation domain at runtime with PageMetadata::setTransDomain() when translated titles, descriptions, or breadcrumb labels are required.
Canonical URL, canonical language, Open Graph URL, and Twitter card type have no configuration defaults and are normally set per request through the PHP API.
Using PageMetadata
Inject PageMetadata into a controller, event listener, or another service:
use Druidvav\PageMetadataBundle\PageMetadata; final class ArticleController { private PageMetadata $pageMetadata; public function __construct(PageMetadata $pageMetadata) { $this->pageMetadata = $pageMetadata; } public function __invoke(Article $article): Response { $this->pageMetadata ->setTitle($article->getTitle()) ->setDescription($article->getDescription()) ->setImage($article->getCoverUrl()) ->setLinkCanonical($article->getCanonicalUrl()) ->setOgUrl($article->getCanonicalUrl()) ->setOgTwitterCard(PageMetadata::TWITTER_CARD_SUMMARY_LARGE_IMAGE); // Render the response. } }
Setter methods return the same PageMetadata instance and can be chained, except for setTransDomain() and setTitleDelimiter().
Setter injection trait
Autoconfigured Symfony services can use PageMetadataAwareTrait instead of constructor injection:
use Druidvav\PageMetadataBundle\PageMetadataAwareTrait; final class ArticleController { use PageMetadataAwareTrait; }
Constructor injection is preferable when page metadata is a required dependency. The trait is useful for optional integration or existing classes where changing the constructor is inconvenient.
Titles
setTitle() updates both the HTML page title and the Open Graph/Twitter title:
$pageMetadata->setTitle('Article title');
Titles can be composed using a configured delimiter:
use Druidvav\PageMetadataBundle\PageMetadata; $pageMetadata ->setTitle('Example') ->addTitle('Air quality', [], PageMetadata::MODE_PREPEND); // Air quality - Example
Available modes are:
PageMetadata::MODE_SET— replace all title parts;PageMetadata::MODE_PREPEND— add a part before the existing title;PageMetadata::MODE_APPEND— add a part after the existing title.
Use setPageTitle() and addPageTitle() when only the HTML <title> should change. Use setOgTitle() and addOgTitle() when only Open Graph and Twitter title tags should change.
Descriptions and keywords
setDescription() updates both the standard meta description and the Open Graph/Twitter description:
$pageMetadata->setDescription('Current air quality and pollution measurements.');
They can also be controlled independently:
$pageMetadata->setMetaDescription('Search result description.'); $pageMetadata->setOgDescription('Social sharing description.');
setMetaKeywords() accepts a comma-separated string, trims individual values, and removes duplicates:
$pageMetadata->setMetaKeywords('air quality, Armenia, air quality'); // air quality, Armenia
Translation
Set a translation domain before passing translation IDs:
$pageMetadata->setTransDomain('messages'); $pageMetadata->setTitle('article.page_title', [ '%title%' => $article->getTitle(), ]); $pageMetadata->addRouteItem('navigation.home', 'homepage');
The bundle treats lowercase identifiers containing letters, numbers, _, -, or . as translation IDs. Strings containing % are also passed through the translator. Other strings are used as provided.
An explicit translation domain can be passed to description setters:
$pageMetadata->setDescription('article.description', [], 'articles'); $pageMetadata->setMetaDescription('article.search_description', [], 'articles'); $pageMetadata->setOgDescription('article.share_description', [], 'articles');
Canonical metadata
$pageMetadata ->setLinkCanonical('https://example.com/en/articles/air-quality') ->setLinkCanonicalLang('en') ->setOgUrl('https://example.com/en/articles/air-quality');
The values are available in Twig through page_link_canonical(), page_link_canonical_lang(), and page_og_url().
Open Graph and Twitter
Convenience setters keep common values synchronized:
$pageMetadata->setTitle('Page title'); // HTML title and OG/Twitter title $pageMetadata->setDescription('Summary'); // meta and OG/Twitter description $pageMetadata->setImage($absoluteImageUrl); // OG and Twitter image
Individual fields can be changed separately:
$pageMetadata ->setOgType('article') ->setOgSiteName('Example') ->setOgTitle('Social title') ->setOgDescription('Social description') ->setOgImage('https://example.com/og-cover.jpg') ->setOgTwitterImage('https://example.com/twitter-cover.jpg') ->setOgTwitterSite('@example') ->setOgTwitterCard(PageMetadata::TWITTER_CARD_SUMMARY_LARGE_IMAGE);
Supported Twitter card constants are:
PageMetadata::TWITTER_CARD_SUMMARY;PageMetadata::TWITTER_CARD_SUMMARY_LARGE_IMAGE.
Configure or set og:site_name when Open Graph output is used. The default metadata template renders og:type together with og:site_name.
Breadcrumbs
Add breadcrumb labels and routes in display order:
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; $pageMetadata ->addRouteItem('navigation.home', 'homepage') ->addRouteItem( 'navigation.article', 'article_show', ['slug' => $article->getSlug()], UrlGeneratorInterface::ABSOLUTE_PATH, ['%title%' => $article->getTitle()] );
Arguments of addRouteItem() are:
- label or translation ID;
- Symfony route name;
- route parameters;
- URL reference type, defaulting to
ABSOLUTE_PATH; - translation parameters for the label.
Render the default breadcrumb namespace with:
{{ page_breadcrumbs() }}
Template options can be overridden for one rendering:
{{ page_breadcrumbs({
listId: 'page-breadcrumbs',
listClass: 'mb-4',
itemClass: 'text-secondary',
linkRel: 'nofollow'
}) }}
The default template contains Bootstrap 4/5-compatible markup. A Bootstrap 3 variant is available at @DvPageMetadata/breadcrumbs/bootstrap3.html.twig. A custom template receives the configured options and a breadcrumbs array containing Breadcrumb objects with text and url properties.
Breadcrumb namespaces are supported by getNsBreadcrumbs() and by the rendering function's namespace option. Adding items to a custom namespace requires extending PageMetadata and using its protected addBreadcrumbToNs() method. The public addRouteItem() method adds to the default namespace.
Structured data
The bundle renders Schema.org data as one JSON-LD object containing a single @context and an @graph with all configured and dynamic nodes.
Static nodes
Site-wide nodes can be configured once:
dv_page_metadata: base_url: '%env(DEFAULT_URI)%' structured_data: enabled: true breadcrumbs: true nodes: organization: '@type': Organization '@id': '/#organization' name: Example url: '/' logo: '/logo.jpg' website: '@type': WebSite '@id': '/#website' name: Example url: '/' publisher: '@id': '/#organization' inLanguage: [en, fr]
The YAML keys organization and website are internal node names. They are not included in the generated JSON-LD.
Dynamic nodes
Add page-specific data through PageMetadata:
$pageMetadata->setStructuredData('article', [ '@type' => 'BlogPosting', '@id' => $article->getCanonicalUrl() . '#article', 'headline' => $article->getTitle(), 'description' => $article->getDescription(), 'datePublished' => $article->getPublishedAt(), 'dateModified' => $article->getModifiedAt(), 'publisher' => [ '@id' => 'https://example.com/#organization', ], ]);
Calling setStructuredData() with the same internal name replaces the previous node without changing its graph position. This can be used to override a node loaded from configuration.
The node-level @context key is removed because the bundle owns the graph context. Other Schema.org properties remain generic, so the API can represent any current or future Schema.org type.
Date and value normalization
Any DateTimeInterface value is converted recursively to DATE_ATOM ISO 8601 format:
$pageMetadata->setStructuredData('event', [ '@type' => 'Event', 'startDate' => new DateTimeImmutable('2026-08-01 10:00:00+04:00'), 'subEvent' => [ 'startDate' => new DateTime('2026-08-01 12:00:00+04:00'), ], ]);
Structured values may contain strings, integers, floats, booleans, null, nested arrays, and DateTimeInterface instances. Strings starting with / or # are resolved against base_url; absolute URIs and other strings are preserved. Unsupported objects or resources cause an InvalidArgumentException whose message includes the property path.
Removing and reading nodes
$pageMetadata->removeStructuredData('article'); $pageMetadata->clearStructuredData(); $namedNodes = $pageMetadata->getStructuredData(); $graph = $pageMetadata->getStructuredDataGraph(); $graphWithoutBreadcrumbs = $pageMetadata->getStructuredDataGraph(false);
getStructuredData() preserves internal names. getStructuredDataGraph() returns the sequential array used as @graph and optionally appends generated breadcrumb data.
BreadcrumbList
When structured_data.breadcrumbs is enabled and the default namespace contains at least two breadcrumbs, the bundle appends a BreadcrumbList node automatically. Relative breadcrumb paths use the global base_url; the current request is not used to determine the host.
Rendering and escaping
Structured data is included automatically by page_meta():
{{ page_meta() }}
page_structured_data() is available for custom head templates that render individual metadata functions instead of calling page_meta():
<title>{{ page_title() }}</title> {{ page_structured_data() }}
Do not call both page_meta() and page_structured_data() in the same document, because page_meta() already includes the JSON-LD block.
JSON is encoded with Unicode and URLs left readable, while HTML-sensitive characters are escaped to prevent values such as </script> from leaving the JSON-LD script element.
Autotext integration
The optional meniam/autotext package can generate title, description, and keyword variants:
composer require meniam/autotext
Available methods are:
$pageMetadata->setTitleAutotext($title, [], $stableId); $pageMetadata->setMetaDescriptionAutotext($description, [], $stableId); $pageMetadata->setMetaKeywordsAutotext($keywords, [], $stableId);
The optional stable ID controls deterministic variant selection according to the Autotext package behavior.
When the optional package is not installed, calling any Autotext method throws a LogicException containing the installation command instead of causing a missing-class error.
Twig functions
| Function | Result |
|---|---|
page_meta() |
Complete metadata HTML, including structured data |
page_breadcrumbs(options = {}) |
Rendered breadcrumb HTML |
page_structured_data() |
JSON-LD script for custom metadata templates |
page_title() |
Composed HTML page title |
page_description(default = null) |
Meta description or supplied default |
page_keywords(default = null) |
Meta keywords or supplied default |
page_link_canonical() |
Canonical URL |
page_link_canonical_lang() |
Canonical language value |
page_og_type() |
Open Graph type |
page_og_url() |
Open Graph URL |
page_og_site_name() |
Open Graph site name |
page_og_image() |
Open Graph image |
page_og_title() |
Composed Open Graph/Twitter title |
page_og_description() |
Open Graph/Twitter description |
page_twitter_image() |
Twitter image |
page_twitter_site() |
Twitter account |
page_twitter_card() |
Twitter card type |
Custom templates
The built-in templates are:
@DvPageMetadata/meta.html.twig— complete metadata output;@DvPageMetadata/structured_data.html.twig— JSON-LD script wrapper;@DvPageMetadata/breadcrumbs/bootstrap.html.twig— Bootstrap 4/5 breadcrumbs;@DvPageMetadata/breadcrumbs/bootstrap3.html.twig— Bootstrap 3 breadcrumbs.
Configure breadcrumbs.viewTemplate to use an application template. Symfony's standard bundle template overriding mechanism can also be used to customize metadata output globally.
Testing
Install development dependencies and run:
composer install
composer test
druidvav/page-metadata-bundle 适用场景与选型建议
druidvav/page-metadata-bundle 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 5.93k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2017 年 06 月 30 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 druidvav/page-metadata-bundle 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 druidvav/page-metadata-bundle 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 druidvav/page-metadata-bundle 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This module allows drag & drop grouping of items in a GridField
Adds text size controls and text-to-speech controls to Flarum discussion content.
Native Blade date, datetime, and date range pickers.
Symfony and Flysystem integration for the maintained KCFinder continuation.
Laravel integration for the maintained KCFinder continuation.
PHPStan rules shared across KnpLabs organization projects
统计信息
- 总下载量: 5.93k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 4
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2017-06-30