Binäres Rechtesystem

  • Themenstarter Themenstarter Bgag
  • Beginndatum Beginndatum
Also ich habs mal probiert, Fehler sind drin, die kann man beheben, aber ich weiß nichts mit Zeile 8 anzufangen. In Zeile 4 müsste == stehen.
MfG, Andy

//EDIT: Ich überlege übrigens ob ich anstatt Exceptions zu werfen, die Fehler mit loggen sollte, damit man sie besser in das jeweilige System integrieren kann. Was haltet ihr davon?
 
Zuletzt bearbeitet von einem Moderator:
Wow. Sorry ersma das ich abends im dichten kopp hier rumgetextet hab.
Daher kommt auch der grobe Patzer in Zeile 4 ;)

Zeile 8: $i <<= 1; bewirkt das die Zahl, die in $i ist mit 2 multipliziert wird - binäre Verschiebung. Quasi ist:

$i = pow(2, $exponent);

das gleiche wie:

$i = 1 << $exponent;

(für alle $exponent > 0) ;)
Vorteil ist das keine Funktion sich drum kümmern muss sondern binär alles stumpf verschoben wird.
 
Als erstes mal vielebn vielen Dank für deine Hilfe. Der Schnipsel ist super und er funktioniert auch hervorragend. Dank deiner kurzen Erklärung konnte ich ihn nun auch getrost in die Methode integrieren (hasse es, wenn ich meine eigenen Scripte nicht mehr verstehe). Gut dass du noch mit vollem Kopf noch soetwas hinbekommst. :) Hast du vielleicht noch irgendwelche Tipps für mich, wie ich die Klasse weiter optimieren könnte? Kleine Optimierungen im Bereich Performance oder weitere Methoden, die die Arbeit etwas erleichtern?

Achso und dann habe ich noch ein kleines Problem. Wie bekomme ich bei der Methode editUser() die Daten aus den Arrays $fields und $values am geschicktesten in das UPDATE-Query?
MfG, Andy
 
Habe zunächst die Klasse angesehen und alles was mir sofort an Performancebremsen da ist umgeschrieben. Ich war so frei auch kleinste Millisekunden zu beachten ;) Wirkt penibel - ist aber nicht so gemeint. Alles optionale Änderungen.
Siehe dir dazu die Kommentare an, hab mich in den letzten 24h schonmal woanders gut geirrt ;)

PHP:
<?php
class Permissions
{
    private $db;
    /*
     * schon mal sagen das es ein string wird
     * sonst prüft er den datentyp beim setzen
     */
    private $userTab = "";
    private $modTab = "";

    public function __construct(mysqli $db, $userTab, $modTab)
    {
        $this->db = $db;
        $this->modTab = trim($modTab);
        $this->userTab = trim($userTab);
    }

    public function addMod($name)
    {
        /*
         * $var = "text" . $andere . "text"
         * ist n tacken schneller
         *
         * Und ID ist bestimmt auto_increment.
         * weglassen in PHP und mySQL die arbeit
         * überlassen ;)
         */
        $sql = "INSERT INTO " . $this->modTab . "
                (`name`)
            VALUES
                ('" . $name . "')";


        $this->db->query($sql);

        /*
         * deprecated : if($this->db->affected_rows <= 0)
         * errno ist 0 (somit FALSE) wenn alles glatt
         * läuft. besser als ihn zählen zu lassen
         */
        if($this->db->errno)
        {
            throw new Exception("Cannot create section " . $name);
        }

        return true;
    }

    public function delMod($ident)
    {
        $id = $this->getId($ident, $this->modTab);

        /**
         * string "..." . $var . "..."
         * siehe oben
         */
        $sql = "DELETE
            FROM
                " . $this->modTab . "
            WHERE
                id = " . $id;

        $this->db->query($sql);

        /**
         * siehe oben
         */
        if($this->db->errno)
        {
        	/**
        	 * $id? hab eigentlich $ident erwartet ^^
        	 */
            throw new Exception("Cannot delete Mod ".$id);
        }

        return true;
    }

    public function getMods()
    {
    	/**
    	 * kennst ja nun die tricks und
    	 * die schleife:
    	 * 		$mods[] = $row;
    	 * das übernimmt [id] und [name]
    	 * von $row und brauch kein zähler
    	 */
    }

    public function addUser($fields = array(), $values = array())
    {
        /*
         * nun wird die größe öfter gebraucht
         * daher in variable speichern
         */
        $i = count($fields);
        $j = count($values);
        /*
         * hab mal gelesen === ist 10% schneller
         * geht hier gut da der typ passt
         */
        if( $i === $j)
        {
        	$sql = "INSERT INTO " . $this->userTab . " (";
        	/*
			 * die trinität ()? : ; ist
        	 * langsamer als ein if
        	 */
        	if ($i)
        	{
        		/*
        		 * nicht konform aber " geht
        		 * immernoch schneller als '
        		 */
        		$sql .= "`" . implode("`, `", $fields) . "`";
        		/*
        		 * so bleibt $fields auch ein array
        		 * und musst nicht umgecastet werden
        		 * auf einen string - was wieder zeit
        		 * brauch
        		 */
        	}
        	$sql .= ") VALUES (";

        	if ($j) {
				$sql .= "'" . implode("', '", $values) . "'";
        	}
        	$sql .= ")";
        }

        else
        {
            throw new Exception("Invalid user data.");
        }

        $this->db->query($sql);

        /*
         * siehe oben
         */
        if($this->db->errno)
        {
            throw new Exception("Cannot create user.");
        }
    }

    /*
     * bei den folgenden funktionen reichen
     * die oben erklärten tricks:
     * delUser($ident)
     * getUser($ident)
     */

    public function getPerms($ident)
    {
        $id = $this->getId($ident, $this->userTab);

        // $sql = ...... - übliche optimierung durch "..." . $var . "..."

        if ( $result = $this->db->query($sql) )
        {
            /*
             * im query ist nur perm gefragt
             * von daher reicht die schnellste
             * variante zum auslesen: fetch_row
             */
            $array = $result->fetch_row();

            // get perm from array
            $perm = $array[0];
        }

        else
        {
            throw new Exception("Cannot get permissions of user " . $userId);
        }

        /*
         * hier die schon optimierte
         * schleife
         */

        return $mods;
    }

    public function calcPerms($mods)
    {
        $perms = 0;

        // create binary permission data
        foreach($mods as $id)
        {
            /*
             * binärer ODER-Vergleich
             * Bsp. einer hat recht 4 und 8:
             * Recht 4 -> 0100
             * ODER
             * Recht 8 -> 1000
             * ergibt
             * Recht 12-> 1100
             * usw.
             */
            $perms |= $id;
        }

        return $perms;
    }


    public function check($user, $mod)
    {
        $userId = $this->getId($user, $this->userTab);

        // bei $sql = ... noch übliche sache mit dem string machen:

        if ( $result = $this->db->query($sql) )
        {
            /*
             * wieder mit fetch_row()
             */
            $array = $result->fetch_row();

            // get perm from array
            $perms = $array[0];
        }

        else
        {
            throw new Exception("Cannot get permissions of user {$userId}.");
        }

        /*
         * ein bisschen variablen
         * und speicher sparen:
         */
        $perms >>= $this->getId($mod, $this->modTab);
        /*
         * nun steht das recht was man
         * prüfen will ganz "vorn"
         * im binären.
         * bsp. :
         * recht 12-> 1100
         * hat er recht 4? ($this->getId liefert 2)
         * 12 >> 2 -> 110
         * ist am ende eine 1?
         * 110 & 1 -> 0 (FALSE)
         */

        /*
         * true, false macht der sich schon
         * wieder eine trinität weniger ;)
         */
        return $perms & 1;
    }

    private function getId($ident, $table)
    {
        if( is_numeric($ident) )
        {
        	// direkt rausspringen
            return $ident;
        }
        else
        {
            // übliche sache noch mit string machen
            $sql = "SELECT
                    `id`
                FROM
                    {$table}
                WHERE
                    name = '{$ident}'
                LIMIT 1";

            if ( $result = $this->db->query($sql) )
            {
                // fetch_row
                $array = $result->fetch_row();

                // direkt return
                return $array[0];
            }

            else
            {
                return false;
            }
        }
    }
}

?>

woah. heidenarbeit.
alles funktion für funktion testen ;)
hab da n komisches gefühl im bauch :suspekt:

Es gibt noch einen optimierungsschritt für die letzte Funktion.
Sie ist private und gibt nur eine Zahl wieder. Wenn du das erste Argument als Referenz machst
und dementsprechend behandelst in allen anderen Funktionen sparst du wieder etwas speicher und rechenzeit.
 
Zuletzt bearbeitet:
Wow Danke! Ich werde es sobald ich Zeit habe nochmal alles testen. Ich habe das ganze schon einmal überflogen und das ganze sieht sehr vielversprechend aus. Also vielen Dank für deine Mühen.

Wegen der editUser()-Methode habe ich mir überlegt, dass man ja einfach beide Arrays auf einmal in einer for()-Schleife durchlaufen könnte und somit das Query erstellen könnte. Was meinst du?
MfG, Andy
 
Ehrlich gesagt weis ich nicht so recht was du mit editUsers noch besonderes vor hast.
Für meinen Teil würde ich es genau so wie AddUser anlegen nur statt INSERT ein UPDATE.
 
Guten Morgen!
Also ich habe die Klasse nun mal überarbeitet. Es waren zwar ein paar Fehler drin, die aber sehr einfach zu beheben waren. Leider gibt es nun doch zwei Probleme. Die Methode editUser() erzeugt einen Fehler, obwohl der entsprechende Nutzer existiert und die Methode calcPerms() errechnet völlig falsche Werte. Gibt man ihr die Ids der Bereiche 1,2,3,4 gibt sie als Ergebnis 7 zurück. Richtig wäre 2 + 4 + 8 + 16 = 30. Woran liegt das?
MfG, Andy
 
Zuletzt bearbeitet von einem Moderator:
Achso sollte das ^^
Weil in der 7 sind alle Rechts quasi drin:
rechte: 1|2|3|4
7 binär->1111 (alle "an")
Das hab ich zunächst unter binär verstanden

Wenn du die 30 haben willst das foreach entsprechend abändern:
PHP:
foreach($mods as $id)
  {
    // create mod perms
    $perms += 1 << $id;
  }

Joa. Das dürfte das sein. Ist gleichbedeutent mit $perms += pow(2,$id); nur schneller.
 
Zuletzt bearbeitet:
Die Erklärung ist eigentlich simpel:
Code:
     0001
ODER 0010
ODER 0011
ODER 0100
   = 0111
Was du brauchst:
PHP:
$perms += 1 << $id;
 
Gumbo hat den Fehler gefunden. Stimmt jetzt. Allerdings funktioniert die Methode editUser() noch nicht und ich weiß auch nicht wieso. Muss ich das ganze vielleicht irgendwie so abändern?
MfG, Andy

PHP:
    /**
    * editUser() - Changes the data of an user
    *
    * @access public
    * @param Str $user
    * @param Arr $fields
    * @param Arr $values
    * @return NONE
    */
    public function editUser($user, $fields = array(), $values = array())
    {
        // get id of the user
        $id = $this->getId($user, $this->userTab);
        
        // check count of fields and values
        if( count($fields) === count($values))
        {
            // create sql-query
            $sql = "UPDATE " . $this->userTab;
            
            $sql .= " SET (";

            // update values
            for($i=0; $i < count($fields); $i++)
            {
                 $sql .= $fields[$i] . "'" . $values[$i] . "'";
            }
            
            $sql .= ") ";
            
            $sql .= "WHERE id = '" . $id . "'";
            
            echo $sql;
        }

        else
        {
            throw new Exception("Invalid user data.");
        }
        
        // edit user data
        $this->db->query($sql);

        // check result
        if( $this->db->errno )
        {
            throw new Exception("Cannot change user data.");
        }
    }
 
Zurück