P
Let's see what we can do here.Your code in general is fine. But what you need is to build the structure you want.The final document you submit is a grouping of activities under the keys of tipoId and documento.We can face the problem in two ways. The first would be to go through the results and generate an array where the key is $tipoId-$documento and save a list of activities.
Once this was done, we'd go through the list again to give it the final format.The other option is to do everything on a single tour... and how we came to play is what we'll use.But first we have to explain the base. Let's use array_reduce as its name well indicates, this function reduces an array (list) of objects to a single object.The clearest example would be:var_dump(array_reduce(array(1,2,3,4), function($acc, $item) { $acc += $item; return $acc; }, 0));
int(10)
array_reduce receives 3 parameters:the array on which we want to operateThe role to be appliedAnd the initial valueThe function to apply receives 2 variables, the first one is an accumulator and the second one is an array item.So the function will be called once with each number in the example.
And $acc the first time you will have the initial value we have assigned to you (0) and in the following executions you will have the value we return in the same functionSo this will be the call list for the example:n1; $acc = 0; $item = 1n2; $acc = 1; $item = 2n3; $acc = 3; $item = 3n4; $acc = 6; $item = 4result: 10There is an important detail in array_reduce And it's just that nothing forces us to return the same object... well we could match the numbers to return the string. 1234.Back to our problem, in my case I assume that the data is already in an array:$db_data = [
array(
"tipoId" => "CC",
"documento" => "123123",
"idActividad" => "1",
"actividad" => "Solicitud semestral",
"fechaSolicitud" => "01/06/2020",
"estadodatos" => "0"
),
array(
"tipoId" => "CC",
"documento" => "123123",
"idActividad" => "2",
"actividad" => "Solicitud adicional",
"fechaSolicitud" => "01/06/2020",
"estadodatos" => "0"
),
array(
"tipoId" => "CD",
"documento" => "12",
"idActividad" => "2",
"actividad" => "Solicitud adicional",
"fechaSolicitud" => "01/06/2020",
"estadodatos" => "0"
)
];
But in your case you will have to read them from the set result as you already do.Let's start with the simplest implementation that can occur to us:$grouped = array_reduce($db_data, function($acc, $item) {
$acc[] = array(
"tipoId" => $item["tipoId"],
"documento" => $item["documento"],
"actividades" => [
array("idActividad" => $item["idActividad"])
]
);
return $acc;
}, array());
In this example we have converted DB data into a list of records where we have the tipoId and documento in the root and inside a list of actividades. However, we will soon realize that we have several tickets for the same pair tipoId and documento.Note that in this particular case we are not doing anything special with array_reduce We could use array_map and we would have the same result. .Now what we need is to check if there's already an entry in $acc for the set of keys we have and if it exists we want to add an entry in actividades in case there is no new registration.To find out if there is already a record with our set of keys we can go all the way array until I find him. But since today is a special day and I don't know how many records we're talking about, we're going to optimize the function so we don't have to search.So we'll change our object $acc from a simple array to a slightly more complex object, the definition will be: array("result" => [], "seen" => array())In result We will have the final result and seen is a key/value array where the key is our set of keys and the value is the position where it is located resultMaybe it's a little clearer with the code.$grouped = array_reduce($db_data, function($acc, $item) {
$key = $item["tipoId"] . "-" . $item["documento"];
if (!array_key_exists($key, $acc["seen"])) {
array_push($acc["result"], array(
"tipoId" => $item["tipoId"],
"documento" => $item["documento"],
"actividades" => [
array("idActividad" => $item["idActividad"])
])
);
$acc["seen"][$key] = count($acc["result"]) - 1;
} else {
array_push($acc["result"][$acc["seen"][$key]]["actividades"], array("idActividad" => $item["idActividad"]));
}
return $acc;
}, array("result" => [], "seen" => array()));
How we see the method changed a little. The first thing is that we generate a $key with the pair of keys.
Then we checked in. $acc["seen"] If it's key, we've seen it before.
In case it is new, we create the full entrance and add the position in which it is located.
If it is not a new entry the only thing we want to do is add the activity. And since in seen We have the position of the array we can do it easily.The result isarray(2) {
'result' =>
array(2) {
[0] =>
array(3) {
'tipoId' =>
string(2) "CC"
'documento' =>
string(6) "123123"
'actividades' =>
array(2) {
...
}
}
[1] =>
array(3) {
'tipoId' =>
string(2) "CD"
'documento' =>
string(2) "12"
'actividades' =>
array(1) {
...
}
}
}
'seen' =>
array(2) {
'CC-123123' =>
int(0)
'CD-12' =>
int(1)
}
}