sfDoctrineForm - 我如何检查嵌入表单中的对象是否存在并将其与新的父对象相关联,而不是创建一个新对象?

发布于 2024-10-21 00:20:41 字数 1705 浏览 2 评论 0原文

我正在制作一个用户注册表,其中涉及 3 个不同的对象:用户、成员个人资料和成员组织。我试图将所有这些嵌入到一个注册表单中,例如“用户>”会员>学校。其基本实现与典型的 sfDoctrineForm::embedRealtion 过程配合得很好。

问题是组织在其 member_number 上有一个唯一的索引,唯一提供的值不会出现在数据库中的是当该用户是第一个从其组织注册的人时。因此,在这种情况下,我们将收到验证错误(或者如果我们关闭验证,则会出现关键约束违规)。

我想要发生的是,我检查数据库中是否存在具有相同 member_number 的 MemberOrganization(在前/后验证器中或在 updateObject 中或在任何适当的地方)。如果成员编号已经存在,那么我想将新的 MemberProfile 与该现有组织相关联,而不是将其链接到提交的新组织,从而丢弃该组织的所有新值。

我尝试通过验证修改组织表单中的对象,但这总是会导致来自配置文件的 organization_id 约束违规:

$object = $this->getObject();
$table = $object->getTable();
$existing = $table->findOneByMemberNumber($values['member_number']);
if($existing)
{
  $members = clone $object->Members;
  $object->assignIdentifier($existing->identifier());
  $object->fromArray($existing->toArray(false), false);

  foreach($members as $member)
  {
    $member->link($object);
  }

  $values = $object->toArray(false); // return only the direct values
}

return $values;

架构如下所示:

User:
  columns:
  username: {type: string(100)}
  email: {type: string(255), unique: true}

MemberProfile:
  columns:
    # some none authentication related user details
    organization_id: {type: integer, notull: true}
    user_id: {type: integer, notnull: true}
  relations:
    User:
      local: user_id
      type: one
      foreign: id
      foreignType: one
    MemberOrganization:
      local: orgainization_id
      type: one
      foreign: id
      foreignType: many
      foreignAlias: Members

MemberOrganization:
  columns:
    membership_number: {type: string(255), unique: true}
    # other organization data

Im working on a user registration form that involves 3 different objects, The user, member profile, and member organization. Im trying to embed all these into a single registration form like User > Member > School. The basic implementation of this works just fine with the typical sfDoctrineForm::embedRealtion procedure.

The problem is the organization has a unique index on its member_number, the only time the the supplied value for this wont be in the database is when that user is first person to sign up from their organization. So in this case we will get a vlaidation error (or a key constraint violation if we turn the validation off).

What I want to happen instead, is that i check for the existence of the MemberOrganization with the same member_number in the database (either in a pre/post validator or in updateObject or wherever is appropriate). If it the member number already exists then i want to relate the new MemberProfile to this existing organization instead of linking it to the new one that was submitted, throwing out all the new values for that organization.

Ive tried modifying the object in the organization form via validation but this always results in a organization_id constraint violation coming from the profile:

$object = $this->getObject();
$table = $object->getTable();
$existing = $table->findOneByMemberNumber($values['member_number']);
if($existing)
{
  $members = clone $object->Members;
  $object->assignIdentifier($existing->identifier());
  $object->fromArray($existing->toArray(false), false);

  foreach($members as $member)
  {
    $member->link($object);
  }

  $values = $object->toArray(false); // return only the direct values
}

return $values;

The schema looks something like this:

User:
  columns:
  username: {type: string(100)}
  email: {type: string(255), unique: true}

MemberProfile:
  columns:
    # some none authentication related user details
    organization_id: {type: integer, notull: true}
    user_id: {type: integer, notnull: true}
  relations:
    User:
      local: user_id
      type: one
      foreign: id
      foreignType: one
    MemberOrganization:
      local: orgainization_id
      type: one
      foreign: id
      foreignType: many
      foreignAlias: Members

MemberOrganization:
  columns:
    membership_number: {type: string(255), unique: true}
    # other organization data

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鹿童谣 2024-10-28 00:20:41

所以我最终做的是重写顶级表单(用户表单)上的 bind 。在此方法中,我检查组织是否存在,如果存在,我将其附加到成员配置文件对象,然后重新嵌入所有子表单。

理想情况下,我实际上会在成员表单中执行此操作,但由于这些值仅绑定在顶级表单上,然后只是级联错误模式进行验证,这似乎是行不通的。似乎需要完全重新嵌入才能使对象关联正确。

一些示例代码(在发出查询之前减去会员号码上的一些清理代码):

  public function linkOrganizationIfExists(array $orgValues)
  {
    $defaultOrg = $this->embeddedForms['member_profile']->embeddedForms['organization']->getObject();
    $table = $defaultOrg->getTable();

    if(isset($orgValues['member_number']) 
      && ($existingOrg = $table->findOneByMemberNumber($orgValues['member_number'])))
    {
      $user = $this->getObject();
      $profile = $user->getMemberProfile();
      $profile->Organization = $existingOrg;

      // prepare the current values from the db to return
      $orgValues = array_merge($orgValues, array_intersect_key($existingOrg->toArray(false), $orgValues));

      $this->embedRelation('MemberProfile as member_profile', 'MemberProfileRegisttrationForm');
    }

    return $orgValues;
  }

  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    if(isset($taintedValues['member_profile']['organization']))
    {
      $taintedValues['member_profile']['organization'] = $this->linkOrganizationIfExists($taintedValues['member_profile']['organization']);
    }

    parent::bind($taintedValues, $taintedFiles);
  } 

So what i ended up doing was overriding bind on the top level form (the one for the User). In this method i check for the existence of the Orgainization and if it exists i attach it to the Member Profile object and then re-embed all the subforms.

Ideally i would actually do this in the Member form but since the values are only bound at the top level form and then just cascade through the error schema for validation this seems to be a no go. Complete re-embedding seems to be required to get the object associations correct.

Some sample code (less some sanitizing code on the member number before issuing the query):

  public function linkOrganizationIfExists(array $orgValues)
  {
    $defaultOrg = $this->embeddedForms['member_profile']->embeddedForms['organization']->getObject();
    $table = $defaultOrg->getTable();

    if(isset($orgValues['member_number']) 
      && ($existingOrg = $table->findOneByMemberNumber($orgValues['member_number'])))
    {
      $user = $this->getObject();
      $profile = $user->getMemberProfile();
      $profile->Organization = $existingOrg;

      // prepare the current values from the db to return
      $orgValues = array_merge($orgValues, array_intersect_key($existingOrg->toArray(false), $orgValues));

      $this->embedRelation('MemberProfile as member_profile', 'MemberProfileRegisttrationForm');
    }

    return $orgValues;
  }

  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    if(isset($taintedValues['member_profile']['organization']))
    {
      $taintedValues['member_profile']['organization'] = $this->linkOrganizationIfExists($taintedValues['member_profile']['organization']);
    }

    parent::bind($taintedValues, $taintedFiles);
  } 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文