【问题标题】:Array of objects returns same values对象数组返回相同的值
【发布时间】:2017-07-17 03:12:18
【问题描述】:

我使用此函数返回用户及其角色和组。

我想返回具有正确索引的对象数组,这就是我创建 $index 计数器的原因。

这里的问题是,如果一个用户有超过 1 个组,我会得到重复的用户。

例如,如果我有一个用户有 3 个组,我将获得该用户 3 次。

如何避免重复用户?

我知道我需要以某种方式检查该用户是否已经存在,就像我检查了角色一样,但我不确定在哪里。

如果我将 users['$index'] 替换为 users['$id'] 则此代码将起作用,但这样我将无法获得具有正确索引的数组,而这正是我所需要的。

    $stmt = $mysqli->prepare("
    SELECT u.id
         , u.firstName
         , u.lastName
         , u.email
         , u.phoneNumber
         , u.address
         , u.birthDate
         , ur.roleName
         , cg.id
         , cg.name 
      FROM users as u 
      LEFT
      JOIN user_role as ur 
         ON u.id = ur.userId 
      LEFT 
      JOIN user_group as ug 
         on ug.userId = u.id 
      LEFT 
      JOIN control_group as cg 
         on cg.id = ug.groupId 
     WHERE u.id != ?");
    $stmt->bind_param("i", $_SESSION["id"]);
    $stmt->execute();
    $stmt->bind_result($id, $firstName, $lastName, $email, $phoneNumber, 
        $address, $birthDate, $roleName, $groupId, $groupName);
    $users = array();

    $index = 0;

    while ($stmt->fetch()) {
        if (empty($users[$index])) {
            $users[$index] = array(
                'id' => $id,
                'firstName' => $firstName,
                'lastName' => $lastName,
                'email' => $email,
                'phoneNumber' => $phoneNumber,
                'address' => $address,
                'birthDate' => $birthDate,
                'roles' => array(),
                'groups' => array()
            );
        }
        if ($roleName) {
            $found = false;
            foreach ($users[$index]['roles'] as $role) {
                if($role['roleName'] == $roleName){
                    $found = true;
                    break;
                }
            }
            if($found == false)
                $users[$index]['roles'][] = array(
                    'roleName' => $roleName
                );
         }

        if ($groupId) {
            $found = false;
            foreach ($users[$index]['groups'] as $group) {
                if($group['groupName'] == $groupName){
                    $found = true;
                    break;
                }
            }
            if($found == false)
                $users[$index]['groups'][] = array(
                    'groupName' => $groupName
                );
         }
         $index++;
    }

    $stmt->close();
    $mysqli->close();
    echo json_encode($users);

所以基本上我希望这样的对象

{  
      "id":2,
      "firstName":"Jon",
      "lastName":"Doe",
      "email":"jon.doe@email.com",
      "phoneNumber":"0621-123-444",
      "address":"Address 12a",
      "birthDate":"1976-01-01",
      "roles":['list of role objects'],
      "groups":['list of group objects']
   }

我也不确定我是否以正确的方式生成对象,我想知道是否有人可以告诉我什么是正确的方法以及如何正确生成像这样的对象。

【问题讨论】:

  • 你能分享一下输出吗?
  • 我得到这样的输出paste.ofcode.org/4irsgF4s4qcnerArP29NfA,你可以看到用户 Mark 有 2 个组,这就是他被显示 2 次的原因......
  • @SuperMario'sYoshi 来自您的查询 r 您正在获取一个或多个用户的数据....您的意思是它为一个用户返回 3 行...?
  • 我正在为许多用户获取数据,因此有可能包含许多组和角色的用户列表,我期待这样的回复 paste.ofcode.org/38W4uJDB3hPKsthh8aVdFSx ,唯一的问题是你可以看到我将用户 ID 作为索引,但我不想将用户 ID 作为索引,我想要从 0 开始的项目
  • $res = []; foreach($users as $user) { $res[] = $user; } 回声 json_encode($res);您在上面链接中显示的输出正在 $users 中考虑它,并且在您对上述代码进行逻辑执行之后,$res 将是您想要的结果

标签: php mysql arrays json


【解决方案1】:

在我看来,一旦您使用联接获得用户和数据库组,您就可以为同一个用户拥有多个索引,并且您无法改变这一事实。

所以,您有两个选择。 - 可以使用 user_id 并统一数组中的组和角色 - 或者您可以使用 user_id 代替索引,并为用户构建一个索引列表,就像您使用角色列表一样

但如果你真的需要知道你在数据库中获得的每个用户的索引,你只需要这样做。

我需要了解上下文或用户故事才能有更准确的想法

好的,我试试这样的:

$index = 0;
$temp_index = 0;
$user_index =[]
while ($stmt->fetch()) {

    if (empty($user_index[$id])){
        $user_index[$id] = $index;
    }else{
        $temp_index = $index;
        $index = $user_index[$id];
    }   

    if (empty($users[$index])) {        
        $users[$index] = array(
            'id' => $id,
            'firstName' => $firstName,
            'lastName' => $lastName,
            'email' => $email,
            'phoneNumber' => $phoneNumber,
            'address' => $address,
            'birthDate' => $birthDate,
            'roles' => array(),
            'groups' => array()
        );
    }
    if ($roleName) {
        $found = false;
        foreach ($users[$index]['roles'] as $role) {
            if($role['roleName'] == $roleName){
                $found = true;
                break;
            }
        }
        if($found == false)
            $users[$index]['roles'][] = array(
                'roleName' => $roleName
            );
     }

    if ($groupId) {
        $found = false;
        foreach ($users[$index]['groups'] as $group) {
            if($group['groupName'] == $groupName){
                $found = true;
                break;
            }
        }
        if($found == false)
            $users[$index]['groups'][] = array(
                'groupName' => $groupName
            );
     }
     if ($tempo_index != 0){
         $index = $temp_index;
         $temp_index = 0;
     }else{
        $index ++;
        $temp_index = 0;
}

【讨论】:

  • 我不确定我是否完全理解你的意思,但基本上我只想返回具有正确索引的用户列表,例如,如果我有 4 个用户,我想返回数组从索引 0 开始,如果我使用用户 ID,我将获得对象数组但没有正确的索引,而是将 userId 作为索引,我不想要那个。
  • 不使用索引只使用$users[]进入用户数组
  • 嗯,我不确定我该怎么做,因为用户有多个角色和组,我需要将它提取到用户对象中?
  • 基本上,索引是您在数据库中提取的行数。当您加入两个表(如用户和组)时,通常数据库将为每个角色或每个组返回一个以上的用户实例。因为每个用户都有不止一个角色或组,所以,就像用户出现不止一次的乘法一样。一个用户 X 一个组 = 一行,一个用户 X 两个组 = 两行等等 我只是不明白为什么你需要索引,如果你显然想要知道 ID 为 349 的用户,例如, 可以访问某些资源或页面。
  • 我只想拥有正确的数组,例如,如果我返回 5 个用户,我想获得从 0 开始的数组响应,而不是从用户 id 开始。
【解决方案2】:

如果可以选择执行多个查询,您可以先获取所有用户,然后为每个用户获取角色和组。

$user_stmt = $mysqli->prepare("SELECT id, firstName, lastName, email, phoneNumber, address, birthDate FROM users WHERE id != ?");
$user_stmt->bind_param("i", $_SESSION["id"]);
$user_stmt->execute();
$user_stmt->bind_result($id, $firstName, $lastName, $email, $phoneNumber, $address, $birthDate);

$role_stmt = $mysqli->prepare("SELECT roleName FROM user_role WHERE userId = ?");
$group_stmt = ...

$users = array();

while($user_stmt->fetch())
{
    $role_stmt->bind_param("i", $id);
    $role_stmt->execute();
    $role_stmt->bind_result($roleName);

    $roles = array();

    while($role_stmt->fetch())
    {
        $roles[] = array("roleName" => $roleName);
    }

    $groups = array();

    // Same as for roles

    $users[] = array(
            'id' => $id,
            'firstName' => $firstName,
            'lastName' => $lastName,
            'email' => $email,
            'phoneNumber' => $phoneNumber,
            'address' => $address,
            'birthDate' => $birthDate,
            'roles' => $roles,
            'groups' => $groups
        );
    }
}

$user_stmt->close();
$role_stmt->close();
$group_stmt->close();
$mysqli->close();
echo json_encode($users);

【讨论】:

  • 我考虑过,但就性能而言,解决方案有多好,这样我有一个 DB 调用,我需要 2 或 3 个取决于对象的外观。所以我的主要问题是,有一个带有连接的大查询还是多个简单查询更好?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-10
  • 2017-11-03
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
相关资源
最近更新 更多