Crear una tabla a partir de un loop foreach con orden

publicado por: Anonymous

Necesito crear una tabla donde los numeros de semana sean las columnas y los empleados sean la primer columna, de esta forma:

introducir la descripción de la imagen aquí

Pero apartir de un array en php como el siguiente:

 /**
     * [$key Año]
     * [$key2 Semana]
     * [$key3 Empleado]
     * [$value3 Total horas]
     */

        echo '<table class="table table-condensed table-hover">';
    foreach ($weeksT as $key => $value) {
        foreach ($value as $key2 => $value2) {
                echo '<td>'.$key2.'</td>';
            foreach ($value2 as $key3 => $value3) {
                //echo $key2 . ' | ' . getNameEmp($key3) . ' - ' . $value3 . '<br>';
                echo '<tr>';
                    echo '<td>'.$key3.'</td>';
                echo '</tr>';
            }
        }
    }
        echo '</table>';`

Alguna idea de como acomodarlo?

Editado: contenido del arreglo:

Array
(
[2018] => Array
    (
        [08] => Array
            (
                [40] => 68
            )

        [09] => Array
            (
                [11] => 50
                [18] => 60
                [28] => 50
                [32] => 68
                [34] => 60
            )

        [10] => Array
            (
                [11] => 60
                [18] => 60
                [24] => 58
                [28] => 60
                [31] => 60
                [32] => 60
                [37] => 60
                [38] => 48
            )

        [11] => Array
            (
                [11] => 58
                [18] => 35
                [24] => 68
                [28] => 35
                [32] => 68
                [37] => 58
                [38] => 50
                [43] => 34.25
            )

solución

Si entendí bien tu estructura de datos, aquí tienes una posible solución.

Use dos años y genero una tabla por cada año.

Código con una posible solución

<style>
    td {
        border: 1px solid grey;
        padding: 5px;
    }
</style>

<?php

/**
 * [$key Año]
 * [$key2 Semana]
 * [$key3 Empleado]
 * [$value3 Total horas]
 */

$arr = [
    2017 => [
        1 => [
            11 => 45,
            18 => 40,
            28 => 42,
        ],
        2 => [
            11 => 19,
            18 => 40,
            28 => 37,
        ],
        3 => [
            11 => 36,
            18 => 40,
            28 => 34,
        ],
    ],
    2018 => [
        1 => [
            11 => 41,
            18 => 35,
            28 => 42,
        ],
        2 => [
            11 => 19,
            18 => 35,
            28 => 10,
        ],
        3 => [
            11 => 36,
            18 => 35,
            28 => 38,
        ],
    ],
];

    // Según la estructura de los datos voy a generar cada fila por
    // separado y una tabla por año

    // Contando con que para cada semana estén los mismos empleados
    // Imprimo la primera fila directamente, las consecutivas
    // (id empleado / horas en cada semana) requiere más trabajo

    foreach ($arr as $year => $year_content) {
        echo '<br><p>Year: ' . $year . '</p>';

?>
    <table class="table table-condensed table-hover">
        <tr> <!-- Opens header row (weeks) -->
        <td>Employee</td>
<?php

        $employees = [];
        foreach ($year_content as $num_of_week => $week_content) {
            echo '<td>WK' . $num_of_week . '</td>';

            // Create an array with the employees' ids
            $employees = array_keys($week_content);
        }
        // Prepare array to store an array of hours for each id
        $employees = array_fill_keys($employees, []);
        // echo '<pre>'; var_dump($employees); echo '</pre><br>'; // HACK: trace


        foreach ($year_content as $week_content) {

            $pos = 0;
            foreach ($week_content as $employee_id => $hours) {
                if ($employee_id === array_keys($employees)[$pos]) {
                    $employees[$employee_id][] = $hours;
                }

                $pos ++;
            }
        }

        // echo '<pre>'; var_dump($employees); echo '</pre><br>'; // HACK: trace

        //$employees esta listo para imprimir cada fila
        foreach ($employees as $employee_id => $arr_hours) {
            echo '<tr>'; // Opens employee row
            echo '<td>emp' . $employee_id . '</td>';

            foreach ($arr_hours as $hour) {
                echo '<td>' . $hour . '</td>';
            }
            echo '</tr>'; // Closes employee row
        }

?>
        </tr> <!-- Closes header row (weeks) -->
    </table>
<?php

    } // end foreach (for year)

Resultado:

introducir la descripción de la imagen aquí

Editado: no siempre trabajan los mismos empleados en las mismas semanas.

En un sistema más realista, los empleados que van a trabajar cada semana del año no son siempre los mismos, igualmente puede haber semanas en que ningún empleado trabaja.
Entonces la tabla tendrá, probablemente, celdas vacías y una “fila de semanas” con las semanas en que se trabaja y una “columna de empleados” con los empleados que trabajan en al menos una de esas semanas, pudiendo ser asimismo varias o todas.

El resultado sería algo así, para la tabla de un determinado año:

introducir la descripción de la imagen aquí

Voy a poner un ejemplo completo (he ajustado los arrays con los datos para el nuevo supuesto):

<style>
    td {
        border: 1px solid grey;
        padding: 5px;
    }
</style>

<?php

$arr = [
    2017 => [
        1 => [
            11 => 45,
            28 => 42,
        ],
        2 => [
            28 => 37,
        ],
        5 => [
            11 => 36,
            27 => 40,
            32 => 34,
        ],
    ],
    2018 => [
        3 => [
            27 => 35,
            32 => 42,
        ],
        4 => [
            11 => 19,
            18 => 35,
            28 => 10,
        ],
    ],
];

    // Según la estructura de los datos voy a generar una tabla por año.
    // Se va a imprimir fila a fila.

    // No siempre trabajan los mismos empleados en las mismas semanas.

    // Los empleados que van a trabajar cada semana del año no son
    // siempre los mismos, igualmente puede haber semanas en que ningún
    // empleado trabaja. Entonces la tabla tendrá, probablemente,
    // celdas vacías y una "fila de semanas" con las semanas en que se
    // trabaja y una "columna de empleados" con los empleados que
    // trabajan en al menos una de esas semanas, pudiendo ser asimismo
    // varias o todas.

    // Usaremos funciones para simplificar el problema
    //

    // Requiero todas las semanas trabajadas en el año
    function getWeeks(array $year): array
    {
        return array_keys($year);
    }

    // Requiero todos los empleados que trabajan en el año
    function getEmployeeIds(array $year): array
    {
        $employee_ids = [];
        foreach ($year as $week_number => $employees_data) {

            $employee_ids =
                array_merge($employee_ids, array_keys($employees_data));
        }

        return array_unique($employee_ids);
    }


    // Usaremos funciones para imprimir los datos
    //

    function printHeaderRow(array $weeks): void
    {
        echo '<tr>';
        echo '<td>Employee</td>';
        foreach ($weeks as $week) {
            echo '<td>WK' . $week . '</td>';
        }
        echo '</tr>';
    }

    function printEmployeeRow(
        int $emp_id,
        array $weeks,
        array $data
    ): void
    {
        echo '<tr>';
        echo '<td>emp' . $emp_id . '</td>';

        // La impresión es horizontal por tanto comprobamos en cada
        // semana si hay horas para el empleado actual
        foreach ($weeks as $actual_week) {
            foreach ($data as $analized_week => $employees_data) {

                // La semana en los datos coincide con la actual:
                // comprobaremos los empleados de la semana
                if ($actual_week === $analized_week) {

                    $printed = false; // Controla si se han imprimido horas
                    foreach ($employees_data as $analized_id => $hours) {

                        // Se ha encontrado la id del empleado en los
                        // datos de la semana: imprimir horas
                        if ($emp_id === $analized_id) {
                            echo '<td>' . $hours . '</td>';
                            $printed = true;
                        }
                    }

                    // No se imprimiron horas: imprimir celda vacía
                    if (! $printed) {
                        echo '<td></td>';
                    }
                }
            }
        }
        echo '</tr>';
    }

    /**
     * Prints a trace
     *
     * @param  mixed       $content
     * @param  string|null $msg
     */
    function dx($content, string $msg=null): void
    {
        echo '<div style="border:1px solid grey;margin-bottom:10px;padding:10px">';
        if ($msg) {
            echo '<p>' . $msg . '</p>';
        }

        echo '<pre>';
        var_dump($content);
        echo '</pre>';
        echo '</div>';
    }


    // Recorre los datos e imprime una tabla para cada año
    foreach ($arr as $year => $year_data) {
        echo '<br><p>Year: ' . $year . '</p>';

?>
    <table class="table table-condensed table-hover">
<?php

        $employee_ids = getEmployeeIds($year_data);
        $weeks        = getWeeks($year_data);

        // HACK: trazas
        // dx($employee_ids, 'IDs de los empleados');
        // dx($weeks, 'Semanas en que se trabaja');

        printHeaderRow($weeks);
        foreach ($employee_ids as $employee_id) {
            printEmployeeRow($employee_id, $weeks, $year_data);
        } /**/

?>
    </table>
<?php

    } // end foreach (for year)

Resultado:

introducir la descripción de la imagen aquí

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *