Люмен / Laravel - Почему данные автоматически вставляются в таблицу соединений? - PullRequest
1 голос
/ 31 января 2020

У меня есть 3 таблицы:

Ad_users

Ad_groups

Ad_usersxad_groups

Ad_usersxad_groups - это таблица соединений для двух других. Сейчас я работаю в проекте lumen / laravel, и мы используем красноречивую модель. У меня есть следующие модели для таблицы ad_users и таблицы ad_groups:

ad_user. php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Ad_user extends Model
{
  /**
   * The attributes that are mass assignable.
   *
   * @var array
   */
  protected $fillable = [
    'common_name',
    'location',
    'description',
    'postalcode',
    'physical_delivery_office_name',
    'telephone_number',
    'initials',
    'street_address'
  ];

  /**
   * Hides pivot in return queries.
   *
   * @var array
   */
  protected $hidden = [
    'pivot'
  ];

  /**
   * Many-To-Many relationship.
   */
  public function ad_groups()
  {
    return $this->belongsToMany('App\Ad_group', 'Ad_usersxad_groups');
  }
}

ad_group. php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Ad_group extends Model
{
  /**
   * The attributes that are mass assignable.
   *
   * @var array
   */
  protected $fillable = [
    'name'
  ];

  /**
   * Hides pivot from return queries.
   *
   * @var array
   */
  protected $hidden = [
    'pivot'
  ];

  /**
   * Many-To-Many relationshipl.
   */
  public function ad_users()
  {
    return $this->belongsToMany('App\Ad_user', 'Ad_usersxad_groups');
  }

  public function extensiontables()
  {
    return $this->belongsToMany('App\extensiontables_registry', 'extensiontables_registryxad_groups');
  }

}

Данные внутри ad_groups и ad_user в основном происходит от нашего LDAP-сервера. Поэтому, когда пользователь входит в систему, промежуточное программное обеспечение устанавливает соединение с ldap и извлекает данные пользователей. Затем данные синхронизируются с нашей локальной базой данных, то есть они либо обновляются, либо создаются. Просто для полноты, вот код, который выполняется при доступе пользователя к маршруту входа в систему:

AuthController. php

  public function login(Request $request)
  {
    $ldap = new LDAP;
    $jwt = new JWTAuth;
    $response = new Response;

    $this->validate($request, [
      'username' => 'string|required',
      'password' => 'string|required'
    ]);

    if(!$ldap->authenticateUser($request->username, $request->password))
    {
      return response()->json([
        'error' => 'User could not be authenticated'
      ], 401);
    }

    /**
     * Synchronizes the user's data from ldap with the local db.
     * Used for better performance and mitigating network overhead.
    */
    $ldap->syncData($request->username);

    $response->header('Authorization', 'Bearer '.$jwt->generateJWT($request->username));
    return $response;
  }

Здесь важной частью является $ldap->syncData($request->username);. Он вызывает LDAP. php, где выполняется этот код:

LDAP. php

  public function syncData($username)
  {
    try
    {
      if(!$this->connect())
      {
        $this->disconnect();
        return false;
      }

      $userData = $this->getUser($username, [
        'cn',
        'l',
        'description',
        'postalcode',
        'physicaldeliveryofficename',
        'telephonenumber',
        'initials',
        'memberof',
        'streetaddress'
      ]);

      $user = Ad_user::updateOrCreate(
        ['common_name' => $userData['cn']],
        [
          'common_name' => $userData['cn'],
          'location' => $userData['l'],
          'description' => $userData['description'],
          'postalcode' => $userData['postalcode'],
          'physical_delivery_office_name' => $userData['physicaldeliveryofficename'],
          'telephone_number' => $userData['telephonenumber'],
          'initials' => $userData['initials'],
          'street_address' => $userData['streetaddress']
        ]
      );

      // Remove everything but the user roles
      foreach($userData['memberof'] as $key=>$role)
      {
        preg_match("/^CN=.+?,/", $role, $role);
        $userData['memberof'][$key] = substr($role[0], 3, -1);
      }

      // Loop through every role because updateOrCreate cant handle arrays
      foreach($userData['memberof'] as $value)
      {
        $roles[] = Ad_group::updateOrCreate(
          ['name' => $value],
          ['name' => $value]
        )->id;
      }

      // Syncs current roles received from ldap with the local db
      $user->ad_groups()->sync($roles);
    }
    catch(\Exception $e)
    {
      $error =  array("exception_code" => $e->getCode(), "error_message" => $e->getMessage());

      Log::error($error);
      return false;
    }
    finally
    {
      $this->disconnect();
    }
  }

Я обнаружил, что всякий раз, когда пользователь входит в систему, записи вставляются в соединительный стол. КАЖДЫЙ раз, то есть создается много избыточных данных. Я предполагаю, что важная часть кода, вызывающая эту проблему, такова:

$user->ad_groups()->sync($roles)

После 7 входов одного и того же пользователя, например, таблица соединений выглядит следующим образом:

select * from ad_usersxad_groups;
+------------+-------------+------------+------------+
| Ad_user_id | Ad_group_id | created_at | updated_at |
+------------+-------------+------------+------------+
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
|          1 |           1 | NULL       | NULL       |
|          1 |           2 | NULL       | NULL       |
|          1 |           3 | NULL       | NULL       |
|          1 |           4 | NULL       | NULL       |
|          1 |           5 | NULL       | NULL       |
|          1 |           6 | NULL       | NULL       |
|          1 |           7 | NULL       | NULL       |
|          1 |           8 | NULL       | NULL       |
|          1 |           9 | NULL       | NULL       |
|          1 |          10 | NULL       | NULL       |
|          1 |          11 | NULL       | NULL       |
|          1 |          12 | NULL       | NULL       |
+------------+-------------+------------+------------+

This не является ни желательным, ни приемлемым, но так как я довольно плохо знаком с lumen / laravel, а также с php LDAP API, используемым здесь, я действительно почти не представляю, что может вызвать такое поведение. По крайней мере, я довольно убедитесь, что MySQL / MariaDB не влияет на это поведение, так как FOREIGN KEY не имеет привязанных к ним CASCADE.

Интересно, сделал ли я что-то неправильно в определении моделей, но я бы не знал, что такое xD. Некоторая помощь от вас будет очень признательна ^^

РЕДАКТИРОВАТЬ: Журнал показал это для массива ролей:

[2020-01-31 08:57:27] local.INFO: array (
  0 => 1,
  1 => 2,
  2 => 3,
  3 => 4,
  4 => 5,
  5 => 6,
  6 => 7,
  7 => 8,
  8 => 9,
  9 => 10,
  10 => 11,
  11 => 12,
)  

Просто для справки, вот внешние ключи БД, конечно, включая те, которые относятся к этой проблеме. Я почти уверен, что настроил их правильно, но, может быть, я просто слепой, вот они:

| TABLE_NAME                         | COLUMN_NAME                 | CONSTRAINT_NAME                      | REFERENCED_TABLE_NAME    | REFERENCED_COLUMN_NAME |
+------------------------------------+-----------------------------+--------------------------------------+--------------------------+------------------------+
| ad_usersxad_groups                 | Ad_user_id                  | fk_ad_groupxad_user                  | ad_users                 | id                     |
| ad_usersxad_groups                 | Ad_group_id                 | fk_ad_userxad_group                  | ad_groups                | id                     |
| extensiontables_registryxad_groups | ad_group_id                 | fk_ad_groupxextensiontables_registry | ad_groups                | id                     |
| extensiontables_registryxad_groups | extensiontables_registry_id | fk_extensiontables_registryxad_group | extensiontables_registry | id                     |
| extensiontable_itc                 | coretable_id                | fk_extensiontable_itc_coretable      | coretable                | id                     |
| inaccessibletable                  | coretable_id                | fk_inaccessibletable_coretable       | coretable                | id                     |
+------------------------------------+-----------------------------+--------------------------------------+--------------------------+------------------------+

1 Ответ

1 голос
/ 31 января 2020

Из того, что я вижу, хорошо выглядят как выгруженный массив, так и код.

Я не эксперт по Laravel, но я бы посоветовал попытаться более точно указать c при определении ваших отношений, чтобы увидеть, это может решить вашу проблему.

В вашей Ad_user модели измените:

public function ad_groups()
{
    return $this->belongsToMany('App\Ad_group', 'Ad_usersxad_groups');
}

на:

public function ad_groups()
{
    return $this->belongsToMany('App\Ad_group', 'Ad_usersxad_groups', 'Ad_user_id', 'Ad_group_id');
}

И в вашей Ad_group модели изменить:

public function ad_users()
{
    return $this->belongsToMany('App\Ad_user', 'Ad_usersxad_groups');
}

на:

public function ad_users()
{
    return $this->belongsToMany('App\Ad_user', 'Ad_usersxad_groups', 'Ad_group_id', 'Ad_user_id');
}
...