butschster/meta-tags

管理 Laravel 项目中 SEO 元标签的最强大和可扩展的工具

v3.1.1 2024-06-28 18:44 UTC

README

meta-tags

管理 Laravel 项目中 SEO 元标签的最强大和可扩展的工具

Laravel SEO Meta Tags 为 Laravel 应用程序提供了一种复杂的解决方案,允许开发人员无缝管理标题、CSS、JavaScript 和其他相关标签。其主要目标是简化在应用程序中管理搜索引擎优化(SEO)标签的过程。

此外,其通用的 API 使其与 Inertiajs、VueJS 等其他 JavaScript 框架兼容。

如果您有任何问题或需要进一步的帮助,请加入我们官方的 telegram 群组

贡献

我们热情地邀请您为该包做出贡献!无论您是否发现了错误、有创新功能建议,还是希望以其他方式做出贡献,我们都热烈欢迎您的参与。只需在我们的 GitHub 仓库中打开一个问题或提交一个拉取请求即可开始。

请记住,每一位伟大的开发者都是从新手开始的。为开源项目做出贡献是您成为更优秀开发者的旅程中的一步。因此,不要犹豫,加入我们开始贡献吧!

我们感激任何有助于使该包变得更好的贡献!

Support me on Patreon

Build Status Latest Stable Version Total Downloads License

使用 Buggregator 提升您的开发体验

搭配我们的工具以获得更强大的开发环境。更多信息请访问 buggregator.dev

功能

  • 元管理:轻松设置标题、字符集、分页链接等。
  • 样式与脚本:在 HTML 中的任何位置组织并放置样式和脚本。
  • 自定义标签:创建满足特定需求的标签。
  • 富媒体集成:支持 Open Graph 和 Twitter Cards。
  • 分析准备:提供 Google Analytics 和 Yandex Metrika 跟踪代码支持,包括后者的代码生成器。
  • 网站验证:支持网站管理工具网站验证标签。
  • 包系统:将标签、样式和脚本分组到命名包中,以便在任何地方轻松包含。
  • 健壮的文档:提供清晰的指导和说明,确保无障碍的设置。
  • 彻底测试:构建确保可靠性和稳定性。

要求

  • Laravel版本:9.x到10.x
  • PHP版本:8.0或更高

安装和配置

  1. 安装包:使用以下命令将Meta Tags包安装到您出色的应用程序中。
composer require butschster/meta-tags
  1. 注册服务提供商:安装包后,您必须注册其服务提供商。

您可以使用以下Artisan命令来完成此操作

php artisan meta-tags:install

此命令将激活App\Providers\MetaTagsServiceProvider并在config/meta_tags.php中发布配置。在此配置文件中,您可以设置默认标题、关键词、描述和其他元标签,这些标签将自动插入到您的HTML中。

  1. 验证:确保在您的config/app.php配置文件中的提供者数组中添加了App\Providers\MetaTagsServiceProvider。如果没有,您需要手动添加。请记住,如果您的应用程序不使用App命名空间,请相应地更新提供者类名。

就是这样!您的Laravel项目现在可以轻松处理SEO元标签。

用法

控制器

您可以在控制器中使用Facade \Butschster\Head\Facades\Meta\Butschster\Head\Contracts\MetaTags\MetaInterface

use Butschster\Head\MetaTags\MetaInterface;

class HomeController extends Controller
{
    public function __contruct(
        protected MetaInterface $meta
    ) {
    }
    
    public function index()
    {
        $news = News::paginate();
        
        // Prepend title part to the default title
        $this->meta
        
            // Will render "Home page - Default Title"
           ->prependTitle('Home page')
           
           // Will include next, prev, canonical links
           ->setPaginationLinks($news)
           
           // Will change default favicon
           ->setFavicon('/favicon-index.ico')
    }
}

// Or you can use the facade

use Butschster\Head\Facades\Meta;

class HomeController extends Controller 
{
    public function index()
    {
        $news = News::paginate();
        
        Meta::prependTitle('Home page')
            ->setPaginationLinks($news)
            ->setFavicon('favicon-index.ico');
    }
}

视图

要将元标签集成到HTML中,只需在需要的位置插入{!! Meta::toHtml() !!}

注意 您有两种插入元标签的方法:{!! Meta::toHtml() !!}或Blade指令@meta_tags

以下是在视图中使用它的示例

<!DOCTYPE html>
<html lang="en">
<head>
    {!! Meta::toHtml() !!}
</head>
...
</html>

位置

该包提供了将元标签插入到标题之外的灵活性。您可以在模板中定义特定的位置。

  • 要将元标签放在页脚,请使用:Meta::footer()->toHtml()
  • 对于自定义位置,请使用:Meta::placement('placement_name')->toHtml()
  • 或者,您也可以使用Blade指令:@meta_tags('placement_name')
<body>
...
{!! Meta::placement('middle_of_the_page')->toHtml() !!}
...
{!! Meta::footer()->toHtml() !!}
</body>

为了避免代码重复并提高代码组织性,您可以将标签、资产等分组到命名包中。这允许在需要的位置轻松包含元标签或资产的集合。

要创建新的包

  • 导航到服务提供商。
  • \App\Providers\MetaTagsServiceProvider中添加您的包。

要定义包,您可以使用PackageManager::create方法

namespace App\Providers;

use Butschster\Head\Facades\PackageManager;
use Butschster\Head\Packages\Package;
use Illuminate\Support\ServiceProvider;

class MetaTagsServiceProvider extends ServiceProvider 
{
    ...
    protected function packages()
    {
       PackageManager::create('jquery', function(Package $package) {
          $package->addScript(
             'jquery.js', 
             'https://code.jqueryjs.cn/jquery-3.3.1.min.js', 
             ['defer']
          );
       });
       
       PackageManager::create('calendar', function(Package $package) {
          $package->requires('jquery');
          $package->addScript(
             'fullcalendar.js', 
             'https://cdn.jsdelivr.net.cn/npm/@fullcalendar/core@4.0.1/main.min.js', 
             ['defer']
          )->addScript(
             'fullcalendar.locales.js', 
             'https://cdn.jsdelivr.net.cn/npm/@fullcalendar/core@4.0.1/locales-all.min.js', 
             ['defer']
          )->addStyle(
             'fullcalendar.css', 
             'https://cdn.jsdelivr.net.cn/npm/@fullcalendar/core@4.0.1/main.min.css'
          );
       });
    }

    ...
}

在控制器中使用包

当控制器需要特定的包时,您可以通过引用包名来包含它们

use Butschster\Head\Facades\Meta;

class EventsController extends Controller {

    public function show(Event $event)
    {
        // Will include all tags from calendar package
        Meta::includePackages(['calendar', ...]);
    }
}

设置全局包

对于应在每个页面上包含的包,您可以在config/meta_tags.php中定义它们

...
'packages' => [
    'jquery', 'calendar', ...
],
...

这样您就完成了!通过这些步骤,处理和组织元标签和资产变得轻而易举。

注意 Meta类中所有可用的方法也可以与这些包函数一起使用。

API

元标签

\Butschster\Head\MetaTags\Meta

  • 此类实现了Illuminate\Contracts\Support\Htmlable接口

方法

设置元标题的主要部分

Meta::setTitle('Laravel');
// <title>Laravel</title>

// You can specify max length. (By default it gets from config.)
Meta::setTitle('Laravel', 4);
// <title>Lara...</title>

将标题部分添加到主标题之前

Meta::setTitle('Laravel')
    ->prependTitle('Home page');
// <title>Home page - Laravel</title>

设置标题分隔符

默认情况下,它从配置中获取

Meta::setTitleSeparator('->')
    ->setTitle('Laravel')
    ->prependTitle('Home page');
// <title>Home page -> Laravel</title>

设置描述

Meta::setDescription('Awesome page');
// <meta name="description" content="Awesome page">

// You can specify max length. (By default it gets from config.)
Meta::setDescription('Awesome page', 7);
// <meta name="description" content="Awesome...">

设置关键词

Meta::setKeywords('Awesome keywords');
// <meta name="keywords" content="Awesome keywords">


Meta::setKeywords(['Awesome keyword', 'keyword2']);
// <meta name="keywords" content="Awesome keyword, keyword2">

// You can specify max length. (By default it gets from config.)
Meta::setKeywords(['keyword', 'keyword2'], 10);
// <meta name="keywords" content="keyword, key...">

设置robots

Meta::setRobots('nofollow,noindex');
// <meta name="robots" content="nofollow,noindex">

设置内容类型

Meta::setContentType('text/html');
// <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

Meta::setContentType('text/html', 'ISO-8859-1');
// <meta http-equiv="Content-Type" content="text/html; ISO-8859-1">

设置视口

Meta::setViewport('width=device-width, initial-scale=1');
// <meta name="viewport" content="width=device-width, initial-scale=1">

添加网站管理员标签 您可以添加多个标签

use Butschster\Head\MetaTags\Entities\Webmaster;

// Supported services [google, yandex, pinterest, alexa, bing]
Meta::addWebmaster(Webmaster::GOOGLE, 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="google-site-verification" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('yandex', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="yandex-verification" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('bing', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="msvalidate.01" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster('alexa', 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="alexaVerifyID" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

Meta::addWebmaster(Webmaster::PINTEREST, 'f+e-Ww4=[Pp4wyEPLdVx4LxTsQ');
// <meta name="p:domain_verify" content="f+e-Ww4=[Pp4wyEPLdVx4LxTsQ">

设置prev href

Meta::setPrevHref('http://site.com/prev');
// <link rel="prev" href="http://site.com/prev" />

设置next href

Meta::setNextHref('http://site.com/next');
// <link rel="next" href="http://site.com/next" />

设置canonical链接

Meta::setCanonical('http://site.com');
// <link rel="canonical" href="http://site.com" />

从分页对象中设置canonical链接、prev和next

$news = \App\News::paginate();

Meta::setPaginationLinks($news);

// <link rel="prev" href="http://site.com/prev" />
// <link rel="next" href="http://site.com/next" />
// <link rel="canonical" href="http://site.com" />

添加hreflang链接

Meta::setHrefLang('en', http://site.com/en');
Meta::setHrefLang('ru', http://site.com/ru');

// <link rel="alternate" hreflang="en" href="http://site.com/en" />
// <link rel="alternate" hreflang="ru" href="http://site.com/ru" />

设置HTML文档的字符编码

Meta::setCharset();
// <meta charset="utf-8">

Meta::setCharset('ISO-8859-1');
// <meta charset="ISO-8859-1">

设置favicon

Meta::setFavicon('http://site.com/favicon.ico');
// <link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />

Meta::setFavicon('http://site.com/favicon.png');
// <link rel="icon" type="image/png" href="http://site.com/favicon.png" />

Meta::setFavicon('http://site.com/favicon.gif');
// <link rel="icon" type="image/gif" href="http://site.com/favicon.gif" />

Meta::setFavicon('http://site.com/favicon.svg');
// <link rel="icon" type="image/svg+xml" href="http://site.com/favicon.svg" />

//You can set additional attributes
Meta::setFavicon('http://site.com/favicon.svg', ['sizes' => '16x16', 'type' => 'custom_type']);
// <link rel="icon" type="custom_type" href="http://site.com/favicon.svg" sizes="16x16" />

添加自定义链接标签

Meta::addLink('apple-touch-icon-precomposed', [
    'href' => 'http://site.com',
    'id' => 'id:213'
]);
// <link rel="apple-touch-icon-precomposed" href="http://site.com" id="id:213" />

添加到CSS文件的链接

Meta::addStyle('style.css', 'http://site.com/style.css');
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />


// You can override or add attributes
Meta::addStyle('style.css', 'http://site.com/style.css', [
    'media' => 'custom', 'defer', 'async'
]);

// <link media="custom" type="text/css" rel="stylesheet" href="http://site.com/style.css" defer async />

添加到JavaScript文件的链接

Meta::addScript('script.js', 'http://site.com/script.js');
// <script src="http://site.com/script.js"></script>

// You can override or add attributes
Meta::addScript('script.js', 'http://site.com/script.js', ['async', 'defer', 'id' => 'hj2b3424iu2-dfsfsd']);
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

// You can specify placement. By default, for scripts it's footer
Meta::addScript('script.js', 'http://site.com/script.js', [], 'custom_placement');
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

注册自定义标签 我们的工具包提供了多种扩展方式。其中之一是创建新的标签。您能够创建一个新的类,并将其与朋友或Laravel社区分享。如果您认为您创建的标签非常有用,也可以创建一个新的pull request。

class FacebookPixelTag implements \Butschster\Head\Contracts\MetaTags\Entities\TagInterface {

    private $pixel_id;

    public function __construct(string $id)
    {
        $this->pixel_id = $id
    }
   
    public function getPlacement(): string
    {
        return 'footer'
    }

    public function toArray()
    {
        return [
            'type' => 'facebook_pixel_tag',
            'pixel_id' => $this->pixel_id
        ];
    }
    
    public function toHtml()
    {
        return '<script type="text/javascript">...</script>'
    }
}

Meta::addTag('facebook.pixel', new FacebookPixelTag('42b3h23-34234'));
// <script type="text/javascript">...</script>

从TagsCollection注册标签

$tags = new \Butschster\Head\MetaTags\TagsCollection([
    ...
]);
Meta::registerTags($tags);

// You can specify the placement 
Meta::registerTags($tags, 'footer');

通过名称获取标签

Meta::getTag('author');

通过名称删除标签

Meta::removeTag('author');

添加元标签

Meta::addMeta('author', [
    'content' => 'butschster',
]);
// <meta name="author" content="butschster">

添加CSRF-token标签

Meta::addCsrfToken();
// <meta name="csrf-token" content="....">

删除所有标签

Meta::reset();

包含所需包

Meta::includePackages('jquery', 'vuejs');
Meta::includePackages(['jquery', 'vuejs']);

Will load registered packages with names jquery and vuejs and append tags from there to Meta

注册新包并注册该包中的所有标签

Meta::setTitle('Current title');

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('New title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);

替换同名包 当您用新包替换旧包时,旧标签将被删除

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

$newPackage = new \Butschster\Head\Packages\Package('custom_package');
$newPackage->setTitle('New title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);
Meta::replacePackage($newPackage);

通过名称删除包

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);
Meta::removePackage('custom_package');

通过名称获取包

$package = new \Butschster\Head\Packages\Package('custom_package');
$package->setTitle('Custom title');

// Will replace "Current title" to "New title" after package registration
Meta::registerPackage($package);

$package = Meta::getPackage('custom_package');

使用元接口

一个包有多个接口,可以帮助您从对象中设置元标签

SEO标签

namespace App;
use Butschster\Head\Contracts\MetaTags\SeoMetaTagsInterface;
use Butschster\Head\Contracts\MetaTags\RobotsTagsInterface;

class Page extends Model implements SeoMetaTagsInterface, RobotsTagsInterface {

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function getKeywords()
    {
        return $this->keywords;
    }

    public function getRobots(): ?string
    {
        return 'noindex, nofollow';
    }
}

// Controller
use Butschster\Head\Facades\Meta;

class PageController extends Controller {

    public function show(\App\Page $page)
    {
        Meta::setMetaFrom($page);
    }
}

元扩展

元对象包含Macroable特性,您可以扩展它!

例如

//Service Provider
Meta::macro('registerSeoMetaTagsForPage', function (\App\Page $page) {
    $this
        ->prependTitle($page->title)
        ->setKeywords($page->meta_keywords)
        ->setDescription($page->meta_description);
 
});

// Controller
use Butschster\Head\Facades\Meta;

class PageController extends Controller {

    public function show(\App\Page $page)
    {
        Meta::registerSeoMetaTagsForPage($page);
    }
}

关于Macroable特性的更多信息 https://unnikked.ga/understanding-the-laravel-macroable-trait-dab051f09172

元标签位置

默认情况下,标签放置在head位置。您可以指定自己的位置并使用所有可用方法。

Meta::placement('twitter.meta')
    ->addMeta('twitter:card', [
        'content' => 'summary_large_image',
    ])
    ->includePackages('twitter')

// There is the method for footer placement
Meta::footer()->...
    
// View
<body>
    ...
    @meta_tags('twitter.meta')
    ...
    
    @meta_tags('footer')
</body>

包对象具有与元对象相同的方法。您可以使用它进行扩展和创建自定义标签集。

\Butschster\Head\Packages\Package

  • 此类扩展了Butschster\Head\MetaTags\Meta
  • 此类实现了Illuminate\Contracts\Support\Htmlable接口

创建新包并在PackageManager中注册

$package = new \Butschster\Head\Packages\Package('jquery');
PackageManager::register($package);

// or
PackageManager::create('jquery', function($package) {
    ...
});

获取包名称

$package = new \Butschster\Head\Packages\Package('jquery');

$package->getName(); // jquery

添加到CSS文件的链接

$package = new \Butschster\Head\Packages\Package('jquery');

$package->addStyle('style.css', 'http://site.com/style.css');
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />


// You can change or add attributes
$package->addStyle('style.css', 'http://site.com/style.css', [
    'media' => 'custom', 'defer', 'async'
]);

// <link media="custom" type="text/css" rel="stylesheet" href="http://site.com/style.css" defer async />

添加到JavaScript文件的链接

$package = new \Butschster\Head\Packages\Package('jquery');

$package->addScript('script.js', 'http://site.com/script.js');
// <script src="http://site.com/script.js"></script>

// You can change or add attributes
$package->addScript('script.js', 'http://site.com/script.js', ['async', 'defer', 'id' => 'hj2b3424iu2-dfsfsd']);
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

// You can placement. By default it's footer
$package->addScript('script.js', 'http://site.com/script.js', [], 'custom_placement');
// <script src="http://site.com/script.js" async defer id="hj2b3424iu2-dfsfsd"></script>

Meta::includePackages('jquery')->placement('custom_placement')->toHtml();

可用包

OpenGraphPackage

Butschster\Head\Packages\Entities\OpenGraphPackage

您可以使用此包来管理OpenGraph元标签

$og = new Butschster\Head\Packages\Entities\OpenGraphPackage('some_name');

$og->setType('website')
   ->setSiteName('My awesome site')
   ->setTitle('Post title');
   
// You can render itself

$og->toHtml();
// <meta name="og:type" content="website">
// <meta name="og:site_name" content="My awesome site">
// <meta name="og:title" content="Post title">

// Or just register this package in Meta class and it will be rendered automatically
Meta::registerPackage($og);

setType 设置对象的类型,例如,"video.movie"。

$og->setType('website');
// <meta name="og:type" content="website">

setTitle 设置对象在图中应显示的标题,例如,"The Rock"。

$og->setTitle('Post title');
// <meta name="og:title" content="Post title">

setDescription 设置描述

$og->setDescription('View the album on Flickr.');
// <meta name="og:description" content="View the album on Flickr.">

setSiteName 设置站点名称

$og->setSiteName('My awesome site');
// <meta name="og:site_name" content="My awesome site">

setUrl 设置对象的规范URL,它将在图中用作其永久ID。

$og->setUrl('https://site.com');
// <meta name="og:url" content="https://site.com">

setLocale 设置标记这些标签的语言环境。格式为language_TERRITORY

$og->setLocale('en_US');
// <meta name="og:locale" content="en_US">

addAlternateLocale

$og->addAlternateLocale('en_US', 'ru_RU');
// <meta name="og:locale:alternate" content="en_US">
// <meta name="og:locale:alternate" content="ru_RU">

addImage 添加代表图中对象的图片URL。

$og->addImage('http://site.com');
// <meta name="og:image" content="http://site.com">

// You can pass properties
$og->addImage('http://site.com', [
    'secure_url' => 'https://site.com',
    'type' => 'image/png'
]);

// <meta name="og:image" content="http://site.com">
// <meta name="og:image:secure_url" content="https://site.com">
// <meta name="og:image:type" content="image/png">

addVideo 添加代表图中对象的视频URL。

$og->addVideo('http://site.com');
// <meta name="og:video" content="http://site.com">

// You can pass properties
$og->addVideo('http://site.com', [
    'secure_url' => 'https://site.com',
    'type' => 'application/x-shockwave-flash'
]);

// <meta name="og:video" content="http://site.com">
// <meta name="og:video:secure_url" content="https://site.com">
// <meta name="og:video:type" content="application/x-shockwave-flash">

TwitterCardPackage

Butschster\Head\Packages\Entities\TwitterCardPackage

您可以使用此包来管理Twitter卡片元标签

$card = new Butschster\Head\Packages\Entities\TwitterCardPackage('some_name');

$card->setType('summary')
   ->setSite('@username')
   ->setTitle('Post title');
   
// You can render itself

$card->toHtml();
// <meta name="twitter:card" content="summary">
// <meta name="twitter:site" content="@username">
// <meta name="twitter:title" content="Post title">

// Or just register this package in Meta class and it will be rendered automatically
Meta::registerPackage($card);

setType 设置卡片的类型:summarysummary_large_imageplayerapp

$card->setType('summary');
// <meta name="twitter:card" content="summary">

setSite 设置卡片页脚中使用的@username。

$card->setSite('@username');
// <meta name="twitter:site" content="@username">

setCreator 设置内容创建者/作者的@username。

$card->setCreator('@username');
// <meta name="twitter:creator" content="@username">

setTitle 设置标题

$card->setTitle('Post title');
// <meta name="twitter:title" content="Post title">

setDescription 设置描述

$card->setDescription('View the album on Flickr.');
// <meta name="twitter:title" content="View the album on Flickr.">

setImage 设置类型为summarysummary_large_image的卡片图片

$card->setImage('https://site.com');
// <meta name="twitter:image" content="https://site.com">

setVideo 设置类型为player的卡片视频

$card->setVideo('https://site.com/video.mp4', ['width' => 1920, 'height' => 1280]);
// <meta name="twitter:player" content="https://site.com/video.mp4">
// <meta name="twitter:player:width" content="1920">
// <meta name="twitter:player:height" content="1280">

addMeta 设置自定义元标签

$card->addMeta('image:alt', 'Picture of Pavel Buchnev');
// <meta name="twitter:image:alt" content="Picture of Pavel Buchnev">

PackageManager API

包管理器提供存储您的包或预设的仓库。您可以按名称获取它们。

创建新包

PackageManager::create('jquery', function($package) {
    ...
});

注册新包

$package = new \Butschster\Head\Packages\Package('jquery');

PackageManager::register($package);

获取所有已注册的包

PackageManager::getPackages(): array;

按名称获取已注册的包

PackageManager::create('jquery', function($package) {
    ...
});

PackageManager::getPackage('jquery'); 
// Will return the registered pacakge or null;

依赖项

一个包可以有依赖项。

PackageManager::create('jquery', function($package) {
    $package->addScript('jquery.js', 'http://site.com/jquery.min.js');
});

PackageManager::create('bootstrap4', function($package) {
    $package->requires('jquery');
    $package->addScript('bootstrap4.js', 'http://site.com/bootstrap4.min.js');
    $package->addStyle('bootstrap4.css', 'http://site.com/bootstrap4.min.css');
});

Meta::includePackages('bootstrap4'); 
// Will load jquery package also
// Head
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/bootstrap4.min.css" />

// Footer
// <script src="http://site.com/jquery.min.js"></script>
// <script src="http://site.com/bootstrap4.min.js"></script>

辅助类

标签

\Butschster\Head\MetaTags\Entities\Tag

创建一个新的标签

$tag = new \Butschster\Head\MetaTags\Entities\Tag('meta', [
    'name' => 'author',
    'content' => 'butschster'
]);
// or
$tag = \Butschster\Head\MetaTags\Entities\Tag::meta([
    'name' => 'author',
    'content' => 'butschster'
]);
$tag->toHtml();
// <meta name="author" content="butschster">

// Closed tag
$tag = new \Butschster\Head\MetaTags\Entities\Tag('link', [
    'rel' => 'favicon',
    'href' => 'http://site.com'
], true);
// or
$tag = \Butschster\Head\MetaTags\Entities\Tag::link([
    'rel' => 'favicon',
    'href' => 'http://site.com'
]);

$tag->toHtml();
// <link rel="favicon" href="http://site.com" />

// Tag with anonymous function
$tag = new \Butschster\Head\MetaTags\Entities\Tag('meta', [
    'name' => 'csrf-token',
    'content' => function () {
        return Session::token();
    }
]);

$tag->toHtml();
// <meta name="csrf-token" content="8760b1d530d60d2cba6fe81cb12d67c0">

设置位置

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->setPlacement('footer');

获取位置

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->getPlacement() // Will return specified placement;

设置可见性条件

$tag = new \Butschster\Head\MetaTags\Entities\Tag(...);
$tag->visibleWhen(function () {
    return Request::ip() === '127.0.0.1';
});

标题

\Butschster\Head\MetaTags\Entities\Title

此类负责生成标题

设置标题默认部分

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');

$title->toHtml(); // <title>Laravel</title>

预置新的标题部分

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');
$title->prepend('Index page');

$title->toHtml(); // <title>Index page | Laravel</title>

更改默认标题部分分隔符

$title = new \Butschster\Head\MetaTags\Entities\Title();

$title->setTitle('Laravel');
$title->prepend('Index page');
$title->setSeparator('-');

$title->toHtml(); // <title>Index page - Laravel</title>

指定最大长度 (默认长度为255)

$title = new \Butschster\Head\MetaTags\Entities\Title('Lorem Ipsum is simply dummy text of the printing and typesetting');

$title->setMaxLength(20);

$title->toHtml(); // <title>Lorem Ipsum is simpl...</title>

描述

\Butschster\Head\MetaTags\Entities\Description

脚本

\Butschster\Head\MetaTags\Entities\Script

此类负责生成脚本链接

use Butschster\Head\MetaTags\Entities\Script;

$script = new Script('jquery.js', 'http://site.com/script.js', ['defer', 'async']);

$script->toHtml(); 
// <script src="http://site.com/script.js" defer async></script>

Meta::addTag($script);

样式

\Butschster\Head\MetaTags\Entities\Style

此类负责生成CSS链接

use Butschster\Head\MetaTags\Entities\Style;

$style = new Style('style.css', 'http://site.com/style.css');

$style->toHtml(); 
// <link media="all" type="text/css" rel="stylesheet" href="http://site.com/style.css" />

Meta::addTag($style);

favicon

\Butschster\Head\MetaTags\Entities\Favicon

此类负责生成favicon链接

注释

\Butschster\Head\MetaTags\Entities\Comment

此类是标签的包装器,允许向您的标签添加注释

use Butschster\Head\MetaTags\Entities\Comment;
use Butschster\Head\MetaTags\Entities\Favicon;

$favicon = new Favicon('http://site.com/favicon.ico');
$comment = new Comment($favicon, 'Favicon');

Meta::addTag('favicon', $comment);

// Will render
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />
<!-- /Favicon -->

条件注释

\Butschster\Head\MetaTags\Entities\ConditionalComment

此类是标签的包装器,允许向您的标签添加条件注释

use Butschster\Head\MetaTags\Entities\ConditionalComment;
use Butschster\Head\MetaTags\Entities\Favicon;

$favicon = new Favicon('http://site.com/favicon.ico');
$comment = new ConditionalComment($favicon, 'IE 6');

Meta::addTag('favicon', $comment);
<!--[if IE 6]>
<link rel="icon" type="image/x-icon" href="http://site.com/favicon.ico" />
<![endif]-->

Google Analytics

有头部位置!

use Butschster\Head\MetaTags\Entities\GoogleAnalytics;
$script = new GoogleAnalytics('UA-12345678-1');

Meta::addTag('google.analytics', $script);

将返回

<script>
    (function (i, s, o, g, r, a, m) {
        i['GoogleAnalyticsObject'] = r;
        i[r] = i[r] || function () {
            (i[r].q = i[r].q || []).push(arguments)
        }, i[r].l = 1 * new Date();
        a = s.createElement(o),
                m = s.getElementsByTagName(o)[0];
        a.async = 1;
        a.src = g;
        m.parentNode.insertBefore(a, m)
    })(window, document, 'script', 'https://#/analytics.js', 'ga');
    ga('create', 'UA-12345678-1', 'auto');
    ga('send', 'pageview');
</script>

Google TagManager

有头部位置!

use Butschster\Head\MetaTags\Entities\GoogleTagManager;
$script = new GoogleTagManager('UA-12345678-1');

Meta::addTag('google.tagmanager', $script);

将返回

<script async src="https://#/gtag/js?id=UA-12345678-1"></script>
<script>
    window.dataLayer = window.dataLayer || [];

    function gtag() {
        dataLayer.push(arguments);
    }

    gtag('js', new Date());

    gtag('config', 'UA-12345678-1');
</script>

Yandex Metrika

有页脚位置!

use \Butschster\Head\MetaTags\Entities\YandexMetrika;
$script = new YandexMetrika('20925319');

Meta::addTag('yandex.metrika', $script);

将返回

<script type="text/javascript">
    (function (m, e, t, r, i, k, a) {
        m[i] = m[i] || function () {
            (m[i].a = m[i].a || []).push(arguments)
        };
        m[i].l = 1 * new Date();
        k = e.createElement(t), a = e.getElementsByTagName(t)[0], k.async = 1, k.src = r, a.parentNode.insertBefore(k, a)
    })
    (window, document, "script", "https://#/metrika/tag.js", "ym");

    ym(20925319, "init", {clickmap: true, trackLinks: true, accurateTrackBounce: true, webvisor: true});
</script>
<noscript>
    <div><img src="https://#/watch/20925319" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>

更改点击地图设置

$script = new YandexMetrika('20925319');

$script->clickmap(bool);

更改webvisor设置

$script = new YandexMetrika('20925319');

$script->webvisor(bool);

更改trackLinks设置

$script = new YandexMetrika('20925319');

$script->trackLinks(bool);

更改accurateTrackBounce设置

$script = new YandexMetrika('20925319');

$script->accurateTrackBounce(bool);

更改trackHash设置

$script = new YandexMetrika('20925319');

$script->trackHash(bool);

更改eCommerce设置

$script = new YandexMetrika('20925319');

$script->eCommerce(string $containerName);

使用备用CDN

$script = new YandexMetrika('20925319');

$script->useCDN();

禁用noscript标签

$script = new YandexMetrika('20925319');

$script->disableNoScript();

Javascript变量

use \Butschster\Head\MetaTags\Entities\JavascriptVariables;

$variables = new JavascriptVariables([
    'string' => 'Hello world',
    'number' => 4815162342,
    'bool' => true,
    'nullable' => null
]);

// you can put new variable
$variables->put('array', ['jquery', 'vuejs']);

Meta::addTag('variables', $variables);

将返回

<script>
    window.array = ["jquery", "vuejs"];
    window.string = 'Hello world';
    window.number = 4815162342;
    window.bool = true;
    window.nullable = null;
</script>

您可以更改命名空间

use \Butschster\Head\MetaTags\Entities\JavascriptVariables;

$variables = new JavascriptVariables([
    'string' => 'Hello world',
    'number' => 4815162342,
], 'custom');

将返回

<script>
    window.custom = window.custom || {};
    custom.string = 'Hello world';
    custom.number = 4815162342;
</script>

用例

多个favicon

您可以使用自己的包来处理。

首先在MetaTagsServiceProvider中创建您的包 App\Providers\MetaTagsServiceProvider

namespace App\Providers;

use Butschster\Head\MetaTags\Entities\Favicon;
use Butschster\Head\MetaTags\Entities\ConditionalComment;
use Butschster\Head\Facades\PackageManager;
use Butschster\Head\Packages\Package;

class MetaTagsServiceProvider extends ServiceProvider {

    ...
    
    protected function packages()
    {
        PackageManager::create('favicons', function(Package $package) {
            $sizes = ['16x16', '32x32', '64x64'];
    
            foreach ($sizes as $size) {
                $package->addTag(
                    'favicon.'.$size, 
                    new Favicon('http://site.com/favicon-'.$size.'.png', [
                        'sizes' => $size
                    ])
                );
            }
    
            $package->addTag('favicon.ie', new ConditionalComment(
                new Favicon('http://site.com/favicon-ie.png'), 'IE gt 6'
            ));
        });
    }
    
    ...
}

然后在config/meta_tags.php中的packages部分中添加此包

...
'packages' => [
    'favicons'
],
...

然后您在head部分将看到类似的内容

<head>
    ...
    <title>...</title>
    <link rel="icon" type="image/png" href="http://site.com/favicon-16x16.png" sizes="16x16"/>
    <link rel="icon" type="image/png" href="http://site.com/favicon-32x32.png" sizes="32x32"/>
    <link rel="icon" type="image/png" href="http://site.com/favicon-64x64.png" sizes="64x64"/>
    <!--[if IE gt 6]>
    <link rel="icon" type="image/png" href="http://site.com/favicon-ie.png" />
    <![endif]-->
    ...
</head>

扩展

如果您想扩展Meta类,可以在App\Providers\MetaTagsServiceProvider中这样做。只需覆盖registerMeta方法。

namespace App\Providers;

use Butschster\Head\MetaTags\Meta;
use Butschster\Head\Contracts\MetaTags\MetaInterface;
use Butschster\Head\Contracts\Packages\ManagerInterface;

class MetaTagsServiceProvider {

    ...

    protected function registerMeta(): void
    {
        $this->app->singleton(MetaInterface::class, function () {
            $meta = new Meta(
                $this->app[ManagerInterface::class],
                $this->app['config']
            );
    
    
            // It just an imagination, you can automatically 
            // add favicon if it exists
            if (file_exists(public_path('favicon.ico'))) {
                $meta->setFavicon('/favicon.ico');
            }
    
            $meta->includePackages('fonts', 'assets');
            
            // This method gets default values from config and creates tags
            // If you don't want to use default values just remove it.
            $meta->initialize();
    
            return $meta;
        });
    }

    ...
}

与inertiajs或vue-meta一起使用

您可以将Meta对象轻松转换为数组,并在您的Js项目中使用这些值

$meta = Meta::setTitle('Laravel')
    ->setDescription('Awesome page')
    ->setKeywords('php, laravel, ...');

dd($meta->toArray());

[
    'head' => [
        [
            'tag' => 'title',
            'content' => 'Laravel',
        ],
        [
            'name' => 'description',
            'content' => 'Awesome page',
            'type' => 'tag',
            'tag' => 'meta',
        ],
        [
            'name' => 'keywords',
            'content' => 'php, laravel, ...',
            'type' => 'tag',
            'tag' => 'meta',
        ],
    ]
]

inertiaJs的示例

use Inertia\Inertia;
use Butschster\Head\MetaTags\MetaInterface;
use Butschster\Head\Hydrator\VueMetaHydrator;

class EventsController extends Controller
{
    protected $meta;
 
    public function __contruct(MetaInterface $meta)
    {
        $this->meta = $meta;
    }
    
    public function show(Event $event, VueMetaHydrator $hydrator)
    {
        $this->meta->setTitle('Laravel')
            ->setDescription('Awesome page')
            ->setKeywords('php, laravel, ...');
    
        return Inertia::render('Event/Show', [
            'event' => $event->only('id', 'title', 'start_date', 'description'),
            
            // this.$page.props.meta...
            'meta' => $hydrator->hydrate($this->meta)
        ]);
    }
}