PHP Kreuztabelle (Pivottable) aus 3 Tabellen

Hallo zusammen,

ich hab da mal wieder ein Problem.
Dies mal geht es um folgendes:

Ich baue momentan eine Sicherheitsüberprüfung in meiner Seite ein, die jeweils gruppenabhängige Richtlinien für Benutzer bereitstellen sollen.
An sich klappt dies auch einwandfrei und ohne Problem.

Jedoch bin ich gerade an dem Punkt angelangt, an dem ich diese Rechte gerne einfach über das Web administrieren möchte.

Unter MySQL habe ich folgende Tabellen:


  • Permissions (was darf die Gruppe: create, edit, delete etc.)
  • Resources (wo darf die Gruppe was: News, Comments etc.)
  • Roles (wer hat die Berechtigungen: Administratoren, Mods etc.)
  • resource_role_permissions (Zusammenschluß aller 3 Tabellen mit Flag "allow" (bool)).

Nun möchte ich folgende (tabellarische) Ausgabe zaubern wie im angehängten Screenshot abgebildet.

Jedoch weiß ich nicht, wie ich dies am besten via SQL/PHP abbilden soll.
Eventuell hat einer von Euch eine Idee oder hilfreiche Tips.

Vielen Dank schoneinmal!

Gruß
Insanity
 
Da ich anhand Deiner Beschreibung nicht auf die Tabellen-Struktur schliessen kann, hab ich einfach mal ein Beispiel erstellt wie ich glaube, dass Du die Daten aus der DB bekommst.

Hier mal der Code:

PHP:
/**
 * Zuerst mal ein paar Klassen für die erstellung einer HTML-Table.
 *
 */

class HTMLTable {
    
    private $data = null;
    private $rows = array();
    private $output = '';

    public function  __construct() {
        
    }

    public function __toString() {
        $this->output();
        return $this->output;
    }

    public function output() {
        $this->output.= '<table border="1">';
        foreach ($this->rows as $row) {
            $this->output.= $row->getHTML();
        }
        $this->output.= '</table>';
    }

    public function addRow($key, HTMLTableRow $row) {
        $this->rows[$key] = $row;
    }

}

class HTMLTableRow {

    private $columns = array();

    public function addColumn(HTMLTableColumn $column) {
        $this->columns[] = $column;
    }

    public function getHTML() {
        $output = '<tr>';
        foreach ($this->columns as $column) {
            $output.= $column->getHTML();
        }
        $output.= '</tr>';
        return $output;
    }
}

class HTMLTableColumn {

    private $value = null;
    private $rowspan = null;

    public function  __construct($value, $rowspan = 0) {
        $this->value = $value;
        $this->rowspan = $rowspan;
    }

    public function getHTML() {
        $output.= '<td';
        if ($this->rowspan > 0) {
            $output.= ' rowspan="' . $this->rowspan . '"';
        }
        $output.= '>';
        return $output . $this->value . '</td>';
    }
}

/**
 *
 * Hier kommen die Demo-Daten.
 *
 */
$data = array(
            'admins' => array (
                'news' => array('create' => 'true', 'edit' => 'false', 'delete' => 'false'),
                'comments' => array('create' => 'true', 'edit' => 'true', 'delete' => 'false'),
                'groups' => array('create' => 'true', 'edit' => 'true', 'delete' => 'true'),
                'messages' => array('create' => 'true', 'edit' => 'true', 'delete' => 'true'),
            ),
            'mods' => array (
                'news' => array('create' => 'false', 'edit' => 'true', 'delete' => 'false'),
                'comments' => array('create' => 'true', 'edit' => 'true', 'delete' => 'false'),
                'groups' => array('create' => 'true', 'edit' => 'true', 'delete' => 'false'),
                'messages' => array('create' => 'true', 'edit' => 'true', 'delete' => 'false'),
            ),
            'users' => array (
                'news' => array('create' => 'false', 'edit' => 'false', 'delete' => 'false'),
                'comments' => array('create' => 'false', 'edit' => 'false', 'delete' => 'false'),
                'groups' => array('create' => 'false', 'edit' => 'false', 'delete' => 'false'),
                'messages' => array('create' => 'true', 'edit' => 'true', 'delete' => 'false'),
            ),
        );

/**
 *
 * Und hier der Code wie die Tabelle zusammengebaut wird.
 *
 */

$table = new HTMLTable();
        foreach ($data as $key => $value) {
            $row = new HTMLTableRow();
            $rowspan = sizeof($value);
            $col1 = new HTMLTableColumn($key, $rowspan);
            $row->addColumn($col1);
            $cntCols = sizeof($value);
            $colKey = array_keys($value);
            for ($i = 0; $i < 1; $i++) {
                $col = new HTMLTableColumn($colKey[$i]);
                $row->addColumn($col);
                foreach ($value[$colKey[$i]] as $colValue) {
                    $col = new HTMLTableColumn($colValue);
                    $row->addColumn($col);
                }
            }
            $table->addRow($key, $row);
            for ($i = 1; $i < $cntCols; $i++) {
                $row1 = new HTMLTableRow();
                $col = new HTMLTableColumn($colKey[$i]);
                $row1->addColumn($col);
                foreach ($value[$colKey[$i]] as $colValue) {
                    $col = new HTMLTableColumn($colValue);
                    $row1->addColumn($col);
                }
                $table->addRow($key . $i, $row1);
            }
        }
        echo $table;

Der Code hat keine Fehlerüberprüfung und bei der Ausgabe fehlen die Header. Aber das ganze kannst ja selber dann noch anpassen. :wink:

Falls Du noch fragen hast dann her damit.
 
Guten Morgen,

vielen Dank für deine Mühe!
Habe deine Lösung gerade mal eingebaut, jedoch zeigt er mir nur folgendes an: http://www.pics-load.net/?v=images/FS1BD23H1Zbla.png

Btw. meine Tabellen sehen wie folgt aus:

  • Permissions


  • Resources


  • Roles


  • resource_role_permissions


Ich kann irgendwie nicht ganz nachvollziehen, wie die Ausgabe (wie sie von deiner Klasse her kommt) zustande kommt.
 
Zuletzt bearbeitet:
Also ich gehe mal davon aus, dass Du die Daten in etwa so aus der DB ziehst.

Code:
SELECT
    ro.*,
    re.*,
    p.*,
    rrp.allow
FROM
    resource_role_permissions rrp
JOIN
    roles ro
ON
    ro.ID = rrp.FK_Roles_ID
JOIN
    resources re
ON
    re.ID = rrp.FK_Resource_ID
JOIN
    permissions p
ON
    p.ID = FK_Permission_ID

Dann kannste ja danach die Daten in so eine Array-Struktur bringen wie meine Demodaten.
Du kannst ja mal ein serialized-Array mit den Daten hier posten.
 
Hallo,

also ich hab bekomme die Rechte genauso wie du es beschrieben hast.
Jedoch habe ich kleinere Verständnisprobleme, aus einem Statement dann so ein Array zusammen zu bauen.

Theoretisch benötige ich doch dafür ein 2 dimensionales Array und in den Values stehen dann true/false und die Keys sind dann dementsprechend einmal die resources und die permissions, richtig?

Ich habe mir eine Abstraktionsschicht für die Datenbank gebaut, die es mir erlaubt mit Hilfe eines Namens bestimmte Statements abzurufen.

Ich hole mir also mit
PHP:
$permissions = Model::getDataTable("GetPermissions");
das Resultset zurück.
Wie müsste ich nun fortfahren um deine Klasse damit zu füttern?
Ich müsste dann doch einfach nur mit einem foreach durch das Set laufen, oder?

Also ich brauch nicht wirklich ne direkte Lösung, sondern eher kleinere Erklärungen wie ich an das Ziel kommen könnte, da ich dies gerne selbst entwickeln würde.
 
Zuletzt bearbeitet:
Für das Beispiel brauchst du ein 3-Dimensionales-Array $arr[1][2][3].

Du nimmst Dein Result-Set und baust dir so ein Array, dieses kannst dann in die Tabelle stecken.

Beispiel:
PHP:
$arr = array();
while($resultSet->next()) {
    $row = $resultSet->getRow();
    $arr[$row['rolle']][$row['resource'][$row['permission']] = $row['allow'];
}

So bekommste das Array. Den Code zum erzeugen der Tabelle kannst ja auch in eine Klasse packen, welcher Du die Daten übergibst.
 
Okay, habs hinbekommen. Musste den Aufbau des Arrays jedoch was ändern, weil ich keine Objekte zurückbekomme von der DB sonder auch Arrays:
PHP:
foreach($permissions as $permission){
                    $arr[$permission['Description']][$permission['Ressource']][$permission['Property']] = $permission['allow'];
                }

Hab jedoch nun auch versucht die Property's heraus zubekommen in der Tabelle, so dass ich auch sehe was nun true / false ist. Aber das will mir nicht so recht gelingen.
 
Okay, habs hinbekommen. Musste den Aufbau des Arrays jedoch was ändern, weil ich keine Objekte zurückbekomme von der DB sonder auch Arrays:
PHP:
...
Hab jedoch nun auch versucht die Property's heraus zubekommen in der Tabelle, so dass ich auch sehe was nun true / false ist. Aber das will mir nicht so recht gelingen.

Welche Ausgabe bekommst den? Oder was bekommste nicht? Vielleicht kannst mal einen Screen von der Ausgabe und dem Array (print_r($arr)) machen.
 
Ich hab dir mal eine Grafik angefügt, wo du oben die Ausgabe deiner Klasse siehst und unten das array.
Leider ist es mir nicht gelungen dieses formatiert darzustellen. UAch nicht durch print_r mit <pre> zusammen.

Wie du siehst gibt es in dem Array die Keys "Create", "View" etc.
Diese würde ich gerne mit als <th> der Tabelle oben ausgeben lassen wollen, damit ich (und andere Admins) sehen können, welche Werte nun auf true sind und welche nicht.

Prinzipiell wäre es cool, wenn ich die Spalte in der dann Administrator steht per Föag wegschalten kann und über den true und / false dann die Beschreibung steht z.B.
 
Zuletzt bearbeitet:
hab deine Lösung gerade eingebaut - funktioniert perfekt.
Den Code von dir habe ich soweit angepasst, dass ich nun anstatt true/false Bilder ausgebe die ich dann anklicken kann zum Ändern.
Eventuell kannst du mir noch einen kleinen Denkanstoß geben.

Ich habe ja nun die Tabelle und muss nun den Bildern irgendwie Referenzen zu der Rolle, der Ressource und der Permission geben, damit ich die mit Hilfe eines onClicks und AJAX abfackeln kann bzw. ändern kann.

Hatte schon das Statement soweit angepasst, dass ich die FK's der role_resource_permissions-Tabelle ausgebe.

Eventuell kann ich dem Bild ne ID die ich dann via JS splitten kann.
Also die ID sähe dann prinzipiell so aus:
id="1;2;3"

Die könnte ich mir dann im JS auseinander basteln und einfach als post an den Ajax-Request dranhängen, das wäre ja kein Thema.

Nur wie bekomme ich am besten die ID in das Bild rein?
Denn ich hab keine Möglichkeit gefunden deine Klasse so minimal wie möglich zu verändern und ich dennoch diese besagten IDs der 3 Tabellen drin habe.
 
Good moooorrrrnnniiinnnnggg Haaabbbboooooo,

so, nun zu Deiner Frage:

Du hast doch in der resource_role_permissions-Table eine eindeutige ID oder nicht? Zusammen gesetzte ID's als Parameter ist nicht gut, ich würde deshalb die ID in ein neues Array packen, welches in die 3-Dimension des Array's kommt.

Beispiel:

PHP:
$arr = array(
    'admins' => array(        
        'news' => array(
            'create' => array('id' => 1, allow' => true)
        )
     )
)

Du gibst die ID natürlich nicht mit aus, sondern hängst Sie an die Ausgabe als Parameter.

Du bekommst dann praktischer Weise in der HTMLTableColumn ein Array übergeben, in diesem Array steckt jetzt dann deine ID und der Wert. Jetzt kannste natürlich die ID einfach an deinen onClick-Event hängen. In der HTMLTableColumn musst Du natürlich überprüfen ob es sich wirklich um ein Array handelt, da du ja einmal einen String übergibst und einmal ein Array.

feel free
 
"Moin"!
danke erstmal für deine schnelle Hilfe!
Hab mir nun die ID der einzelnen RRPs mit in das Array aufgenommen und nun deine Klasse versucht ein wenig abzuändern.

Habe in die getHTML-Methode HTMLTableColumns-Klasse den Paramter $id angefügt, als Eigenschaft bereitgestellt und übergebe diesen auch.

Nur ich fürchte ich habe irgendetwas nicht in deiner Klasse bedacht.
Hier die HTMLTableColumns:

PHP:
class HTMLTableColumn {

    private $value = null;
    private $rowspan = null;
    private $id = null;

    public function  __construct($value, $rowspan = 0, $id) {
        $this->value = $value;
        $this->rowspan = $rowspan;
        $this->id = $id;
        
    }

    public function getHTML() {
        $output.= '<td';
        if ($this->rowspan > 0) {
            $output.= ' rowspan="' . $this->rowspan . '"';
        }
        $output.= ' align="center">';
        if($this->value == "true"){
            $ret = "<img id='".$this->id."' src='images/icons/accept.png'>";
        }elseif($this->value == "false"){
            $ret = "<img id='".$this->id."' src='images/icons/delete.png'>";
        }else{
            $ret = $this->value;
        }
        return $output . $ret . '</td>';
    }
}
Die Aufbereitung des Arrays:
PHP:
$permissions = Model::getDataset($role_id, "GetPermissions", true, "FK_Role_ID", true);
                $arr = array();
                foreach($permissions as $permission){
                    $arr[$permission['Description']][$permission['Ressource']] = array('ID' => $permission['rrpID'], $permission['Property'] => $permission['allow']);
                }
Und die Verarbeitung des Arrays:
PHP:
$table = new HTMLTable();
                foreach ($arr as $key => $value) {
                    $row = new HTMLTableRow();
                    $rowspan = sizeof($value);
                    $col1 = new HTMLTableColumn($key, $rowspan);
                    $row->addColumn($col1);
                    $cntCols = sizeof($value);
                    $colKey = array_keys($value);
                    for ($i = 0; $i < 1; $i++) {
                        $col = new HTMLTableColumn($colKey[$i]);
                        
                        $row->addColumn($col);
                        foreach ($value[$colKey[$i]] as $colValue) {
                            $col = new HTMLTableColumn($colValue,0, $value[$colKey[$i]]['ID']);
                            $row->addColumn($col);
                        }
                    }
                    $table->addRow($key, $row);
                    $headerData = array();
                    $headerData['role'] = 'Rolle';
                    $headerData['resource'] = 'Ressource';
                    for ($i = 1; $i < $cntCols; $i++) {
                        $row1 = new HTMLTableRow();
                        $col = new HTMLTableColumn($colKey[$i]);
                        $row1->addColumn($col);
                        foreach ($value[$colKey[$i]] as $permKey => $colValue) {
                            $headerData[$permKey] = $permKey;
                            $col = new HTMLTableColumn($colValue);
                            $row1->addColumn($col);
                        }
                        $table->addRow($key . $i, $row1);
                    }
                }
                $header = new HTMLHeader($headerData);
                $table->addHeader($header);
                    
                $view->assign('Array',$arr);
                $view->assign('Table', $table);
Eventuell siehst du dort noch einen Fehler, der dort ganz gewiss irgendwo schlummert.

Achja btw. meine Ausgabe sieht wie folgt aus (falls es dir etwas helfen sollte):

 
Zuletzt bearbeitet:
Hallo,

ich hab Dir mein Beispiel nochmal angepasst und angehängt. Die neuen Sachen sind Kommentiert.

Musst Dir nur die neuen Codezeilen in Deinen Code ziehen.
 
So, vielen vielen Dank für deine tatkräftige Unterstützung! Klappt wunderbar alles.
Werd jezz noch den Ajax-Request einbauen und dann das Ergebnis mal posten für alle die dort Hilfe brauchen.

Vielen Dank nochmals! :)
 
Zurück
Oben