├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── UPGRADING.md ├── composer.json ├── config └── meta-tags.php ├── database └── migrations │ └── create_meta_tags_table.php.stub ├── resources └── views │ └── tags.blade.php └── src ├── Builder.php ├── Facade.php ├── Models └── MetaTag.php ├── ServiceProvider.php └── Traits └── Metatagable.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | composer.lock 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog Laravel Meta Tags 2 | 3 | ## 2.0.0 - 2019-02-11 4 | 5 | - Added fields `seo_text`, `timestamps` 6 | - Remove helper `meta_tag_prepare_path` 7 | - Added support Laravel 5.8 8 | 9 | ## 1.2.0 - 2018-10-25 10 | 11 | - Added caninical tag 12 | - Added robots tag 13 | 14 | ## 1.1.0 - 2018-10-25 15 | 16 | - Added `setDefault()` & `meta_tag_prepare_path` 17 | - Fixed `singleton` for path 18 | - Updated docs 19 | 20 | ## 1.0.0 - 2018-10-24 21 | 22 | - Initial release package 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Fomin Vasyl 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Development and support of this package is discontinued! Use a better solution [fomvasss/laravel-seo](https://github.com/fomvasss/laravel-seo)** 2 | 3 | 4 | # Laravel Meta Tags 5 | 6 | [![License](https://img.shields.io/packagist/l/fomvasss/laravel-meta-tags.svg?style=for-the-badge)](https://packagist.org/packages/fomvasss/laravel-meta-tags) 7 | [![Build Status](https://img.shields.io/github/stars/fomvasss/laravel-meta-tags.svg?style=for-the-badge)](https://github.com/fomvasss/laravel-meta-tags) 8 | [![Latest Stable Version](https://img.shields.io/packagist/v/fomvasss/laravel-meta-tags.svg?style=for-the-badge)](https://packagist.org/packages/fomvasss/laravel-meta-tags) 9 | [![Total Downloads](https://img.shields.io/packagist/dt/fomvasss/laravel-meta-tags.svg?style=for-the-badge)](https://packagist.org/packages/fomvasss/laravel-meta-tags) 10 | [![Quality Score](https://img.shields.io/scrutinizer/g/fomvasss/laravel-meta-tags.svg?style=for-the-badge)](https://scrutinizer-ci.com/g/fomvasss/laravel-meta-tags) 11 | 12 | With this package you can manage meta-tags and SEO-fields from Laravel controllers and "blade" template. 13 | 14 | ---------- 15 | 16 | ## Installation 17 | 18 | Run from the command line: 19 | 20 | ```bash 21 | composer require fomvasss/laravel-meta-tags 22 | ``` 23 | 24 | ### Publish and settings 25 | 26 | 1) Publish assets - run this on the command line: 27 | 28 | ```bash 29 | php artisan vendor:publish --provider="Fomvasss\LaravelMetaTags\ServiceProvider" 30 | ``` 31 | - A configuration file will be publish to `config/meta-tags.php`. 32 | - A migration file will be publish to `database/migrations/DATE_NOW_create_meta_tags_table.php`. 33 | - A customizable blade template file will be publish to `resources/views/vondor/meta-tags/tags.blade.php`. 34 | 35 | 2) Edit assets: 36 | 37 | - Set available tags in`config/meta-tags.php` - uncomment needed 38 | - If needed - set own model class for meta-tags in`config/meta-tags.php` 39 | - Edit migration `meta_tags` file - set available field tags - uncomment needed 40 | 41 | 3) Run migration 42 | ``` 43 | php artisan migrate 44 | ``` 45 | 46 | --- 47 | 48 | ## Upgrading 49 | 50 | When upgrading from v2 to v3, please see the [UPGRADING.md](UPGRADING.md) 51 | 52 | --- 53 | 54 | ## Integrate & usage 55 | 56 | ### Usage in Eloquent models: `app/Models/Article.php` 57 | 58 | Add `Metatagable` trait in your entity model: 59 | 60 | ```php 61 | 'Article index page', 96 | 'description' => 'It is article index page', 97 | ]); 98 | 99 | return view('index', compact('articles')); 100 | } 101 | 102 | public function store(Request $request) 103 | { 104 | // create entity 105 | $article = \App\Model\Article::create($request->only([ 106 | //.. article data 107 | ])); 108 | 109 | // create meta tag for entity 110 | $article->metaTag()->create($request->only([ 111 | //.. meta tags fields 112 | ])); 113 | } 114 | 115 | public function show($id) 116 | { 117 | $article = \App\Model\Article::findOrFail($id); 118 | 119 | // Set tags for showing 120 | MetaTag::setEntity($article) 121 | ->setDefault([ 122 | 'title' => $article->title, // if empty $article->metaTag->title - show this title 123 | ])->setTags([ 124 | 'seo_text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', 125 | 'h1' => $article->title, 126 | ]); 127 | 128 | return view('stow', compact('article')); 129 | } 130 | 131 | public function search(Request $request) 132 | { 133 | $articles = \App\Model\Article::bySearch($request->q) 134 | ->paginate(); 135 | 136 | // Set tags for showing 137 | MetaTag::setPath() // if argument `setPath()` is empty (or not set) - path = `request()->path()` 138 | ->setDefault([ 139 | 'title' => 'Search page', 140 | 'robots' => 'noindex', 141 | 'og_title' => 'Search page OG', 142 | 'twitter_title' => 'Search page Twitter', 143 | 'canonical' => 'page/search', 144 | ]); 145 | 146 | return view('index', compact('articles')); 147 | } 148 | } 149 | ``` 150 | 151 | For the package to work correctly, you must save to the database, in the `path` field, only the url-path itself, without a domain and trim slash'es (`/`) 152 | 153 | Example: 154 | - `https://site.com/some/pages/?page=23` => `some/pages` 155 | - `https://site.com/some/pages` => `/` 156 | 157 | 158 | ### Usage facade `MetaTag` in blade templates: `resources/views/layouts/app.blade.php` 159 | 160 | Simple and efficient: 161 | 162 | ```blade 163 | 164 | 165 | 166 | 167 | 168 | 169 | {!! MetaTag::render() !!} 170 | 171 | 172 | 173 | @yield('content') 174 | 175 | 176 | ``` 177 | 178 | Or output one by one manually: 179 | 180 | ```blade 181 | 182 | 183 | 184 | 185 | 186 | 187 | {!! MetaTag::tag('title') !!} 188 | 189 | 190 | 191 | 192 | 193 | @yield('content') 194 | 195 | 196 | ``` 197 | 198 | Another example: `resources/views/articles/show.blade.php` 199 | 200 | ```blade 201 | @extends('layouts.app') 202 | @section('content') 203 |

{!! MetaTag::tag('title') !!}

204 |
{!! $article->body !!}
205 |
{{ MetaTag::tag('seo_text') }}
206 | @endsection 207 | ``` 208 | 209 | And you can set meta tags right in the template: 210 | 211 | ```blade 212 | 213 | 214 | 215 | 216 | 217 | 218 | @php(MetaTag::setEntity($article)) 219 | @php(MetaTag::setDefault(['description' => 'My default meta tag'])) 220 | 221 | {!! MetaTag::render() !!} 222 | 223 | 224 | 225 | @yield('content') 226 | 227 | 228 | ``` 229 | 230 | Similarly: 231 | 232 | ```blade 233 | {!! 234 | \MetaTag::setEntity($article) 235 | ->setDefault(['description' => 'My default meta tag']) 236 | ->render() 237 | !!} 238 | ``` 239 | 240 | ```blade 241 | {!! 242 | \MetaTag::setPath('articles') 243 | ->setDefault(['robots' => 'follow', 'canonical' => 'page/articles']) 244 | ->setDefault(['title' => 'All articles']) 245 | ->setDefault(['og_title' => 'All articles']) 246 | ->setDefault(['og_locale' => 'de']) 247 | ->setDefault(['og_image' => 'files/images/5be3d92e02a55890e4301ed4.jpg', 'og_image_height' => 123]) 248 | ->render() 249 | !!} 250 | ``` 251 | 252 | ## Links 253 | 254 | * [Use perfect package for url-aliases](https://github.com/fomvasss/laravel-url-aliases) -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Upgrading 2 | 3 | ## From v2 to v3 4 | 5 | The database schema for `meta_tags` table have change, you should update the table accordingly. 6 | 7 | - ~~`metatagable_id`~~ -> `model_id` 8 | - ~~`metatagable_type`~~ -> `model_type` 9 | 10 | To rename the columns see [Laravel's Documenation on Modifiyng Columns](https://laravel.com/docs/8.x/migrations#modifying-columns) 11 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fomvasss/laravel-meta-tags", 3 | "description": "A package to manage SEO (meta-tags, xml-fields, etc.)", 4 | "type": "composer-package", 5 | "keywords": ["meta tags", "meta", "tags", "seo", "seo", "sitemap", "xml-map", "laravel"], 6 | "authors": [ 7 | { 8 | "name": "Vasyl Fomin", 9 | "email": "fomvasss@gmail.com", 10 | "role": "Developer" 11 | } 12 | ], 13 | "license": "MIT", 14 | "require": { 15 | "php" : ">=7.0.0", 16 | "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0", 17 | "illuminate/database": "^5.8|^6.0|^7.0|^8.0|^9.0", 18 | "illuminate/view": "^5.8|^6.0|^7.0|^8.0|^9.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Fomvasss\\LaravelMetaTags\\": "src" 23 | } 24 | }, 25 | "extra": { 26 | "laravel": { 27 | "providers": [ 28 | "Fomvasss\\LaravelMetaTags\\ServiceProvider" 29 | ], 30 | "aliases": { 31 | "MetaTag": "Fomvasss\\LaravelMetaTags\\Facade" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/meta-tags.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'title' => env('APP_NAME'), 10 | 11 | 'og_image' => [ 12 | 'type' => 'image/png', 13 | 'width' => '780', 14 | 'height' => '780', 15 | ], 16 | 17 | 'fb_app_id' => env('SEO_FB_ID', null), 18 | ], 19 | 20 | /* ----------------------------------------------------------------- 21 | | Will be render in blade 22 | | Uncomment needed 23 | | ----------------------------------------------------------------- 24 | */ 25 | 'available' => [ 26 | // Main 27 | 'title' => ['title' => 'Title'], // recommend max => 60 28 | 'description' => ['title' => 'Description'], // recommend max => 300 29 | 'keywords' => ['title' => 'Keywords'], // recommend max => 300 30 | 31 | // OG-tags 32 | 'og_site_name' => ['title' => 'OG-site name'], 33 | 'og_locale' => ['title' => 'OG-locale'], 34 | 'og_title' => ['title' => 'OG-title'], 35 | 'og_description' => ['title' => 'OG-description'], 36 | 'og_type' => ['title' => 'OG-type'], 37 | 'og_image' => ['title' => 'OG-image'], 38 | 'og_url' => ['title' => 'OG-url'], 39 | 'og_audio' => ['title' => 'OG-audio'], 40 | 'og_determiner' => ['title' => 'OG-determiner'], 41 | 'og_video' => ['title' => 'OG-video'], 42 | 43 | // Twitter tags 44 | 'twitter_title' => ['title' => 'Twitter domain'], 45 | 'twitter_description' => ['title' => 'Twitter description'], 46 | 'twitter_card' => ['title' => 'Twitter card'], 47 | 'twitter_site' => ['title' => 'Twitter site'], 48 | 'twitter_creator' => ['title' => 'Twitter creator'], 49 | 'twitter_image' => ['title' => 'Twitter image'], 50 | 'twitter_domain' => ['title' => 'Twitter domain'], 51 | 52 | // Additional fields 53 | 'canonical' => ['title' => 'Canonical link'], 54 | 'robots' => ['title' => 'Robots'], 55 | 'fb_app_id' => ['title' => 'Facebook app ID'], 56 | ], 57 | 58 | /* ----------------------------------------------------------------- 59 | | This is example, for dashboard SEO form,... 60 | | Available values 61 | | This list is a sample and is not used in the package 62 | | ----------------------------------------------------------------- 63 | */ 64 | 'values' => [ 65 | 'robots' => ['none', 'all', 'index', 'noindex', 'nofollow', 'follow',], 66 | 'changefreq' => ['always', 'daily', 'hourly', 'weekly',], 67 | 'priority' => [0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9,], 68 | ], 69 | 70 | 71 | /* ----------------------------------------------------------------- 72 | | The default Model meta-tag 73 | | ----------------------------------------------------------------- 74 | */ 75 | 'model' => \Fomvasss\LaravelMetaTags\Models\MetaTag::class, 76 | ]; 77 | -------------------------------------------------------------------------------- /database/migrations/create_meta_tags_table.php.stub: -------------------------------------------------------------------------------- 1 | id(); 18 | 19 | // url path - without domain 20 | $table->string('path')->nullable(); 21 | 22 | // metatagable: node, term,... 23 | $table->integer('model_id')->nullable(); 24 | $table->string('model_type')->nullable(); 25 | 26 | // Meta-tags 27 | $table->string('title')->nullable(); 28 | $table->string('keywords')->nullable(); 29 | $table->text('description')->nullable(); 30 | 31 | // SEO-fields 32 | $table->string('h1')->nullable(); 33 | $table->text('seo_text')->nullable(); 34 | $table->string('canonical')->nullable(); 35 | $table->string('robots')->nullable(); 36 | 37 | // Fields for build XML site-map 38 | $table->string('changefreq', 10)->nullable(); 39 | $table->string('priority', 10)->nullable(); 40 | 41 | // OG-tags 42 | // $table->string('og_title')->nullable(); 43 | // $table->text('og_description')->nullable(); 44 | // $table->string('og_type')->nullable(); 45 | // $table->string('og_image')->nullable(); 46 | // $table->string('og_url')->nullable(); 47 | // $table->string('og_audio')->nullable(); 48 | // $table->string('og_determiner')->nullable(); 49 | // $table->string('og_locale')->nullable(); 50 | // $table->string('og_site_name')->nullable(); 51 | // $table->string('og_video')->nullable(); 52 | 53 | // Twitter tags 54 | // $table->string('twitter_title')->nullable(); 55 | // $table->text('twitter_description')->nullable(); 56 | // $table->string('twitter_card')->nullable(); 57 | // $table->string('twitter_site')->nullable(); 58 | // $table->string('twitter_creator')->nullable(); 59 | // $table->string('twitter_image')->nullable(); 60 | // $table->string('twitter_domain')->nullable(); 61 | 62 | // for XML site-map "lastmod" 63 | $table->timestamps(); 64 | }); 65 | } 66 | 67 | /** 68 | * Reverse the migrations. 69 | * 70 | * @return void 71 | */ 72 | public function down() 73 | { 74 | Schema::dropIfExists('meta_tags'); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /resources/views/tags.blade.php: -------------------------------------------------------------------------------- 1 | @if(count($tags)) 2 | @foreach(config('meta-tags.available') as $key => $option) 3 | @if (isset($tags[$key])) 4 | @if($key === 'canonical' && $tags[$key]) 5 | 6 | @elseif($key === 'title') 7 | {{ $tags[$key] }} 8 | @elseif($key === 'description') 9 | 10 | @elseif($key === 'keywords') 11 | 12 | @elseif($key === 'robots') 13 | 14 | @elseif (preg_match('/^og_\w+/', $key)) 15 | @if($key === 'og_url') 16 | 17 | @elseif($key === 'og_image' && !empty($tags[$key])) 18 | 19 | 20 | 21 | 22 | @else 23 | 24 | @endif 25 | @elseif (preg_match('/^twitter_\w+/', $key)) 26 | @if($key === 'twitter_image' && !empty($tags[$key])) 27 | 28 | @else 29 | 30 | @endif 31 | @endif 32 | @endif 33 | @endforeach 34 | @else 35 | {{ config('meta-tags.default.title') }} 36 | @endif 37 | 38 | @if(config('meta-tags.default.fb_app_id')) 39 | 40 | @endif -------------------------------------------------------------------------------- /src/Builder.php: -------------------------------------------------------------------------------- 1 | getTemplate(), [ 62 | 'tags' => $this->get(), 63 | 'path' => $this->getPath(), 64 | 'entity' => $this->entityModel, 65 | ])->render(); 66 | } 67 | 68 | /** 69 | * @param string $template 70 | * @return Builder 71 | */ 72 | public function setTemplate(string $template): self 73 | { 74 | $this->template = $template; 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * @return string 81 | */ 82 | public function getTemplate(): string 83 | { 84 | return $this->template; 85 | } 86 | 87 | /** 88 | * @param Model $entityModel 89 | * @return $this 90 | */ 91 | public function setEntity(Model $entityModel) 92 | { 93 | $this->entityModel = $entityModel; 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * Set current path. 100 | * 101 | * @param string $path 102 | * @return $this 103 | */ 104 | public function setPath(string $path = null) 105 | { 106 | $this->pathModel = null; 107 | 108 | $this->path = $path ?: \Illuminate\Support\Facades\Request::path(); 109 | 110 | return $this; 111 | } 112 | 113 | public function getPath(): string 114 | { 115 | return $this->path ?: \Illuminate\Support\Facades\Request::path(); 116 | } 117 | 118 | /** 119 | * @param array $tags 120 | * @return $this 121 | */ 122 | public function setTags(array $tags = []) 123 | { 124 | $this->tags = array_merge($this->tags, $tags); 125 | 126 | return $this; 127 | } 128 | 129 | /** 130 | * @param array $defaultTags 131 | */ 132 | public function setDefault(array $defaultTags = []) 133 | { 134 | $this->default = array_merge($this->default, $defaultTags); 135 | 136 | return $this; 137 | } 138 | 139 | /** 140 | * @return array 141 | */ 142 | public function get(): array 143 | { 144 | if ($this->entityModel) { 145 | $this->result = $this->getForEntity(); 146 | } 147 | 148 | if ($this->path) { 149 | $this->result = $this->getForPath(); 150 | } 151 | 152 | if ($this->tags) { 153 | $this->result = $this->getTags(); 154 | } 155 | 156 | if ($this->result) { 157 | return $this->getResult(); 158 | } 159 | 160 | $this->setPath(); 161 | $this->result = $this->getForPath(); 162 | 163 | return $this->getResult(); 164 | } 165 | 166 | /** 167 | * @param string $tag 168 | * @return string 169 | */ 170 | public function tag(string $tag): string 171 | { 172 | return $this->get()[$tag] ?? ''; 173 | } 174 | 175 | /** 176 | * @return array 177 | */ 178 | public function getForEntity(): array 179 | { 180 | if ($this->entityModel && ($tags = $this->entityModel->metaTag)) { 181 | return array_merge($this->getResult(), $tags->toArray()); 182 | } 183 | 184 | return []; 185 | } 186 | 187 | /** 188 | * @return array 189 | */ 190 | public function getForPath(): array 191 | { 192 | if (isset($this->path)) { 193 | if (!isset($this->pathModel)) { // Singleton 194 | $modelClass = config('meta-tags.model', \Fomvasss\LaravelMetaTags\Models\MetaTag::class); 195 | try { 196 | $this->pathModel = $modelClass::wherePath($this->path)->first() ?? 0; 197 | } catch (\Exception $e) { 198 | //... 199 | } 200 | } 201 | 202 | return array_merge( 203 | $this->getResult(), 204 | $this->pathModel ? $this->pathModel->toArray() : [] 205 | ); 206 | } 207 | 208 | return []; 209 | } 210 | 211 | /** 212 | * @return array 213 | */ 214 | protected function getTags(): array 215 | { 216 | return array_merge($this->getResult(), $this->tags); 217 | } 218 | 219 | /** 220 | * @return array 221 | */ 222 | public function getResult(): array 223 | { 224 | $result = array_filter($this->result, function ($tag) { 225 | if ($tag !== null && $tag !== '') { 226 | return $tag; 227 | } 228 | }); 229 | 230 | return array_merge($this->default, $result); 231 | } 232 | } -------------------------------------------------------------------------------- /src/Facade.php: -------------------------------------------------------------------------------- 1 | morphTo('metatagable', 'model_type', 'model_id'); 14 | } 15 | 16 | /** 17 | * TODO: Deprecated 18 | * 19 | * @param $query 20 | * @param string|null $type 21 | * @return mixed 22 | */ 23 | public function scopeByType($query, string $type = null) 24 | { 25 | return $query->where('model_type', config("meta-tags.types.$type.model")); 26 | } 27 | 28 | public function scopeByPath($query, string $path = '/') 29 | { 30 | return $query->where('path', $path); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishedConfig(); 15 | 16 | $this->publishedMigrations(); 17 | 18 | $this->loadViewsFrom(__DIR__.'/../resources/views', 'meta-tags'); 19 | 20 | $this->publishes([ 21 | __DIR__.'/../resources/views' => resource_path('views/vendor/meta-tags'), 22 | ]); 23 | } 24 | 25 | /** 26 | * Register the application services. 27 | * 28 | * @return void 29 | */ 30 | public function register() 31 | { 32 | $this->mergeConfigFrom(__DIR__.'/../config/meta-tags.php', 'meta-tags'); 33 | 34 | $this->app->singleton(Builder::class); 35 | } 36 | 37 | protected function publishedConfig() 38 | { 39 | $this->publishes([ 40 | __DIR__.'/../config/meta-tags.php' => config_path('meta-tags.php') 41 | ], 'config'); 42 | } 43 | 44 | protected function publishedMigrations() 45 | { 46 | if (! class_exists('CreateMetaTagsTable')) { 47 | $timestamp = date('Y_m_d_His', time()); 48 | 49 | $this->publishes([ 50 | __DIR__.'/../database/migrations/create_meta_tags_table.php.stub' => database_path('/migrations/'.$timestamp.'_create_meta_tags_table.php'), 51 | ], 'migrations'); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Traits/Metatagable.php: -------------------------------------------------------------------------------- 1 | seo()->delete(); 11 | }); 12 | } 13 | 14 | /** 15 | * Deprecated, will be replaced by seo() 16 | * 17 | * @return \Illuminate\Database\Eloquent\Relations\MorphOne 18 | */ 19 | public function metaTag() 20 | { 21 | return $this->seo(); 22 | } 23 | 24 | /** 25 | * @return \Illuminate\Database\Eloquent\Relations\MorphOne 26 | */ 27 | public function seo() 28 | { 29 | $modelClass = config('meta-tags.model', \Fomvasss\LaravelMetaTags\Models\MetaTag::class); 30 | 31 | return $this->morphOne($modelClass, 'model'); 32 | } 33 | } --------------------------------------------------------------------------------