在表单中,我有一个Tags字段,它只是一个标准的文本字段。用户可以键入标记名称,然后将其添加到文章中。
我已经有三个表:tags
,taggables
和articles
并且它们是通过Eloquent关系方法链接的,考虑到a previous question中的设置,我问过。
这是我ArticleController
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$validatedData = $request->validate([
'title' => 'required',
'excerpt' => 'required',
]);
$article = Article::find($id);
$article->title = $request->get('title');
$article->author = $request->get('author');
$article->category = $request->get('category');
$article->excerpt = $request->get('excerpt');
$article->content = $request->get('content');
$article->featuredImage = $request->get('featuredImage');
$article->featuredVideo = $request->get('featuredVideo');
$article->readingTime = $request->get('readingTime');
$article->published = $request->get('published');
$article->save();
/**
* Once the article has been saved, we deal with the tag logic.
* Grab the tag or tags from the field, sync them with the article
*/
$tags = $request->get('tags');
$comma = ',';
if (!empty($tags)) {
if (strpos($tags, $comma) !== false) {
$tagList = explode(",", $tags);
// Loop through the tag array that we just created
foreach ($tagList as $tags) {
// Get any existing tags
$tag = Tag::where('name', '=', $tags)->first();
// If the tag exists, sync it, otherwise create it
if ($tag != null) {
$article->tags()->sync($tag->id);
} else {
$tag = new Tag();
$tag->name = $tags;
$tag->slug = str_slug($tags);
$tag->save();
$article->tags()->sync($tag->id);
}
}
} else {
// Only one tag
$tag = Tag::where('name', '=', $tags)->first();
if ($tag != null) {
$article->tags()->sync($tag->id);
} else {
$tag = new Tag();
$tag->name = $tags;
$tag->slug = str_slug($tags);
$tag->save();
$article->tags()->sync($tag->id);
}
}
}
return back();
return redirect()->back();
}
在查找标签的方法部分中,我执行以下操作:
explode()
将字符串转换为数组这种方法感觉非常混乱,但是,有什么方法可以让我更干净吗?
根据提供的答案进行更新
我选择了以下方法:
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required',
'excerpt' => 'required',
]);
$article = new Article();
$article->title = $request->get('title');
$article->author = $request->get('author');
$article->category = $request->get('category');
$article->excerpt = $request->get('excerpt');
$article->content = $request->get('content');
$article->featuredImage = $request->get('featuredImage');
$article->featuredVideo = $request->get('featuredVideo');
$article->readingTime = $request->get('readingTime');
$article->published = $request->get('published');
//If no featured image set, automatically create featured image placeholder
if ($request->get('featuredImage') == null) {
$article->featuredImage = "http://via.placeholder.com/350x150";
}
$article->save();
// Handle Tags
$tags = $request->get('tags');
if (!empty($tags)) {
$tagList = array_filter(explode(",", $tags));
// Loop through the tag array that we just created
foreach ($tagList as $tags) {
$tag = Tag::firstOrCreate(['name' => $tags, 'slug' => str_slug($tags)]);
}
$tags = Tag::whereIn('name', $tagList)->get()->pluck('id');
$article->tags()->sync($tags);
}
return redirect('editable/news-and-updates')->with('success', 'Article has been added');
}
然后,为了在更新时显示标签,我做了以下工作:
/**
* Show the form to edit this resource
*/
public function edit($id)
{
$user = auth::user();
$article = Article::find($id);
// Get the tags associated with this article and convert to a comma seperated string
if ($article->has('tags')) {
$tags = $article->tags->pluck('name')->toArray();
$tags = implode(', ', $tags);
} else {
$tags = "";
}
return view('editable.news.edit', compact('article', 'user', 'tags'));
}
基本上,我只是抓取与文章关联的标签,将它们转换为数组,然后使用implode()
。
这为标签字段中的逗号分隔列表提供了标签,如:
blue, red, orange
但是,在更新时,如果我尝试使用相同的标签保存,我会得到:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'sauce' for key 'tags_slug_unique' (SQL: insert into
代码(
{名称{1}} {蛞蝓{1}}的updated_at ,
{created_at {1}}
以下是标记迁移以供参考:
,
答案 0 :(得分:3)
确实没有必要检查是否有逗号并且有两条不同的路径。如果没有逗号,则explode将返回一个迭代的元素。你可以直接删除if和else。
lists.stream().max(Comparator.comparing(List::size)).get()
此外,您还可以$tagList = explode(",", $tags);
// Loop through the tag array that we just created
foreach ($tagList as $tags) {
// Get any existing tags
$tag = Tag::where('name', '=', $tags)->first();
// If the tag exists, sync it, otherwise create it
if ($tag != null) {
$article->tags()->sync($tag->id);
} else {
$tag = new Tag();
$tag->name = $tags;
$tag->slug = str_slug($tags);
$tag->save();
$article->tags()->sync($tag->id);
}
}
查看here的文档。
firstOrCreate方法将尝试查找数据库记录 使用给定的列/值对。如果找不到该模型 在数据库中,将插入一条带有属性的记录 第一个参数,以及可选的第二个参数中的参数。
这可用于将代码重构为以下内容:
firstOrCreate
答案 1 :(得分:2)
也许像这样的东西,只是从头上输入,没有经过测试,但我希望它有点给你一个想法
public function update(Request $request, Article $article)
{
$validatedData = $request->validate([
'title' => 'required',
'excerpt' => 'required',
// Make validation for all inputs !
]);
// Fill model with inputs and save (make sure that inputs are in fillable model property)
$article->fill($request->all())->save();
// Handle Tags
$this->handleTags($request, $article);
// Return Redirect to previous URL
return redirect()->back();
}
/**
* Handle Tags for Article
* @param \Illuminate\Http\Request $request
* @param \App\Article $article
* @return void
*/
public function handleTags(Request $request, Article $article){
/**
* Once the article has been saved, we deal with the tag logic.
* Grab the tag or tags from the field, sync them with the article
*/
$tagsNames = explode(',', $request->get('tags'));
// Create all tags (unassociet)
foreach($tagsNames as $tagName){
Tag::firstOrCreate(['name' => $tagName, 'slug' => str_slug($tagName)])->save();
}
// Once All tags are created we can query them
$tags = Tag::whereIn('name', $tagNames)->get()->pluck('id')->get();
$article->tags()->sync($tags);
}
答案 2 :(得分:1)
我认为最简单的标记方法是使用多对多多态关系... morphedByMany()
和morphToMany()
。
请参阅此示例代码...
在迁移中,它们有3个表
articles
,tags
,taggables
# --- for Article Table ---
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
// ---
});
}
# --- for Tags Table ---
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('tagname');
});
}
# --- for Taggables Table ---
public function up()
{
Schema::create('taggables', function (Blueprint $table) {
$table->integer('tag_id');
$table->integer('taggable_id'); // for storing Article ID's
$table->string('taggable_type'); // Aside from Article, if you decide to use tags on other model eg. Videos, ...
});
}
在模型中
# Tag.php Model
class Tag extends Model
{
protected $fillable = [
'tagname',
];
public function article()
{
return $this->morphedByMany('Yourapp\Article', 'taggable');
}
}
# Article.php Model
class Article extends Model
{
protected $fillable = [
'title',
# and more...
];
public function tags()
{
return $this->morphToMany('Yourapp\Tag', 'taggable');
}
}
在AppServiceProvide.php中〜Yourapp / app / Providers / AppServiceProvider.php
public function boot()
{
//... by creating this map you don't need to store the "Yourapp\Post" to the "taggable_type" on taggable table
Relation::morphMap([
'article' => 'Yourapp\Article',
'videos' => 'Yourapp\Videos', // <--- other models may have tags
]);
}
现在使用Elequent,您可以轻松访问数据
$article->tags; # retrieve related tags for the article
$tags->articles; # or $tags->articles->get() retrieve all article that has specific tag
用于存储和更新文章
# SAVING article with tags
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required',
//----
// Validate tags and also it should be an Array but its up to you
'tag' => 'required|array|exists:tags,id' # < (exist:tags,id) This will check if tag exist on the Tag table
]);
$article = Article::create([
'title' => $request->input('title'),
//----
]);
//Adding tags to article, Sync() the easy way
$article->tags()->sync($request->input('tag'));
return "Return anywhare";
}
# UPDATE tags article
public function update(Request $request, $id)
{
// Validate first and ...
$article = Article::find($id)->first();
$article->title = $request->input('title');
$article->save();
//Updating tags of the article, Sync() the easy way
$article->tags()->sync($request->input('tag'));
return "Return anywhare";
}
有关多对多多态关系的更多details信息