php.de

Zurück   php.de > Webentwicklung > Software-Design

Software-Design Diskussionen auf Profi-Niveau: PHP Lösungen auf konzeptioneller Ebene

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 02.12.2009, 22:28  
Neuer Benutzer
 
Registriert seit: 29.07.2009
Beiträge: 17
PHP-Kenntnisse:
Fortgeschritten
raw-venture-ad befindet sich auf einem aufstrebenden Ast
Standard Clevere und skalierbare Datenstruktur für verknüpfte Select-Felder

Hallo zusammen

Ich suche derzeit für meinen Kunden eine Möglichkeit, dass Werte innerhalb von HTML-Select Feldern von Werten anderer Select-Felder abhängig sind.

Folgende Anforderung liegt vor:
  • 10 Select Felder
  • ca. 150 Werte (insgesamt in allen 10 Feldern, kann variieren)
  • Eine Auswahl soll in x Feldern (1. Unbekannte) bewirken, dass in diesen Feldern nurnoch y Einträge (2. Unbekannte) auswählbar sind
  • Manche Option-Werte sind unsichtbar und werden nur bei bestimmten Kombinationen der 10 Feldwerte auswählbar
  • Diese Kombinationen / Verknüpfungen werden sich regelmäßig verändern, d.h. es muss leicht editierbar und skalierbar sein

Ist also eine andere Aufgabe als das übliche lineare "Kontinent" - "Land" - "Stadt" Verfahren was es schon so häufig gibt.


Bisher habe ich mir das so gedacht:

Für einen Feldwert (ID + Bezeichnung) wird in einer Datenbank (SQL Server) eine PHP-If Bedingungen als String gespeichert die dann mit eval ausgeführt wird und TRUE liefert wenn der Feldwert angezeigt werden soll, also:


25 --- Feld1 --- MeineBezeichnung --- ((Feld3==32||Feld3==33)&&Feld10!=34)

Also wird "MeineBezeichnung" im Feld1 nur angezeigt wenn Feld3 den Wert 32 oder 33 hat UND Feld10 nicht den Wert 34 hat.

Was haltet ihr von dieser Datenstruktur? Sehr performant und elegant ist sie leider nicht, aber bisher fällt mir keine andere Möglichkeit diese vielen Bedingungen- / Kombinationswünsche des Kunden umzusetzen.

Habt Ihr vielleicht Ideen oder Denkanstöße für mich wie ich das Problem sonst noch lösen könnte?

Vielen Dank vorab!

raw
raw-venture-ad ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 02.12.2009, 22:49  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.269
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Hallo,
grundsätzlich sind eval() und das Ablegen von Algorithmen in der Datenbank zu vermeiden. Du musst wenn möglich ein Regelwerk oder ein Schema dahinter erkennen. Eine gut strukturierte Datenbasis kann dieses Regelwerk ja schon beinhalten, eben durch das Verwenden von Fremdschlüsseln.

Kannst du denn etwas mehr über die Anwendung sagen?
Chriz ist gerade online   Mit Zitat antworten
Alt 03.12.2009, 00:18  
Moderator
 
Benutzerbild von robo47
 
Registriert seit: 03.09.2004
Beiträge: 11.792
PHP-Kenntnisse:
Fortgeschritten
robo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz seinrobo47 kann auf vieles stolz sein
Standard

Ansonsten jenachdem wie oft sich die Daten ändern, cache die abfragen doch einfach
robo47 ist offline   Mit Zitat antworten
Alt 03.12.2009, 18:10  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

Zitat:
Eine gut strukturierte Datenbasis kann dieses Regelwerk ja schon beinhalten, eben durch das Verwenden von Fremdschlüsseln.
Jain. IMHO ist es irgendwann sinnfrei, alles relational abbilden zu wollen. Bereits wenn es an solche == und != Geschichten wie oben geht, könnte man jetzt alles als Fremdschlússelbeziehung anlegen, und mit JOINs und NOT INs arbeiten. Nur ist das unter Umständen much to much. Wenn es bspw. um die Darstellungslogik von Selectfeldern (gar nicht mal um die Strukturierung der ausgewählten Werte) ginge, reich m. E. auch ein JSON-String o.ä. (doppelt praktisch, weil auch Javascript damit direkt umgehen kann). Bestimmte Dinge sind einfach schon zu sehr Logik des Businessobjekts, statt Datenhaltung und die resultierenden DB-Operationen sind nach meiner Ansicht dann nicht mehr gerechtfertigt. Man kann einfach nicht alles relational abbilden. Und ein häufig wechselndes Prinzip macht das Ganze noch viel schlimmer.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 03.12.2009, 18:20  
Neuer Benutzer
 
Registriert seit: 29.07.2009
Beiträge: 17
PHP-Kenntnisse:
Fortgeschritten
raw-venture-ad befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von Chriz Beitrag anzeigen
Hallo,
grundsätzlich sind eval() und das Ablegen von Algorithmen in der Datenbank zu vermeiden. Du musst wenn möglich ein Regelwerk oder ein Schema dahinter erkennen. Eine gut strukturierte Datenbasis kann dieses Regelwerk ja schon beinhalten, eben durch das Verwenden von Fremdschlüsseln.
Ja, das ist auch meine Idee gewesen. Nicht für jeden Wert zu speichern, WANN er angezeigt wird, sondern die Verknüpfung zu speichern. Beispielsweise so:

Feld3 --- OptionWert 24 --- Feld4 --- OptionWert 1
Feld3 --- OptionWert 24 --- Feld4 --- OptionWert 2
Feld3 --- OptionWert 24 --- Feld9 --- OptionWert 93

Also die Auswahl "OptionWert 24" bewirkt das in Feld 4 nurnoch die Werte OptionWert 1 und 2 gehen und in Feld 9 nurnoch OptionWert 93. Aber wie stelle ich dann die "Außnahmen" dar?

Zitat:
Zitat von Chriz Beitrag anzeigen
Kannst du denn etwas mehr über die Anwendung sagen?
Leider schwer zu erklären, es soll im Prinzip eine Geschäftslogik strukturiert abgelegt werden. Z.B. ein bestimmter Kundenkreis ist immer einem bestimmten Vertriebsteam zugeordnet. Um obige Darstellung zu verwenden also z.B. so:

Kundenkreis --- Kleine Kunden --- Vertriebsteam --- Team 2
Kundenkreis --- Kleine Kunden --- Vertriebsteam --- Team 3
Kundenkreis --- Mittlere Kunden --- Vertriebsteam --- Team 9
Kundenkreis --- Große Kunden --- Vertriebsteam --- Team 1

Man wählt also den Kundenkreis "Große Kunden" aus und es wird automatisch das Vetriebsteam "Team 1" ausgewählt (alle anderen Vertriebsteams gehen nicht mehr). Am Besten sogar auch noch umgekehrt, also Auswahl des Vertriebsteams "Team 1" bewirkt das automatisch "Große Kunden" im Feld Kundenkreis ausgewählt wird.

Das Problem sind wie gesagt die Verknüpfungen die etwas komplizierter sind bzw. Außnahmen haben.
raw-venture-ad ist offline   Mit Zitat antworten
Alt 03.12.2009, 18:57  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.269
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Was genau wäre eine Ausnahme, welche Art von Bedingungen sind daran geknüpft (zeitliche Abhängigkeit, Anzahl der Kunden, um die sich ein Team bereits kümmert, ..?).

Sind diese Ausnahmen nur ausschließender (Team 2 doch nicht) oder auch erweiternder Natur (Großkunden-Teams ohne Arbeit bekommen auch mal Kleinkunden)?

Du könntest dir überlegen das ganze Event-basiert aufzubauen. Für Events können sich dynamisch (über DB steuerbar) Komponenten registrieren, die bestimmte Aktionen durchführen.
Beispielsweise schmeißt du den Event "onAfterTeamSelection" nachdem du aus der Datenbank die passenden Teams für die Auswahl des Kundenkreises ermittelt hast (über die normale Fremdschlüsselbeziehung kundenkreis->teams). In der Datenbank hast du eine Event-Tabelle, der du dem Event "onAfterTeamSelection" den PHP-Callback "SelectExceptions::harry5pm" zuweist. Dieser bekommt nun die Liste der Teams übergeben und kann entscheiden, dass 17 Uhr vorbei ist und Harry dann schon immer nach Hause gegangen ist, also Team 2 dafür nicht in Frage kommt. Also schmeißt er Team 2 aus dem Ergebnis heraus.

Die Zuordnung, SelectExceptions::harry5pm <-> onAfterTeamSelection, könntest du relativ einfach gestalten. Einmal liest du von irgendwoher (DB-Tabelle) alle erlaubten Events aus und über die Reflection-API oder andere Hilfsmittel, listest du die Methoden der SelectExceptions aus. Über DOC-Kommentare könntest du steuern, dass "harry5pm" dort "Harry geht um 17 Uhr heim" heißt.

Wenn du eine neue Funktionalität brauchst (Großkunden-Teams mit weniger als 3 betreuten Kunden rutschen auch in die Ergebnisse der Mittleren Kunden), musst du das ganze eben in SelectExceptions implementieren, die Zuweisung zum Event vornehmen, und das ganze ist gebongt.

Ich schreib dir nachher mal ein paar Schnipsel dazu an Code.
Chriz ist gerade online   Mit Zitat antworten
Alt 03.12.2009, 20:05  
Neuer Benutzer
 
Registriert seit: 29.07.2009
Beiträge: 17
PHP-Kenntnisse:
Fortgeschritten
raw-venture-ad befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von Chriz Beitrag anzeigen
Was genau wäre eine Ausnahme, welche Art von Bedingungen sind daran geknüpft (zeitliche Abhängigkeit, Anzahl der Kunden, um die sich ein Team bereits kümmert, ..?)
Eine Ausnahme wäre z.B.:

"Große Kunden" werden immer vom "Vertriebsteam 1" betreut, es sei denn im Feld "Produktklasse" ist "Server" ausgewählt, dann ist nämlich immer Vertriebsteam 9 zuständig, egal wie groß der Kunde ist.


Eine "kompliziertere" Verknüpfung wäre z.B.:

"Kleine Kunden" werden immer nur dann vom Vertriebsteam 2 oder 3 betreut, wenn der Kunde eine "Installation" beauftragt hat. Also eine zusätzliche UND Verknüpfung der Felder "Vertriebsteam" und "Geschäftsfall".



Den Rest deiner Antwort muss ich jetzt noch ein paar mal lesen bevor ich ihn endgültig verstehe, aber danke schonmal für den Codeschnippsel! Bin gespannt!!
raw-venture-ad ist offline   Mit Zitat antworten
Alt 03.12.2009, 23:31  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.269
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Also ganz so komplex wird es nicht sein, aber es ist ein Ansatz (siehe Anhang).

Folgende Struktur:
Code:
classes/Interceptor/
classes/Interceptor/Abstract
classes/Interceptor/CoffeeBreak.php
classes/Interceptor/HolidayReplacement.php
classes/Database.php
classes/Employee.php
classes/EventDispatcher.php
classes/Listener.php
classes/Team.php
data/employee.txt
data/team_has_employee.txt
data/team.txt
functions/selectHelper.php
ajax.php
init.php
index.php
Ich habe der Einfachheit halber nur zwei Drop-Downs genommen (index.php): Team und Employee. Jedes Team hat Mitarbeiter, jeder Mitarbeiter ist ins Teams. Wird eine Auswahl getätigt, wird diese per AJAX übermittelt (an ajax.php). Diese holt bei Auswahl des Mitarbeiters dessen Teams und bei Auswahl von einem Team dessen Mitarbeiter. Nach der jeweiligen Auswahl wird ein Event angetriggert. Eigentlich ist es nur ein Methodenaufruf:
PHP-Code:
<?php
$dispatcher
->trigger("onSelectEmployee"$employee);
?>
Vorher wurden aber Listener auf diesen Event registriert:
PHP-Code:
<?php
// create listener
$holidayReplacement Interceptor_Abstract::factory("holidayReplacement"$database);
$coffeeBreak        Interceptor_Abstract::factory("coffeeBreak"$database);

// create event dispatcher and register listeners
$dispatcher = new EventDispatcher();
$dispatcher->listen("onPublishEmployees"$holidayReplacement);
$dispatcher->listen("onSelectEmployee",   $coffeeBreak);
?>
Letztlich landet also der ausgewählte Mitarbeiter beim Kaffeepausen-Check. Bei jeder ungeraden Minute der aktuellen Uhrzeit ist Katrin jetzt beispielsweise mal eben Kaffee holen.
Weiterhin wird Peter grundsätzlich durch Steffen ersetzt, weil der im Urlaub ist, das übernimmt die Klasse Interceptor_HolidayReplacement.php.

Das Beispiel hat vermutlich garnichts mit deinen Ausnahmen zu tun, aber letztlich ist das Schema das gleiche. Du bekommst eine Auswahl aus dem Dropdown und musst entsprechend Daten zurückliefern, die du aber möglicherweise vorher nochmal manipulieren musst, wenn bestimmte Zustände zutreffen. Durch die Interceptors geht das relativ einfach, auch wenn die konkrete Manipulation der Daten sicherlich professioneller umgesetzt werden könnte (ist eben ein schneller Hack).

Für dich interessant ist eigentlich nur der Event-Dispatcher, die Interceptor-Klassen und die Zuordnung in ajax.php.

Hier mal die interessanten Parts:
ajax.php
PHP-Code:
<?php
require "./init.php";

$database = new Database(_DATABASE_DIR);

// create listener
$holidayReplacement Interceptor_Abstract::factory("holidayReplacement"$database);
$coffeeBreak        Interceptor_Abstract::factory("coffeeBreak"$database);

// create event dispatcher and register listeners
$dispatcher = new EventDispatcher();
$dispatcher->listen("onPublishEmployees"$holidayReplacement);
$dispatcher->listen("onSelectEmployee",   $coffeeBreak);

$teamId     = (int)@$_GET["team"];
$employeeId = (int)@$_GET["employee"];
$focus      = (string)@$_GET["focus"];

$data null;

if (
$focus == "team") {
    
$data = array("employee" => array("-"));
    if (
$teamId 0) {
        
$team $database->getTeam($teamId);
        
$dispatcher->trigger("onSelectTeam"$team);
        
$dispatcher->trigger("onPublishEmployees"$team->employees);
        foreach (
$team->employees as $employee) {
            
$data["employee"][$employee->id] = $employee->name;
        }
    }
} elseif (
$focus == "employee") {
    
$data = array("team" => array("-"));
    if (
$employeeId 0) {
        
$employee $database->getEmployee($employeeId);
        
$dispatcher->trigger("onSelectEmployee"$employee);
        
$dispatcher->trigger("onPublishTeams"$employee->teams);
        foreach (
$employee->teams as $team) {
            
$data["team"][$team->id] = $team->name;
        }
    }
}
$data["message"] = implode(PHP_EOL$dispatcher->getMessages());

header("Content-Type: text/json; charset=UTF-8"true);
echo 
json_encode($data);
Interceptor_CoffeeBreak.php
PHP-Code:
<?php
class Interceptor_CoffeeBreak extends Interceptor_Abstract
{
    public function 
notify(EventDispatcher $dispatcher$event, &$subject)
    {
        
$employee $subject;
        if (
$employee->name == "Katrin" && date("i") % == 1) {
            
$dispatcher->addMessage("Katrin macht grad Kaffeepause, ist aber gleich zurück.");
        }
    }
}
EventDispatcher.php
PHP-Code:
<?php
class EventDispatcher
{
    protected 
$_events = array();
    protected 
$_messages = array();
    
    public function 
listen($eventListener $listener)
    {
        if (!
array_key_exists($event$this->_events)) {
            
$this->_events[$event] = array();
        }
        
$this->_events[$event][] = $listener;
    }
    
    public function 
trigger($event, &$subject)
    {
        if (!isset(
$this->_events[$event])) {
            return;
        }
        foreach (
$this->_events[$event] as $listener) {
            
$listener->notify($this$event$subject);
        }
    }
    
    public function 
addMessage($message)
    {
        
$this->_messages[] = $message;
    }
    
    public function 
getMessages()
    {
        return 
$this->_messages;
    }
}
Miniaturansicht angehängter Grafiken
clevere-und-skalierbare-datenstruktur-fuer-verknuepfte-select-felder-screenshot.jpg  
Angehängte Dateien
Dateityp: zip event.zip (6,4 KB, 19x aufgerufen)

Geändert von Chriz (03.12.2009 um 23:34 Uhr).
Chriz ist gerade online   Mit Zitat antworten
Alt 04.12.2009, 00:20  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 35.994
PHP-Kenntnisse:
Fortgeschritten
nikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunftnikosch hat eine strahlende Zukunft
Standard

PHP-Code:
if ($employee->name == "Katrin" && date("i") % == 1) {
            
$dispatcher->addMessage("Katrin macht grad Kaffeepause, ist aber gleich zurück.");
        } 
Großartig
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 04.12.2009, 10:58  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.269
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Im Prinzip kannst du natürlich auch auf Events verzichten und alle Ergebnisse an den Interceptor-Sammler übergeben. Nur muss der halt wissen, was für ein Ergebnis das ist, sonst wird Peter auch nicht zur Weihnachtsfeier eingeladen, wenns ans Verschicken der Kärtchen geht
Chriz ist gerade online   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
mysql select von 2 tabellen mit variablen felder, zeiträumen, saisons und einer ber.. xavie PHP Tipps 2009 3 12.01.2009 15:31
select felder Templerschaf PHP Tipps 2008 3 04.11.2008 21:22
Select 2 verschiedene Felder aus einer Tabelle/Datenbank DDogg Datenbanken 5 26.05.2006 19:23
select felder HTML, Usability und Barrierefreiheit 5 08.12.2005 16:10
2 Select Felder identifizieren HTML, Usability und Barrierefreiheit 4 29.06.2005 16:18
Warum manchmal "`" um Felder bei Select Unbekanntes_Pferd Datenbanken 4 02.05.2005 14:11
[Erledigt] 2 mal select 1 form PHP-Fortgeschrittene 1 01.09.2004 20:13

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php datenstruktur, php datenstrukturen, php ajax verknüpfte select felder, datenstruktur urlaub, verknüpfte selects, select felder designen, zend_form_select, javascript daten strukturieren, html select struktur, verknüpfte select, $dispatcher->trigger, javascript select feld ändern keine doppelte auswahl, if php mit select feld, javascript verknüpfte select, php verknüpfte select felder, selectfelder php, select in datenstruktur, datesntrukturen php, verknüpfte select html, php ergebnis von event dispatchern

Alle Zeitangaben in WEZ +2. Es ist jetzt 00:36 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum