拉拉维尔多对多关系问题


Laravel Many To Many Relationship issue

我是Laravel的新手。我修改了github代码中的启动应用程序,将给定的帖子详细信息保存到数据库中。但面临以下2个问题

  1. 仅在逗号插入数据库之前输入的第一个值。我认为正因为如此,在关系表中只插入一条记录
  2. 在编辑文章中,类别显示为json结构

我已经为多对多关系建立了一个数据库。

职位、类别和类别_职位

创建了一个表单以添加/编辑后

<form class="form-horizontal" method="post" action="@if (isset($post)){{ URL::to('admin/blogs/' . $post->id . '/edit') }}@endif" autocomplete="off">
        <!-- CSRF Token -->
        <input type="hidden" name="_token" value="{{{ csrf_token() }}}" />
        <!-- ./ csrf token -->
        <!-- Tabs Content -->
        <div class="tab-content">
            <!-- General tab -->
            <div class="tab-pane active" id="tab-general">
                <!-- Post Title -->
                <div class="form-group {{{ $errors->has('title') ? 'error' : '' }}}">
                    <div class="col-md-12">
                        <label class="control-label" for="title">Post Title</label>
                        <input class="form-control" type="text" name="title" id="title" value="{{{ Input::old('title', isset($post) ? $post->title : null) }}}" />
                        {{{ $errors->first('title', '<span class="help-block">:message</span>') }}}
                    </div>
                </div>
                <div class="form-group {{{ $errors->has('categories') ? 'error' : '' }}}">
                    <div class="col-md-12">
                        <label class="control-label" for="categories">Categories</label>
                        <input class="form-control" type="text" name="categories" id="categories" value="{{{ Input::old('categories', isset($post) ? $post->categories : null) }}}" />
                        {{{ $errors->first('categories', '<span class="help-block">:message</span>') }}}
                    </div>
                </div>
                <!-- ./ post title -->
                <!-- Content -->
                <div class="form-group {{{ $errors->has('content') ? 'has-error' : '' }}}">
                    <div class="col-md-12">
                        <label class="control-label" for="content">Content</label>
                        <textarea class="ckeditor" name="content" value="content" rows="10">{{{ Input::old('content', isset($post) ? $post->content : null) }}}</textarea>
                        {{{ $errors->first('content', '<span class="help-block">:message</span>') }}}
                    </div>
                </div>
                <!-- ./ content -->
            </div>
            <!-- ./ general tab -->
        </div>
        <!-- ./ tabs content -->
        <!-- Form Actions -->
        <div class="form-group">
            <div class="col-md-12">
                <element class="btn-cancel close_popup">Cancel</element>
                <button type="reset" class="btn btn-default">Reset</button>
                <button type="submit" class="btn btn-success">Update</button>
            </div>
        </div>
        <!-- ./ form actions -->
    </form>

这是控制器代码

// Start transaction!
        DB::beginTransaction();
        $title = Input::get('title');
        $categoriesString = Input::get('categories');
        $categories = explode(',', $categoriesString);
        $postDetails = $this->post->findByTitle($title);
        if($postDetails)
        {
            return Redirect::to('blog/create')->withInput()->withErrors(array('title' => 'Title already exists'));
        } else {
            // Update the blog post data
            $this->post->title            = $title;
            $this->post->slug             = Str::slug(Input::get('title'));
            $this->post->content          = Input::get('content');
        }
        try 
        { // Validate, then create if valid
            $newPost = $this->post->save();
        } catch(ValidationException $e)
        {
            // Rollback and then redirect
            // back to form with errors
            DB::rollback();
            return Redirect::to('admin/blogs/create')->with('error', Lang::get('admin/blogs/messages.create.error'));
        } catch('Exception $e)
        {
            DB::rollback();
            throw $e;
        }

将类别作为逗号从表单中分离

        $categoriesString = Input::get('categories');
        $categories = explode(',', $categoriesString);

然后检查数据库中是否已存在该类别。如果存在,则获取其id并附加到新数组。

        $categoryClass = new Categories();
        $categoryIds = array();
        foreach($categories as $category)
        {
            try {
                // Validate, then create if valid
                $categoryName = strtolower($category);
                $categoryDetails = $categoryClass->findByName($categoryName);
                if($categoryDetails)
                {
                    $categoryId = $categoryDetails->id;
                } else {    
                    $categoryClass->name = $category;
                    $categoryClass->save();
                    $categoryId = $categoryClass->id;
                } 
            } catch(ValidationException $e)
            {
                // Rollback and then redirect
                // back to form with errors
                DB::rollback();
                return Redirect::to('blog/create')->with('error', Lang::get('blog/messages.create.error'));
            } catch('Exception $e)
            {
                DB::rollback();
                throw $e;
            }
            // Push category id into category id's array
            $categoryIds[] = $categoryId;
        }
        //Then sync the categories with new categories  
        $this->post->categories()->sync($categoryIds);
        // Commit
        DB::commit();
        return Redirect::to('blog/' . $this->post->id . '/edit')->with('success', Lang::get('blog/messages.create.success'));

POST型号

    /**
     * Get the post's categories.
     *
     * @return array
     */
    public function categories()
    {
        return $this->belongsToMany('Categories');
    }

类别型号

    /**
     * Get the Categories's posts.
     *
     * @return array
     */
    public function posts()
    {
        return $this->belongsToMany('Post');
    }

有人请帮我摆脱这个问题。

今天做这件事要容易得多。这就是我存储文章的方式,可以用逗号分隔的标签输入。

文章控制器存储函数:首先创建文章对象,将user_id设置为当前用户会话id,并填写表单中的所有字段。如果文章被保存,则在标签模型中使用静态方法附加标签。

public function store()
{
    $article = new Article();
    $article->user_id = Auth::id();
    $article->fill(Input::all());
    if ($article->save())
    {
        Tag::attach($article, Input::get('tags'));
        return Redirect::route('articles.index')
            ->with(['flashMessage' => 'Article created.', 'flashType' => 'success']);
    } else {
        return Redirect::back()->withErrors($article->errors())->withInput();
    }
}

文章模型,设置可填充属性和标记关系:

protected $fillable = ['category_id', 'title', 'description', 'content', 'published'];
public function tags()
{
    return $this->belongsToMany('Tag', 'article_tag', 'article_id', 'tag_id');
}

标签-模型-文章关系:

public function articles()
{
    return $this->belongsToMany('Article', 'article_tag', 'tag_id', 'article_id');
}

标签模型attach-shope:首先创建一个空数组来容纳标签,分解逗号分隔的标签并枚举它们。修剪分解的标记以消除空白。从标签表中获取TagID,如果为空(意味着标签不存在),则创建它。将每个TagID添加到标签数组中,最后将文章模型与标签数组同步。

public function scopeAttach($query, $model, $tags)
{
    $returnTags = array();
    foreach (explode(',', $tags) as $tag)
    {
        $tag = trim(Str::slug($tag));
        if ($tag != '')
        {
            $tagID = Tag::where('name', '=', $tag)->pluck('id');
            if (empty($tagID))
            {
                $tagNew = new Tag;
                $tagNew->name = $tag;
                $tagNew->save();
                $tagID = $tagNew->id;
            }
            $returnTags[] = $tagID;
        }
    }
    $model->tags()->sync($returnTags);
}

查看演示者内爆标记函数:枚举所有标记并内爆为逗号分隔的字符串。

public function implodeTags()
{
    $returnString = null;
    foreach ($this->tags as $tag)
    {
        if (!empty($returnString)) $returnString .= ", ";
        $returnString .= $tag->name;
    }
    return $returnString;
}

创建/编辑刀片视图:首先打开新表单进行创建或绑定模型进行编辑。如果创建;显示没有值的输入字段。如果编辑;使用视图演示器中的implodeTags函数,用逗号分隔的标记列表填充文本字段。

@if (!isset($edit))
  @section('title', 'Create article')
  {{ Form::open(array('route' => 'articles.store', 'role' => 'form')) }}
@else
  @section('title', 'Edit article')
  {{ Form::model($article, array('method' => 'PUT', 'route' => ['articles.update', $article->id], 'role' => 'form')) }}
@endif
...
<div class="form-group @if ($errors->has('tags')) has-error @endif">
    {{ Form::label('tags', 'Tags') }}
    @if(!isset($article))
        {{ Form::text('tags', null, array('class' => 'form-control')) }}
    @else
        {{ Form::text('tags', $article->present()->implodeTags, array('class' => 'form-control')) }}
    @endif
    @if ($errors->has('tags')) <p class="help-block">{{ $errors->first('tags') }}</p> @endif
</div>
...

显然,create/edit视图包含的内容不止这些,但这些都是与标记实现相关的部分。