【问题标题】:Laravel generate slug before saveLaravel 在保存前生成 slug
【发布时间】:2015-08-15 10:47:48
【问题描述】:

我正在尝试在 this wondefull website 的帮助下学习 laravel 5。 对于我的活动模型,我想在将其保存到数据库之前生成 slug,因此我创建了以下模型。

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Activity extends Model {

    protected $table = 'activitys';

    protected $fillable = [
        'title',
        'text',
        'subtitle'
    ];

    // Here I want to auto generate slug based on the title
    public function setSlugAttribute(){
        $this->attributes['slug'] = str_slug($this->title , "-");
    }
    //    
}

但是当我在 Activity 模型 slug 未填充的帮助下保存对象时,我尝试将其更改为 $this->attributes['title'] = "test" 进行测试,但它没有运行。我也尝试将参数 $title, $slug 添加到 setSlugAttribute() 但它没有帮助。

我做错了什么,有人可以解释在 setSomeAttribute($whyParameterHere) 的一些示例中使用的参数。

注意:我的数据库中有一个 slug 字段。

根据 user3158900 的建议,我已经尝试过:

public function setTitleAttribute($title){
    $this->title = $title;
    $this->attributes['slug'] = str_slug($this->title , "-");
}
//

这使我的标题字段为空,但以我想要的方式保存了 slug,为什么 $this->title 为空呢? 如果我删除 $this->title = $title; title 和 slug 都是空的

【问题讨论】:

    标签: php laravel laravel-5


    【解决方案1】:

    我认为这不起作用,因为您没有尝试设置 slug 属性,因此该函数永远不会被命中。

    我建议在您的 setTitleAttribute() 函数中设置 $this-&gt;attributes['slug'] = ... 以便在您设置标题时运行。

    否则,另一种解决方案是在保存时为您的模型创建一个事件,将其设置在那里。

    编辑:根据cmets的说法,这个函数中也需要实际设置title属性...

    public function setTitleAttribute($value)
    {
        $this->attributes['title'] = $value;
        $this->attributes['slug'] = str_slug($value);
    }
    

    【讨论】:

    • 在您的帮助下编辑问题。由于某种原因,它使标题为空。如果我删除 $this->title = $title;两者都是空的。我还是不明白参数虽然
    • $this->title = $title;应该是 $this->attributes['title'] 现在可以正常工作了!
    • 使用 Sluggable 库
    【解决方案2】:

    你有两种方法:

    1。在您的控制器方法中添加本地化这一行:

    $request['slug'] = Str::slug($request->title);
    

    示例:

    //use Illuminate\Support\Str;
    
    public function store(Request $request)
    {
        $request['slug'] = Str::slug($request->title);
    
        auth()->user()->question()->create($request->all());
        return response('Created!',Response::HTTP_CREATED);
    }
    

    2。将其添加到您的模型中以在 db 中每次保存时检查它

    //use Illuminate\Support\Str;
    
    protected static function boot() {
        parent::boot();
    
        static::creating(function ($question) {
            $question->slug = Str::slug($question->title);
        });
    }
    
    

    示例:

    <?php
    
    namespace App\Model;
    
    use Illuminate\Database\Eloquent\Model;
    use App\User;
    use Illuminate\Support\Str;
    
    class Question extends Model
    {
        protected static function boot() {
            parent::boot();
    
            static::creating(function ($question) {
                $question->slug = Str::slug($question->title);
            });
        }
    
    //The rest of methods
    
    

    您必须在类声明之前添加此代码:

    use Illuminate\Support\Str;
    

    【讨论】:

    • 在 Laravel8 中完美运行,谢谢
    【解决方案3】:

    实现此目的的一种方法是连接到model events。在这种情况下,我们希望在创建时生成一个 slug。

    /**
     * Laravel provides a boot method which is 'a convenient place to register your event bindings.'
     * See: https://laravel.com/docs/4.2/eloquent#model-events
     */
    public static function boot()
    {
        parent::boot();
    
        // registering a callback to be executed upon the creation of an activity AR
        static::creating(function($activity) {
    
            // produce a slug based on the activity title
            $slug = \Str::slug($news->title);
    
            // check to see if any other slugs exist that are the same & count them
            $count = static::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
    
            // if other slugs exist that are the same, append the count to the slug
            $activity->slug = $count ? "{$slug}-{$count}" : $slug;
    
        });
    
    }
    

    您还需要将以下内容添加到您的应用程序别名列表 (app.php):

    'Str' => Illuminate\Support\Str::class,
    

    【讨论】:

    • 很好的解决方案!当输入像titletitle-1title-3 这样的顺序输入时,它可以工作,但如果首先给出Title 1,它会在用户为Title 生成slug 时生成title-1,它会抛出重复的条目异常(因为它已经生成tittle-1)。怎么解决?
    • 您可能必须更改 RegEx 表达式以考虑您所概述的场景,或者将代码包装在检查重复条目的事务中,此时异常可以处理修改条目,或者它可能只是一个验证错误。给猫剥皮有多种方法。如果有人有兴趣,我可以编写一些代码来处理这种情况。
    【解决方案4】:

    您可以使用我使用的这个包 https://github.com/cviebrock/eloquent-sluggable 或检查它如何将观察者应用于模型保存以及它如何生成唯一的 Slug,然后执行相同操作。

    【讨论】:

      【解决方案5】:

      在设置 title 属性时,您想根据标题设置 slug。

      public function setTitleAttribute($value)
      {
          $this->attributes['title'] = $value;
          $this->attributes['slug'] = str_slug($value);
      }
      
      /// Later that same day...
      
      $activity->title = 'Foo Bar Baz';
      
      echo $activity->slug; // prints foo-bar-baz
      

      另一种选择是使用 ModelObserver 并监听 saving 事件。这将允许您在模型写入数据库之前生成 slug。

      class ActivityObserver {
      
          public function saving($activity) 
          {
              $activity->slug = str_slug($activity->title);
          }
      }
      

      在这两种情况下,您可能都希望添加一些逻辑来测试数据库中是否已经存在 slug,如果存在则添加一个递增的数字。即 foo-bar-baz-2。这个逻辑最安全的地方是在 ModelObserver 中,因为它在写入操作之前立即执行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-14
        • 2018-03-28
        • 2017-05-31
        • 2011-04-27
        • 2017-12-28
        • 2021-10-26
        • 2014-05-16
        • 1970-01-01
        相关资源
        最近更新 更多