代码改动: - SEO-02 产品页标题品牌重复:Product::seoTitle() 去掉品牌后缀,由视图统一追加 $siteName - SEO-05/Geo-03 结构化数据:布局增 WebSite+SearchAction;产品页 Product+BreadcrumbList;文章页 Article+BreadcrumbList(含作者/发布日期) - SEO-06 hreflang 自引用(zh-CN/x-default) - SEC-02 新增 public/.well-known/security.txt - GEO-05 新增 public/llms.txt 记录文档(供未来开发者接手): - CHANGELOG.md:版本与变更日志 - docs/SECURITY_SEO_REMEDIATION.md:逐项状态总表 + 改动位置 + 上线 curl 自检清单 (SEC-01/REL-01~03/PHY-01~04 等需 Tailwind 构建或云端操作项标记为待办,未自动改以免破坏站点)
55 lines
1.3 KiB
PHP
55 lines
1.3 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class Product extends Model
|
|
{
|
|
use SoftDeletes;
|
|
|
|
protected $fillable = [
|
|
'category_id',
|
|
'name',
|
|
'slug',
|
|
'model',
|
|
'summary',
|
|
'description',
|
|
'specs',
|
|
'cover',
|
|
'status',
|
|
'sort',
|
|
'seo_title',
|
|
'seo_description',
|
|
];
|
|
|
|
protected $casts = [
|
|
'category_id' => 'integer',
|
|
'sort' => 'integer',
|
|
];
|
|
|
|
public function category(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Category::class, 'category_id');
|
|
}
|
|
|
|
public function scopePublished($query)
|
|
{
|
|
return $query->where('status', 'published')->orderBy('sort')->orderBy('name');
|
|
}
|
|
|
|
public function seoTitle(): string
|
|
{
|
|
// 仅返回实体名;品牌后缀由视图统一以 ' - ' . $siteName 追加(products/show.blade.php:4),
|
|
// 避免 Product::seoTitle() 与视图双重拼接导致标题品牌重复(审计 SEO-02)。
|
|
return $this->seo_title ?: $this->name;
|
|
}
|
|
|
|
public function seoDescription(): string
|
|
{
|
|
return $this->seo_description ?: ($this->summary ?: $this->name);
|
|
}
|
|
}
|