PHP code example of rasuvaeff / yii3-seo

1. Go to this page and download the library: Download rasuvaeff/yii3-seo library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

rasuvaeff / yii3-seo example snippets


use Rasuvaeff\Yii3Seo\MetadataDefaults;
use Rasuvaeff\Yii3Seo\OpenGraph;
use Rasuvaeff\Yii3Seo\SelfCanonical;
use Rasuvaeff\Yii3Seo\SelfCanonicalMiddleware;
use Rasuvaeff\Yii3Seo\Title;
use Rasuvaeff\Yii3Seo\TwitterCard;

return [
    'rasuvaeff/yii3-seo' => [
        'defaults' => new MetadataDefaults(
            metadataBase: 'https://example.com',
            title: Title::template('%s | My Store', default: 'My Store'),
            openGraph: new OpenGraph(siteName: 'My Store', locale: 'en_US'),
            twitter: new TwitterCard(card: 'summary_large_image', site: '@mystore'),
            selfCanonical: SelfCanonical::enabled(),   // optional
        ),
    ],

    'middlewares' => [
        SelfCanonicalMiddleware::class,               // only for selfCanonical
        // ... router and the rest of the stack
    ],
];

use Rasuvaeff\Yii3Seo\SeoInjection;
use Yiisoft\Yii\View\Renderer\CsrfViewInjection;
use Yiisoft\Yii\View\Renderer\WebViewRenderer;

return [
    WebViewRenderer::class => [
        '__construct()' => [
            'injections' => [
                CsrfViewInjection::class,
                SeoInjection::class,
            ],
        ],
    ],
];

use Psr\EventDispatcher\EventDispatcherInterface;
use Rasuvaeff\Yii3Seo\Metadata;
use Rasuvaeff\Yii3Seo\OgImage;
use Rasuvaeff\Yii3Seo\OpenGraph;
use Rasuvaeff\Yii3Seo\SeoMetadataEvent;

final readonly class ProductAction
{
    public function __construct(
        private EventDispatcherInterface $eventDispatcher,
        private ProductResponder $responder,
    ) {}

    public function __invoke(): ResponseInterface
    {
        $this->eventDispatcher->dispatch(new SeoMetadataEvent(
            metadata: new Metadata(
                title: 'Awesome Product',                 // -> "Awesome Product | My Store"
                description: 'Buy the awesome product.',
                openGraph: new OpenGraph(
                    type: 'product',
                    images: [new OgImage(url: '/og/awesome.jpg', width: 1200, height: 630, alt: 'Awesome')],
                ),
            ),
        ));

        return $this->responder->render('product/view');
    }
}

<!-- layout.php -->
 use Yiisoft\Html\Html; 

use Rasuvaeff\Yii3Seo\MetadataResolver;

$resolved = (new MetadataResolver())->resolve(
    metadata: new Metadata(title: 'Product', description: 'Description'),
    defaults: $defaults,
);

$resolved->getTitle();       // "Product | My Store"
$resolved->getOpenGraph();   // merged OpenGraph with title/description fallback
$resolved->getTwitter();     // merged Twitter card with OpenGraph fallback

$resolved->toArray();
// [
//     'metadataBase' => 'https://example.com',
//     'title' => 'Product | My Store',
//     'description' => 'Description',
//     'openGraph' => [
//         'title' => 'Product | My Store',
//         'type' => 'website',
//         'images' => [['url' => 'https://example.com/og.jpg', 'width' => 1200]],
//     ],
//     'twitter' => ['card' => 'summary_large_image', ...],
// ]

use Rasuvaeff\Yii3Seo\MetadataValidator;

$result = (new MetadataValidator())->validate($seo->getResolvedMetadata());

$result->isValid();      // true when there are no errors (warnings are advisory)
$result->hasErrors();
$result->getErrors();    // list<MetadataIssue>
$result->getWarnings();  // list<MetadataIssue>

foreach ($result->getIssues() as $issue) {
    echo $issue->getSeverity()->value, ' ', $issue->getCode(), ': ', $issue->getMessage(), "\n";
}
// error title.missing: Page title is empty
// warning canonical.missing: Canonical URL is not set

new Alternates(
    canonical: '/page',
    languages: ['en' => '/en', 'en-US' => '/us', 'x-default' => '/'],
)

// config/common/params.php
use Rasuvaeff\Yii3Seo\MetadataDefaults;
use Rasuvaeff\Yii3Seo\SelfCanonical;

new MetadataDefaults(
    metadataBase: 'https://example.com',
    selfCanonical: SelfCanonical::enabled(),                 // drop every query parameter
    // selfCanonical: SelfCanonical::keepingQuery('page'),   // keep an explicit allow-list
);

// config/common/params.php — application middleware stack
use Rasuvaeff\Yii3Seo\SelfCanonicalMiddleware;

'middlewares' => [
    SelfCanonicalMiddleware::class,
    // ... router and the rest of the stack
],

new OpenGraph(
    title: null,            // falls back to Metadata title
    description: null,      // falls back to Metadata description
    type: null,             // inherits defaults; renders og:type "website" if unset everywhere
    url: '/page',           // resolved against metadataBase
    siteName: 'My Site',
    locale: 'en_US',
    images: [new OgImage(url: '/og.jpg', width: 1200, height: 630, alt: 'Alt', type: 'image/jpeg')],
)

new TwitterCard(
    card: null,                     // summary | summary_large_image | app | player; inherits defaults, renders "summary_large_image" if unset everywhere
    site: '@site',
    creator: '@creator',
    title: null,                    // falls back to OpenGraph/title
    description: null,              // falls back to OpenGraph/description
    images: [],                     // falls back to OpenGraph images
)

new Icons(icon: '/favicon.ico', shortcut: '/favicon.ico', apple: '/apple.png', other: [
    new Icon(rel: 'mask-icon', url: '/safari.svg'),
]);

new Verification(google: 'g-token', yandex: 'y-token', bing: 'b-token', other: ['me' => 'token']);

new Author(name: 'Alice', url: 'https://example.com/alice');

JsonLd::fromArray(['@context' => 'https://schema.org', '@type' => 'WebPage', 'name' => 'Home'])

final class ProductSitemapProvider implements SitemapProviderInterface
{
    public function __construct(private ProductRepository $products) {}

    public function getUrls(): iterable
    {
        foreach ($this->products->each() as $product) {
            yield new SitemapUrl(
                loc: "/products/{$product->id}",
                lastModified: $product->updatedAt,
                priority: 0.8,
            );
        }
    }
}

$sitemap = new Sitemap($provider->getUrls(), 'https://example.com');

foreach ($sitemap->toChunks() as $chunk) {
    echo $chunk;
}

$exporter = new SitemapFileExporter(
    metadataBase: 'https://example.com',
    limits: new SitemapLimits(),   // defaults to the protocol maximums
    publicPath: '/',               // URL path the files are served under
);

$files = $exporter->export($provider->getUrls(), '/var/www/public');

final class SitemapAction
{
    public function __construct(
        private SitemapResponseFactory $responses,
        private ProductSitemapProvider $provider,
    ) {}

    public function __invoke(): ResponseInterface
    {
        return $this->responses->create(new Sitemap($this->provider->getUrls(), 'https://example.com'));
    }
}

$robotsTxt = new RobotsTxt(
    groups: [
        new RobotsTxtGroup(
            userAgents: ['*'],
            allow: ['/admin/public/'],
            disallow: ['/admin/', '/cart/', '*.json'],
        ),
        new RobotsTxtGroup(userAgents: ['AhrefsBot'], disallow: ['/'], crawlDelay: 10),
    ],
    sitemaps: ['/sitemap.xml'],
    metadataBase: 'https://example.com',
);

echo $robotsTxt->toString();

Route::get('/robots.txt')->action(RobotsTxtAction::class);

'rasuvaeff/yii3-seo' => [
    'robotsTxt' => [
        'indexable' => $_ENV['APP_ENV'] === 'prod',   // the application decides
        'robots' => new RobotsTxt(...),               // optional; omit for "allow everything"
    ],
],

foreach (Robots::noindex()->withGoogleBot('noindex', 'noimageindex')->toHeaderValues() as $value) {
    $response = $response->withAddedHeader('X-Robots-Tag', $value);
}