SEO Meta tags with Symfony — An easy implementation — [Full CODE sample]

Alberto Robles
5 min readJan 16, 2024
This post by Dall-E

Hey there! I’ve been playing around with something cool in PHP and Symfony, and I just had to share it with you. You know how SEO can be a bit of a headache, right? Well, I’ve crafted a nifty PHP class that might just make our lives a tad easier. Grab a cup of coffee, and let me walk you through this.

What’s Cooking in the PHP Kitchen? So, I’ve been playing with this idea of a custom SEO class in PHP. It’s like having a Swiss Army knife for managing all those pesky SEO bits — titles, descriptions, Open Graph tags — you name it. It’s all about making each page on our site not just visible but irresistible to those search engines.

The Cool Bits of My SEO Class:

Say Goodbye to Boring Metadata: I’ve set up this class to handle titles and descriptions dynamically. It’s like tailoring a suit — each page gets its own bespoke metadata outfit.

Open Graph Tags — Because Social Media Matters: Okay, so here’s where it gets exciting. The class includes OG tags, meaning when you share a URL on Facebook or Twitter, it looks snazzy and professional. We’re talking about controlling how our content looks when it’s out in the wild.

Symfony’s SluggerInterface for the Win: You know how important SEO-friendly URLs are, right? Symfony’s SluggerInterface is our secret weapon here. It turns our titles into neat, clean URLs that search engines love.

Real-World Stuff: I’ve set up methods like home(), blog(), and blogItem($blog) – each tuning the SEO vibe depending on what the page is about. The coolest part? In blogItem(), we’re dynamically crafting URLs that are not just unique but also SEO-friendly. It's pretty slick!

The Code in Action:

Now, let’s look at the code that makes this all happen. Here’s a snippet from the SEO class we’ve been discussing:

<?php

namespace App\Service;


use Symfony\Component\String\Slugger\SluggerInterface;

class SEO
{
private $title;
private $description;
private $canonical;
private $ogLocale;
private $ogType;
private $ogTitle;
private $ogDescription;
private $ogUrl;
private $ogSiteName;
private $ogImageSecureUrl;
private $ogImageWidth;
private $ogImageHeight;
private $slugger;


public function __construct(SluggerInterface $slugger)
{

$this->ogLocale = 'en_US';
$this->ogType = 'website';
$this->ogSiteName = 'yourname';
$this->ogImageSecureUrl = 'https://www.yourdomain.com/theme/assets/img/seo.png';
$this->ogImageWidth = '1280';
$this->ogImageHeight = '521';
$this->slugger = $slugger;


}


public function home(){

$this->title = 'Seo title here!';
$this->description = 'Seo description here!';
$this->canonical = 'https://www.yourdomain.com';

$this->ogTitle = $this->title;
$this->ogDescription = $this->description;
$this->ogUrl = $this->canonical;

return $this;

}


public function blog(){


$this->title = 'Seo title here!';
$this->description = 'Seo description here!';
$this->canonical = 'https://www.yourdomain.com/blog';

$this->ogTitle = $this->title;
$this->ogDescription = $this->description;
$this->ogUrl = $this->canonical;

return $this;

}

public function blogItem($blog){

$images = $blog->getImagesGallery();

$this->title = $blog->getSeoTitle();
$this->description = $blog->getSeoDescription();
$this->canonical = 'https://www.yourdomain.com/blog/'.$blog->getId().'/'.$this->slugger->slug($blog->getUrl())->lower();
$this->ogImageSecureUrl = "https://www.yourdomain.com".$images[0];
$this->ogTitle = $this->title;
$this->ogDescription = $this->description;
$this->ogUrl = $this->canonical;

return $this;

}



/**
* Get the value of title
*/
public function getTitle()
{
return $this->title;
}

/**
* Set the value of title
*
* @return self
*/
public function setTitle($title)
{
$this->title = $title;

return $this;
}

/**
* Get the value of description
*/
public function getDescription()
{
return $this->description;
}

/**
* Set the value of description
*
* @return self
*/
public function setDescription($description)
{
$this->description = $description;

return $this;
}

/**
* Get the value of ogLocale
*/
public function getOgLocale()
{
return $this->ogLocale;
}

/**
* Set the value of ogLocale
*
* @return self
*/
public function setOgLocale($ogLocale)
{
$this->ogLocale = $ogLocale;

return $this;
}

/**
* Get the value of ogType
*/
public function getOgType()
{
return $this->ogType;
}

/**
* Set the value of ogType
*
* @return self
*/
public function setOgType($ogType)
{
$this->ogType = $ogType;

return $this;
}

/**
* Get the value of ogTitle
*/
public function getOgTitle()
{
return $this->ogTitle;
}

/**
* Set the value of ogTitle
*
* @return self
*/
public function setOgTitle($ogTitle)
{
$this->ogTitle = $ogTitle;

return $this;
}

/**
* Get the value of ogDescription
*/
public function getOgDescription()
{
return $this->ogDescription;
}

/**
* Set the value of ogDescription
*
* @return self
*/
public function setOgDescription($ogDescription)
{
$this->ogDescription = $ogDescription;

return $this;
}

/**
* Get the value of ogUrl
*/
public function getOgUrl()
{
return $this->ogUrl;
}

/**
* Set the value of ogUrl
*
* @return self
*/
public function setOgUrl($ogUrl)
{
$this->ogUrl = $ogUrl;

return $this;
}

/**
* Get the value of ogSiteName
*/
public function getOgSiteName()
{
return $this->ogSiteName;
}

/**
* Set the value of ogSiteName
*
* @return self
*/
public function setOgSiteName($ogSiteName)
{
$this->ogSiteName = $ogSiteName;

return $this;
}

/**
* Get the value of ogImageSecureUrl
*/
public function getOgImageSecureUrl()
{
return $this->ogImageSecureUrl;
}

/**
* Set the value of ogImageSecureUrl
*
* @return self
*/
public function setOgImageSecureUrl($ogImageSecureUrl)
{
$this->ogImageSecureUrl = $ogImageSecureUrl;

return $this;
}

/**
* Get the value of ogImageWidth
*/
public function getOgImageWidth()
{
return $this->ogImageWidth;
}

/**
* Set the value of ogImageWidth
*
* @return self
*/
public function setOgImageWidth($ogImageWidth)
{
$this->ogImageWidth = $ogImageWidth;

return $this;
}

/**
* Get the value of ogImageHeight
*/
public function getOgImageHeight()
{
return $this->ogImageHeight;
}

/**
* Set the value of ogImageHeight
*
* @return self
*/
public function setOgImageHeight($ogImageHeight)
{
$this->ogImageHeight = $ogImageHeight;

return $this;
}

/**
* Get the value of canonical
*/
public function getCanonical()
{
return $this->canonical;
}

/**
* Set the value of canonical
*
* @return self
*/
public function setCanonical($canonical)
{
$this->canonical = $canonical;

return $this;
}
}
<title>{{seo.title}}</title>
<meta name="description" content="{{seo.description}}"/>
<link rel="canonical" href="{{seo.canonical}}" />
<meta property="og:locale" content="{{seo.ogLocale}}" />
<meta property="og:type" content="{{seo.ogType}}" />
<meta property="og:title" content="{{seo.ogTitle}}" />
<meta property="og:description" content="{{seo.ogDescription}}" />
<meta property="og:url" content="{{seo.ogUrl}}" />
<meta property="og:site_name" content="{{seo.ogSiteName}}" />
<meta property="og:image:secure_url" content="{{seo.ogImageSecureUrl}}" />
<meta property="og:image:width" content="{{seo.ogImageWidth}}" />
<meta property="og:image:height" content="{{seo.ogImageHeight}}" />t
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\Persistence\ManagerRegistry;
use App\Repository\PostRepository;
use App\Service\SEO;
use App\Entity\Post;


class AppController extends AbstractController
{

#[Route('/', name: 'app_start')]
public function index(): Response
{

return $this->render('app/index.html.twig', [
'seo' => $seo->home(),

]);
}


#[Route('/blog', name: 'app_blog', methods: ['GET'])]
public function blog(Request $request,SEO $seo,): Response
{



return $this->render('app/blog.html.twig',[

'seo' => $seo->blog(),


]);

}

#[Route('/blog/{id}/{name}', name: 'app_blog_item', methods: ['GET'])]
public function blogItem(Request $request, SEO $seo, Post $post): Response
{


return $this->render('app/blog-item.html.twig',[

'seo' => $seo->blogItem($post),
'post' => $post
]);

}




}

Over to You, Buddies: Now that you’ve seen a bit of the code, why not try integrating something similar into your projects? I’m sure you can tweak and improve upon it. And remember, I’m super curious about your SEO strategies and tools.

Before you go, a quick question. Do any of you have a go-to class or method for handling SEO tags effectively?

I’m always on the lookout to learn more and improve my toolbox. If you’ve got something that’s worked like a charm for you, do share! It’s all about learning from each other in this awesome dev community.

Drop your thoughts or links in the comments — can’t wait to check out your recommendations!

--

--