4

我有 2 个模型,联系人和电子邮件。任何联系人都可能有多个电子邮件地址,因此我在模型中创建了一对多关系:

class Contact extends Eloquent {

    protected $guarded = array();

    public static $rules = array(
        'first_name' => 'required',
        'last_name' => 'required'
    );

    public function emails() {
        return $this->hasMany('Email');
    }

}

class Email extends Eloquent {

    public function emails() {
        return $this->belongsTo('Contact');
    }

}

希望到目前为止我在正确的轨道上......

我已经为 Contact 模型使用了 Jeff Way 的脚手架,所以我在控制器中有这个更新方法:

public function update($id)
{
    $input = array_except(Input::all(), '_method');
    $validation = Validator::make($input, Contact::$rules);

    if ($validation->passes())
    {
        $contact = $this->contact->find($id);
        $contact->update($input);

        return Redirect::route('contacts.show', $id);
    }

    return Redirect::route('contacts.edit', $id)
        ->withInput()
        ->withErrors($validation)
        ->with('message', 'There were validation errors.');
}

此外,我修改了编辑视图以显示与联系人关联的所有电子邮件,然后添加一个额外的空白输入以添加新的:

@foreach($emails as $key => $email)
    <li>
        {{ Form::label('email', 'Email '.$key.':') }}
        {{ Form::text('email'.$email->id, $email->email) }}
    </li>
    @if(count($emails)==$key+1)
    <li>
        {{ Form::label('email', 'Email '.($key+1).':') }}
        {{ Form::text('email'.($email->id+1)) }}
    </li>
    @endif
@endforeach

现在,我不知道如何修改更新方法以更新电子邮件(如果已修改)并添加新电子邮件(如果已输入)。如果有人能指出我正确的方向,我将不胜感激 - 谢谢!

4

1 回答 1

4

这个问题的答案不一定是 Laravel 特定的答案。

无论如何,您需要处理将联系人的电子邮件与表单中提交的内容同步:

两种战术:

  1. 删除与该联系人关联的所有电子邮件。然后根据表单中的内容创建新电子邮件。这样,您总是在插入新电子邮件。
  2. 获取与联系人关联的所有电子邮件。遍历它们。如果提交的电子邮件的 ID(来自表单)与现有电子邮件匹配,请更新该电子邮件地址。如果电子邮件是新的(没有与之关联的 ID),请创建一个新电子邮件。此选项可能需要嵌套循环,并且在技术上应该不赞成 - 但是,对于少量电子邮件,这不是什么大问题。

现在,要获得 Laravel(4)-specific

Eloquent 有一种方便的sync()方法来处理更新关系 - 但是,我相信它只适用于多对多关系,因此依赖于“数据透视表”。

Eloquent 也有一个push()方法,但由于我还没有玩过它,我不确定它是在幕后“同步”相关电子邮件还是只是添加新的关系。这是你最好的选择。

我向 Laravel 发了推文问这个问题,希望能看到答案:https ://twitter.com/fideloper/status/353303438664278018

对于选项 1:

首先,将所有电子邮件文本字段(无论是现有的还是新的)重命名为email[]. 我们不会关心他们的 ID,因为他们会被删除。

@foreach($emails as $key => $email)
    <li>
        {{ Form::label('email', 'Email:') }}
        {{ Form::text('email[]', $email->email) }}
    </li>
@endforeach
    <!-- No need to have this in PHP logic - always give option to add new emails -->
    <!-- I'm also assuming you can name multiple new emails, perhaps with some JS -->
    <li>
        {{ Form::label('email', 'New Email:') }}
        {{ Form::text('email[]' }}
    </li>

小提示:您可能需要注意文本字段的 ID,可能需要使用$key变量,以便标签for=""属性与正确的文本字段匹配。我会把它留给你。

然后,在 PHP 中,您将删除与 $contact 关联的所有电子邮件,然后像新的一样创建它们。

// Delete all related emails
$contact->emails()->delete(); // I think this works. Otherwise do a manual query or loop through email email and `->delete()` them.

// Create new ones
foreach( Input::get("emails") as $email )
{
    $newEmail = new Email;
    $newEmail->email = $email;
    $contact->emails()->save($email);
}

对于选项 2:

您会知道是否存在新电子邮件,因为它们没有与表单数据相关联的 ID。我会将输入更改为电子邮件数组,因此更容易循环浏览它们:

@foreach($emails as $key => $email)
    <li>
        {{ Form::label('email', 'Email '.$key.':') }}
        <!-- Notice this is an array now: -->
        {{ Form::text('email['.$email->id.']', $email->email) }}
    </li>
@endforeach
    <!-- No need to have this in PHP logic - always give option to add new emails -->
    <!-- I'm also assuming you can name multiple new emails, perhaps with some JS -->
    <li>
        {{ Form::label('newemail', 'New Email:') }}
        {{ Form::text('newemail[]' }}
    </li>

然后在您的 PHP 中,对于新电子邮件:

foreach( Input::get('newemail') as $email)
{
    $newEmail = new Email();
    $newEmail->email = $email;
    $contact->emails()->save( $newEmail );
}

对于“非新”电子邮件,Input::get('email')在我上面的示例中,您可能需要获取与联系人($currentEmails = $contact->emails())关联的当前电子邮件,并在 foreach 循环中根据需要更新它们(此处未写出)。

这样的事情应该让你开始......

于 2013-07-06T00:27:27.353 回答