Zufallstext

Dieser Bereich dient dazu, neue Features zu diskutieren und für die Entwicklung zu dokumentieren. // This area is dedicated to new features including proposals and documentation.
Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 01.04.2011, 22:37:31

Sofern ich das Problem verstanden habe, liegt es einfach an der Zerlegung des Strings. Was spricht dagegen einfach ein Array so zu definieren:

Code: Alles auswählen

$chars = array('1', '2', ...); 
Dann sollten wir doch sichergehen, dass PHP intern die Zuordnung auch mit Mehrbyte-Zeichen korrekt vornimmt.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 02.04.2011, 19:20:19

Hallöchen,

Doku ist im Wiki schonmal begonnen:
http://wiki.adventure-php-framework.org ... ingManager

Zum Umlauteproblem:
ich habe nochmal ein paar neue Infos:

Und zwar ist es sinnvoll, bei der Gefahr auf Multibyte-Zeichen zu stossen, auch die MultiByte-Funktionen von PHP zu nutzen ;). Dazu genügt meist einfach ein "mb_" vor der Funktion, dann passt das.
Es gibt weiterhin die Möglichkeit, die Codierung auszugeben:

Code: Alles auswählen

echo mb_internal_encoding(); 
http://de3.php.net/manual/de/function.m ... coding.php

Überraschenderweise hat das bei mit NICHT UTF-8 sondern ISO-8859-1 bei mir ausgespuckt ... sher merkwürdig! Daher spuckt die Funktion strlen und auch mb_strlen immer einen grösseren Wert aus, als es für uns tatsächlich der Fall ist. Der Grund ist ja eben das MultiByte-Problem.

Daraufhin habe ich über die Funktion das Encoding nochmal manuell gesetzt:

Code: Alles auswählen

mb_internal_encoding("UTF-8");
 
Damit wird immerhin die Länge schonmal richtig erkannt und ausgegeben. MultiByte-Zeichen werden als ein Zeichen gezählt, nicht als zwei oder drei.

Trotzdem wird teilweise noch Müll ausgespuckt. Gibts vllt. doch noch weitere Ansätze? ;)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 04.04.2011, 20:12:58

Hast du mal meine Variante versucht?

Was den Wiki-Eintrag angeht, so könntest du auch noch eine Möglichkeit vorsehen, den Service über den DIServiceManager zu beziehen. Das ist für den Anwender einfacher und sieht hübscher aus.

Hierzu musst du einfach ein oder mehrere Methoden implementieren, die die Konfigurations-Werte aufnehmen und die Komponente initialisieren. Dies verpackt in eine Service-Konfiguration macht den Manager sehr einfach per

Code: Alles auswählen

// APF <= 1.13
$this->__getDIServiceObject('namespace::of::service','ServiceNamen');

// APF > 1.13
$this->getDIServiceObject('namespace::of::service','ServiceNamen'); 
verfügbar.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 04.04.2011, 21:26:17

dr.e. hat geschrieben:Hast du mal meine Variante versucht?[/qoute]
dr.e. hat geschrieben:Was spricht dagegen einfach ein Array so zu definieren:

Code: Alles auswählen

$chars = array('1', '2', ...); 
Sorry, da bin ich etwas drüber hinweg gelaufen ...
Wie meinst du das? Beim Einbinden in meinen Controller? Kannst du das etwas näher erläutern?

Für den DIService wird doch eine Konfiguration benötigt, richtig? Genau das wollte ich für dieses kleine, einfache Tool vermeiden.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 04.04.2011, 22:14:12

Hi dave,
Wie meinst du das? Beim Einbinden in meinen Controller? Kannst du das etwas näher erläutern?
Zur Definition der möglichen Zahlen meinte ich.
Für den DIService wird doch eine Konfiguration benötigt, richtig? Genau das wollte ich für dieses kleine, einfache Tool vermeiden.
Korrekt, dafür benötigst du eine Konfiguration um den Service gegenüber deiner Software zu abstrahieren. Aber wenn ich mir deine Komponente so ansehe, ist das jetzt schon auf jeden Fall keine einfach Konfiguration mehr, da du eine DB-Config brauchst. Ein DI-Service ist IMHO da nicht weit weg, bzw. kannst du die Flexibilität dadurch erhöhen, dass du den Connection-Key auch injizieren kannst. So ist er nur "statisch" definiert.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 04.04.2011, 22:24:17

dr.e. hat geschrieben:Zur Definition der möglichen Zahlen meinte ich.
Mit den Zahlen gibt es ja gar keine Probleme, auch mit normalen Zeichen des Alphabets klappt alles wunderbar. Wenn ich nun vom Programmierer verlange, den Aufruf dieser Art zu gestalten:

Code: Alles auswählen

$randomString = &$this->__getAndInitServiceObject('tools::randomstring', 'RandomStringManager', array('!', '§', '$', '(', ')', '?', ...); 
werd der mir wohl einen Vogel zeigen ... das artet ja in Schreibarbeit aus. Und wenn ich dass dann noch in eine Config umändern möchte, wegen dem DI, klappt das auch nicht mehr ...
dr.e. hat geschrieben: Korrekt, dafür benötigst du eine Konfiguration um den Service gegenüber deiner Software zu abstrahieren. Aber wenn ich mir deine Komponente so ansehe, ist das jetzt schon auf jeden Fall keine einfach Konfiguration mehr, da du eine DB-Config brauchst. Ein DI-Service ist IMHO da nicht weit weg, bzw. kannst du die Flexibilität dadurch erhöhen, dass du den Connection-Key auch injizieren kannst. So ist er nur "statisch" definiert.
Wow, das überschreitet im Moment bei Weitem das, was ich eigentlich erreichen wollte. ;) Ich habe mich in der Doku auch schonmal ein wenig umgesehen und das ist echt mal wieder fetter Stoff. Es ist zwar schön, dass es das alles gibt, aber für dieses kleine Sche*** ZufallsString-Ding wäre das doch übertrieben, oder? Wie war das mit Spatzen und Kanonen? :)

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 04.04.2011, 22:51:48

Mmhhh, Ok, ich habe zum fünften mal in die PHP-Doku geschaut und was interessantes dort entdeckt:

Code: Alles auswählen

    function mbStringToArray($string) {
        $strlen = mb_strlen($string);
        while ($strlen) {
            $array[] = mb_substr($string, 0, 1, "UTF-8");
            $string = mb_substr($string, 1, $strlen, "UTF-8");
            $strlen = mb_strlen($string);
        }
        return $array;
    }
 
Die Funktion liefert mir ein Array, wobei jedes Zeichen einem Array-Element entspricht. Und da pcike ich mir nun irgendeins raus und füge es meinem String hinzu. Und das gebe ich aus und es passt, es sieht alles gaaanz normal aus, ohne Hyroglyphen oder sonderbaren, ungewollten Zeichen! Und auch im Quelltext sieht alles gut aus, alles die gewünschten Zeichen, so wie es sein soll!! Funktioniert allerdings nur für UTF-8, da dies in der Funktion direkt eingegeben ist.

Wenn nun über den DI eine Konfiguration zum Einsatz käme, hätte man natürlich alle Möglichkeiten der Welt ... aber das nehme ich mir für später vor!

Ich bin erstmal froh, dass nun endlich alles locker flockig läuft, ohne mit utf8_decode oder _encode rum zu spielen ;).

Pah, nun aber ins Bett ... es ruft schon! :ugeek:

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 04.04.2011, 22:53:49

Hi dave,

naja, wie diskutieren ja über eine Komponente eines Frameworks. Und da wirst du oft mit Fragen wie "Kann ich damit auch *** machen?" (z.B. "Kann ich mit dem RandomStringManager auch Kaffee kochen?") konfrontiert. :) Sofern du also nur eine einfache Komponente haben möchtest, musst du dem User eine statische Methode mit dem Kern-Inhalt geben, der eben nichts mit Datenbank & Co. zu tun hat.

Insofern gebe ich dir mit den Kanonen schon recht, andererseits hast du mit der Datenbank-Geschichte schon eine Komplexitäts-Stufe eingebaut, die eben nicht mehr so ganz einfach ist. ;) Einigen wir uns auf 1:1?
Ich habe mich in der Doku auch schonmal ein wenig umgesehen und das ist echt mal wieder fetter Stoff.
Jep, DI ist cool. Man kann die komplette Konfiguration aus der Applikation herausziehen und damit beispielsweise die Testbarkeit extrem erhöhen. Wenn du möchtest, können wir das ja mal zusammen coden/diskutieren.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 05.04.2011, 15:17:22

Wie würde es mit dem DI denn aussehen?

Würde es reichen, dass ich einfach weitere Methoden für den DI mit einprogrammiere, sodass man die einfachen Methoden auch weiterhin verwenden kann, wenn man keine extra Konfiguration nutzen will? Oder müsste ich den kompletten Manager umbauen?

Die Doku im Wiki habe ich soweit fertig. Ganz zu Beginn gibt es den Hinweis wegen den Sonderzeichen:
http://wiki.adventure-php-framework.org ... ingManager

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 05.04.2011, 23:47:25

Hi dave,
Würde es reichen, dass ich einfach weitere Methoden für den DI mit einprogrammiere, sodass man die einfachen Methoden auch weiterhin verwenden kann, wenn man keine extra Konfiguration nutzen will? Oder müsste ich den kompletten Manager umbauen?
Beide Wege sind denkbar. Wenn du beide anbieten möchtest, würdest du einfach zusätzliche Methoden definieren, die die Abhängigkeiten injizieren. Basierend auf dem vorhandenen Code sind das
  • chars
  • length
  • connectionKey
Wobei length eigentlich auch ein Parameter von createHash() sein könnte, dann bist du flexibler in der Handhabe.

Hier mal der Code für DI-Erzeugung:

Code: Alles auswählen

class RandomStringManager extends APFObject {

   private $chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
   private $lenght = 16;
   private $randomString;
   private $connectionKey;

   public function __construct() {
      $this->randomString = '';
   }

   public function setChars($chars) {
      $this->chars = utf8_decode($chars);
   }

   public function setLenght($lenght) {
      $this->lenght = (int) $lenght;
   }

   public function setConnectionKey($connectionKey) {
      $this->connectionKey = $connectionKey;
   }

   public function init($initParam) {
      if ($initParam['chars'] === '') {
         $this->chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
      } else {
         $this->chars = utf8_decode($initParam['chars']);
      }
      if (empty($initParam['lenght'])) {
         $this->lenght = (int) 16;
      } else {
         $this->lenght = (int) $initParam['lenght'];
      }
   }

   public function createHash() {
      for ($i = 0; $i < $this->lenght; $i++) {
         $this->randomString .= $this->chars[mt_rand(0, strlen($this->chars) - 1)];
      }

      return utf8_encode($this->randomString);
   }

   public function advancedCreateHash($select, $connectionKey) {
      $this->randomString = '';

      if ($select == '') {
         throw new Exception('[RandomStringManager::advancedCreateHash()] You must provide a SQL query!', E_USER_ERROR);
      }

      if ($connectionKey == '') {
         throw new Exception('[RandomStringManager::advancedCreateHash()] You must provide a ConnectionKey for the SQL Statement!', E_USER_ERROR);
      }

      $cM = &$this->__getServiceObject('core::database', 'ConnectionManager');
      $SQL = &$cM->getConnection($connectionKey);

      $hash = $this->createHash();
      $hash = $SQL->escapeValue($hash);
      $selection = $select . "'$hash'";
      $result = $SQL->executeTextStatement($selection);

      while ($SQL->getNumRows($result) > 0) {
         $this->advancedCreateHash($select, $connectionKey);
         break;
      }

      return $this->randomString;
   }

} 
Die passende Konfiguration (*_serviceobjects.ini) lautet dafür

Code: Alles auswählen

[RandomString]
namespace = "..."
class = "RandomStringManager"
servicetype = "SINGLETON"
conf.chars.method = "setChars"
conf.chars.value = "..."
conf.length.method = "setLength"
conf.length.value = "..."
conf.conn.method = "setConnectionKey"
conf.conn.value = "..."
Anschließend kannst du den Service wie oben beschrieben beziehen.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 06.04.2011, 10:20:01

Ok, ich vermute mal, du willst den DI mit drin haben, sonst würdest du dir nicht soviel Mühe geben. :)

Ich erweitere das und probiere das bei mir aus.

Nochmal eine Frage zur Konfiguration:
Über

Code: Alles auswählen

conf.chars.value = "..."
conf.length.value = "..."
conf.conn.value = "..."
kann man dann die Parameter einstellen. Also welche Zeichen ich verwenden möchte usw., korrekt?

Was mir dabei übrigens auffällt, dass ich es kompliziert finde, dass in die Konfiguration die Klassennamen mit rein müssen. Der Programmierer, welcher nur das Tool nutzen will, kennt sich mit der inneren Struktur des Tools ja gar nicht aus und ist dann mit solchen Parametern überfordert. Ich spreche aus Erfahrung, ging mir auch so, bis mir das dann hier durch klarer wurde ;)

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 06.04.2011, 21:49:53

Hi dave,
Ok, ich vermute mal, du willst den DI mit drin haben, sonst würdest du dir nicht soviel Mühe geben. :)
Nein, das ist dann falsch angekommen. :)
kann man dann die Parameter einstellen. Also welche Zeichen ich verwenden möchte usw., korrekt?
Die Konvention ist

Code: Alles auswählen

conf.xyz.method = ""
conf.xyz.value = ""
Du kannst für eine Gruppe von statischen Initialisierungen jeweils einen eigenen Key vergeben (im Beispiel oben "xyz").
Was mir dabei übrigens auffällt, dass ich es kompliziert finde, dass in die Konfiguration die Klassennamen mit rein müssen. Der Programmierer, welcher nur das Tool nutzen will, kennt sich mit der inneren Struktur des Tools ja gar nicht aus und ist dann mit solchen Parametern überfordert. Ich spreche aus Erfahrung, ging mir auch so, bis mir das dann hier durch klarer wurde ;)
Dann magst du entweder DI nicht oder kannst mit dem Prinzip nichts anfangen. Ziel der Vorgehensweise ist es, die Implementierung und die Initialisierung gegenüber der verwendenden Instanz zu verstecken. Üblicherweise hast du ein Interface, das unterschiedliche Implementierungen besitzt. Welcher Service (~=Interface) dann welche tatsächlich Implementierung darstellt, bleibt einer Konfiguration überlassen. So kannst du beispielsweise einen MOCK-Service injizieren und deine Komponenten Unittesten oder einfach eine andere Datenquelle verpassen. Nutzt du einen Service nicht über DI, stehen die Abhängigkeiten immer direkt im Code und du musst Code ändern um die Datenquelle zu ändern oder einen MOCK-Test durchzuführen.

Die init()-Methode bzw. der ServiceManager ist bereits eine Form von dependency injection und du nutzt es ohne darüber nachzudenken schon also solche (z.B. zur Initialisierung). Du bist also inhaltlich und gedanklich garnicht so weit davon entfernt. :)

Sicher ist DI nicht an allen Stellen notwendig und angebracht, das APF nutzt das Konzept jedoch schon bei den DOM-Elementen hinsichtlich des Context und der Sprache um diese überall verfügbar zu machen. Wenn du den Aufwand nicht treiben möchtest, ist das völlig in Ordnung, ich würde dann jedoch noch eine kleine Anpassung an der API vornehmen, damit die Applikation an sich nicht so viel von den Interna des Service kennt (z.B. DB-Connection in der init()-Methode übergeben).
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 06.09.2011, 20:01:03

Hallöchen :)

Ich nutze meinen RandomStringManager nun schon eine ganze Weile. Die anfänglichen Probleme mit der Codierung habe ich soweit auch behoben. Sicherlich gibt es noch Nachholbedarf gerade im Bereich der Methode advancedCreateHash(). Da könnte ich mir sehr gut die Bearbeitung mit dem GORM vorstellen.

Insgesamt habe ich aber im Moment nicht die Zeit, das alles weiter zu realisieren. Rom wurde bekanntlich auch nicht an einem Tag erbaut. Sobald sich was ergibt, wird das angepasst und ich könnte das dann auch zur Verfügung stellen.

Eine Einbindung in das APF würde mich sehr freuen bzw. wäre ich froh, auch einen Teil dazu beigetragen haben zu dürfen :). Eine Doku dazu ist auch im Wiki bereits online: http://wiki.adventure-php-framework.org ... ingManager

Christian, bist du bereit, das Teil ins APF aufzunehmen. Was muss ich dafür noch an Kommentaren anpassen?

Achso: Hier die gesamte Klasse;

Code: Alles auswählen

<?php

class RandomStringManager extends APFObject {

    private $chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    private $lenght = 16;
    private $randomString;

    public function __construct() {
        $this->randomString = '';
    }

    public function setChars($chars) {
        $this->chars = $this->mbStringToArray($chars);
    }

    public function setLenght($lenght) {
        $this->lenght = (int) $lenght;
    }

    public function setConnectionKey($connectionKey) {
        $this->connectionKey = $connectionKey;
    }

    private function mbStringToArray($string) {
        $strlen = mb_strlen($string);
        while ($strlen) {
            $array[] = mb_substr($string, 0, 1, "UTF-8");
            $string = mb_substr($string, 1, $strlen, "UTF-8");
            $strlen = mb_strlen($string);
        }
        return $array;
    }

    public function init($initParam) {
        if ($initParam['chars'] === '') {
            $this->chars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        } else {
            $this->chars = $initParam['chars'];
        }
        if (empty($initParam['lenght'])) {
            $this->lenght = (int) 16;
        } else {
            $this->lenght = (int) $initParam['lenght'];
        }

        $this->chars = $this->mbStringToArray($this->chars);
    }

    public function createHash() {
        for ($i = 0; $i < $this->lenght; $i++) {
            $this->randomString .= $this->chars[mt_rand(0, count($this->chars) - 1)];
        }

        return $this->randomString;
    }

    public function advancedCreateHash($select, $connectionKey) {
        $this->randomString = '';

        if ($select == '') {
            throw new InvalidArgumentException('[RandomStringManager::advancedCreateHash()] You must provide a SQL query!', E_USER_ERROR);
        }

        if ($connectionKey == '') {
            throw new InvalidArgumentException('[RandomStringManager::advancedCreateHash()] You must provide a ConnectionKey for the SQL Statement!', E_USER_ERROR);
        }

        $cM = &$this->getServiceObject('core::database', 'ConnectionManager');
        $SQL = &$cM->getConnection($connectionKey);

        $hash = $this->createHash();
        $hash = $SQL->escapeValue($hash);
        $selection = $select . "'$hash'";
        $result = $SQL->executeTextStatement($selection);

        while ($SQL->getNumRows($result) > 0) {
            $this->advancedCreateHash($select, $connectionKey);
            break;
        }

        return $this->randomString;
    }

}

?>

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Zufallstext

Beitrag von dr.e. » 07.09.2011, 00:16:07

Hi dave,
Eine Einbindung in das APF würde mich sehr freuen bzw. wäre ich froh, auch einen Teil dazu beigetragen haben zu dürfen :). Eine Doku dazu ist auch im Wiki bereits online: http://wiki.adventure-php-framework.org ... ingManager
Grundsätzlich immer gerne, für eine offizielle Aufnahme brauchen wir jedoch noch eine offizielle Dokumentation. Textuell hattest du diese im Wiki schon verfasst, diese muss jedoch noch als HTML-Template aufgearbeitet und ins SVN kommen.
Christian, bist du bereit, das Teil ins APF aufzunehmen. Was muss ich dafür noch an Kommentaren anpassen?
Jep, Code benötigt noch eine Klassen- sowie Methoden-Dokumentation.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Zufallstext

Beitrag von dave » 07.09.2011, 00:17:36

Ok, darum kümmere ich mich die Tage gerne, melde mich dann wieder an dieser Stelle!

Gesperrt

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast