php Laravel 在保存前生成 slug

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30582600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:53:43  来源:igfitidea点击:

Laravel generate slug before save

phplaravellaravel-5

提问by Sven van den Boogaart

Im trying to learn laravel 5 with help of this wondefull website. For my activity model I want to generate slugs before I save one to my database so I've created the following model.

我试图在这个奇妙的网站的帮助下学习 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 , "-");
    }
    //    
}

But when I save an object with help of the Activity model slug is not filled, i tried changing it to $this->attributes['title'] = "test" for testing but it didnt run. Also I tried adding parameters $title, $slug to setSlugAttribute() but it didnt help.

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

What am I doing wrong and could someone explain the parameter that is used in some examples for setSomeAttribute($whyParameterHere).

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

Note : there is a slug field in my database.

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

As suggested by user3158900 I've tried :

正如 user3158900 所建议的,我尝试过:

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

This makes my title field empty but saves the slug the way I want it, why is $this->title empty then ? If I remove $this->title = $title; both title and slug are empty

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

回答by user1669496

I believe this isn't working because you aren't trying to set a slug attribute so that function never gets hit.

我相信这是行不通的,因为您没有尝试设置 slug 属性,以便该函数永远不会被击中。

I'd suggest setting $this->attributes['slug'] = ...in your setTitleAttribute()function so it runs whenever you set a title.

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

Otherwise, another solution would be to create an event on save for your model which would set it there.

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

Edit: According to comments, it's also necessary to actually set the title attribute in this function as well...

编辑:根据评论,还需要在此功能中实际设置标题属性......

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

回答by Dilworth

One way to accomplish this would be to hook into model events. In this instance, we want to generate a slug upon creating.

实现此目的的一种方法是挂钩模型事件。在这种情况下,我们希望在创建.

/**
 * 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;

    });

}

You will also need to add the following to your applications list of aliases (app.php):

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

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

回答by Mahmoud Zalt

You could use this package which I use https://github.com/cviebrock/eloquent-sluggableor check how it applies an observer on the model saving and how it generates a unique Slug, then do the same.

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

回答by Piotr

You got 2 ways:

你有两种方法:

1. Add localy in your controller method this line:

1. 在您的控制器方法中添加 localy 这一行:

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

Example:

例子:

//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. Add it in your model to check it every save in db

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

//use Illuminate\Support\Str;

protected static function boot() {
    parent::boot();

    static::creating(function ($question) {
        $question->slug = Str::slug($question->title);
    });
}

Example:

例子:

<?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

In each way you have to add this code before class declaration:

在每种方式中,您都必须在类声明之前添加此代码:

use Illuminate\Support\Str;

回答by Collin James

You want to set the slug based off the title when the title attribute is being set.

您希望在设置 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

Another alternative would be to use a ModelObserverand listen to the savingevent. This will allow you to generate the slug right before the model is written to the database.

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

class ActivityObserver {

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

In both cases you probably want to add some logic to test if the slug already exists in the DB, adding an incrementing number if it does. ie foo-bar-baz-2. The safest place for this logic would be in the ModelObserver as it is executed immediately prior to the write action.

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