Laravel多对多关系问题

时间:2014-09-17 06:16:17

标签: php mysql laravel laravel-4

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

  1. 在逗号之前输入的第一个值,仅插入数据库。我认为因为在关系表中只插入一条记录。
  2. 在编辑帖子中,显示为json结构的类别
  3. 我为多对多关系设置了一个数据库。

      

    帖子,类别和类别_post

    创建了一个表单来添加/编辑帖子

    <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');
        }
    

    有人请帮助我解决这个问题。

1 个答案:

答案 0 :(得分:3)

这样做的日子要容易得多。这是我如何存储我的文章,标签可以用逗号分隔。

文章控制器存储功能:首先创建文章对象,将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');
}

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

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);
}

View presenter implode tags功能:枚举所有代码并内嵌到逗号分隔的字符串。

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>

...

显然,创建/编辑视图包含的内容多于此,但这些是与标记实现相关的部分。