php-resource



Zurück   PHP-Scripte PHP-Tutorials PHP-Jobs und vieles mehr > Entwicklung > PHP Developer Forum
 

Login

 
eingeloggt bleiben
star Jetzt registrieren   star Passwort vergessen
 

 

 


PHP Developer Forum Hier habt ihr die Möglichkeit, eure Skriptprobleme mit anderen Anwendern zu diskutieren. Seid so fair und beantwortet auch Fragen von anderen Anwendern. Dieses Forum ist sowohl für ANFÄNGER als auch für PHP-Profis! Fragen zu Laravel, YII oder anderen PHP-Frameworks.

Antwort
 
LinkBack Themen-Optionen Thema bewerten
  #1 (permalink)  
Alt 24-08-2013, 16:48
Chrissi007
 Registrierter Benutzer
Links : Onlinestatus : Chrissi007 ist offline
Registriert seit: Jul 2004
Beiträge: 49
Chrissi007 ist zur Zeit noch ein unbeschriebenes Blatt
Chrissi007 eine Nachricht über ICQ schicken
Standard Methode auf Objekt anwenden

Hi zusammen,

ich habe gerade leider ein ziemlich kniffliges Problem. Bei der Lösungssuche im Internet bin ich auch schon über Begriffe wie Strategy Pattern oder Decorator Pattern gestolpert, bin mir aber nicht sicher, ob das wirklich das Mittel zum Zweck ist.

Vorab, als Vergleich, was ich erreichen will: Auf php.net gibt es zu mysqli_fetch_array einen kleinen Code Snippet, siehe (ich habs etwas gekürzt):

PHP-Code:
$mysqli = new mysqli("localhost""my_user""my_password""world");
$query "SELECT Name, CountryCode FROM City ORDER by ID LIMIT 3";
$result $mysqli->query($query);
$row $result->fetch_array(); 
Es wird in diesem Beispiel eine Methode fetch_array() auf das Objekt $result angewendet. Das ist letzten Endes genau das, was ich auch erreichen will. Ich will eine Methode, die ich jederzeit auf beliebig viele Objekte anwenden.

Was ich bisher gebastelt habe:

Klasse:

PHP-Code:
class mysqldb extends mysqli
{
    
/**
     * DB Verbindung herstellen und Charset setzen
     */
    
public function __construct()
    {    
        
// DB Verbindung
    
}
    
    
/**
     * Führt die Datenbankanfrage durch
     */
    
public function query ($sql)
    {
        
$this->result parent::query($sql);
        return 
$this;
    }
    
    
    
/**
     * Liefert alle Datensätze der abgefragten SQL Query
     */
    
public function getAll ()
    {        
        while (
$row $this->result->fetch_array())
        {
            
$data[] = $row;
        }
        return 
$data;
    }

So, jetzt kommts zu dem Problem-Part:

PHP-Code:
$mysqldb = new mysqldb();

$result_a $mysqldb->query('SELECT bla');
$result_b $mysqldb->query('SELECT blub');

$data_a $result_a->getAll();
$data_b $result_b->getAll();

var_dump($data_a);
var_dump($data_b); 
Nur $data_b ist mit Inhalten gefüllt. $data_a ist leer. Das liegt an der Funktionsweise von getAll(); Eigentlich soll die Methode alle Datensätze der Datenbankabfrage liefern, über das Objekt, über das es aufgerufen wird.
Also:
PHP-Code:
$result_a->getAll(); // soll alle Datensätze der Query A liefern.
$result_b->getAll(); // soll alle Datensätze der Query B liefern. 
Es wird aber aufgrund der Implementierung von $this->result->fetch_array() in der Methode getAll() logischerweise immer nur das Result der zuletzt durchgeführten Datenbankanfrage verwendet, nicht aber des Results, auf das ich mittels dem Pfeil -> verweise.

Meine Frage ist: Wie muss ich die Methode getAll() umgestalten, dass ich sie nach dem gleichen Prinzip verwenden kann, wie die php-Entwickler das in ihrem Beispiel auf der Php-Seite mittels folgendem Code machen:
PHP-Code:
$row $result->fetch_array(); 
Aus meiner Sicht erlaubt solch eine Arbeitsweise eine enorme Flexibilität und ich will in jedem Fall eine saubere Lösung. Klar gibt es Workaround (ich könnte die betroffene Query z.B. als Argument der Methode übergeben), aber ich will in diesem Fall mal ausnahmsweise was gescheites auf die Beine stellen

Ich hab mir schon einige Tutorials bezüglich Decorator Patterns angesehen, aber da werden plötzlich viele Klassen ins Leben gerufen und ich bin mir nicht ganz sicher, ob das auch die Korrekte arbeitsweise in diesem Fall ist. Weil in diesem Fall müsste ich ja dann pro Query ebenfalls eine eigene Klasse erstellen, oder? a la:

PHP-Code:
$mysqldb_a = new mysqldb;
$result_a $mysqldb_a->query ("SELECT bla...");

$mysqldb_b = new $mysqldb;
$result_b $mysqldb_b->query("SELECT blubb..."); 
Dadurch würden dann auch etliche DB-Connects durchgeführt werden, weil der Konstruktor der Klasse mysqldb logischerweise die Datenbankverbindung herstellt.

Fragen über Fragen, über jegliche Hilfe, sei es auch nur ein kleiner Denkanstoß, wäre ich wahnsinnig dankbar.

Vielen Dank soweit!
__________________
Grüße, Chrissi
Our Dreams are Wings

Geändert von Chrissi007 (24-08-2013 um 16:51 Uhr)
Mit Zitat antworten
  #2 (permalink)  
Alt 24-08-2013, 17:25
wahsaga
  Moderator
Links : Onlinestatus : wahsaga ist offline
Registriert seit: Sep 2001
Beiträge: 25.236
wahsaga befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von Chrissi007 Beitrag anzeigen
Nur $data_b ist mit Inhalten gefüllt. $data_a ist leer. Das liegt an der Funktionsweise von getAll()
Nein, das liegt viel mehr daran, dass du mit dem zweiten Aufruf von query() die Variable $this->query überschrieben hast.

Zitat:
Es wird aber aufgrund der Implementierung von $this->result->fetch_array() in der Methode getAll() logischerweise immer nur das Result der zuletzt durchgeführten Datenbankanfrage verwendet, nicht aber des Results, auf das ich mittels dem Pfeil -> verweise.
Da du immer auf der selben Objektinstanz arbeitest, verweisen auch deine „Pfeile“ immer auf die gleiche Query bzw. das gleiche result set.

Zitat:
Meine Frage ist: Wie muss ich die Methode getAll() umgestalten
Nicht diese eine Methode ist das Problem, sondern die ganze Klasse, bzw. wie du sie benutzt.

Du erzeugst nur eine einzige Instanz der Klasse, und gibst dann auch noch diese selber zurück (in query() mit return $this), was ungewöhnlich und auch nicht zielführend ist.

Was ist denn der Rückgabetyp der Methode mysqli::query laut Handbuch …?

Zitat:
Weil in diesem Fall müsste ich ja dann pro Query ebenfalls eine eigene Klasse erstellen, oder?
Keine eigene Klasse, sondern mehrere Instanzen der Klasse, also mehrere Objekte.

Zitat:
Dadurch würden dann auch etliche DB-Connects durchgeführt werden, weil der Konstruktor der Klasse mysqldb logischerweise die Datenbankverbindung herstellt.
Dann lass ihn vorher prüfen, ob er überhaupt eine neue Verbindung herstellen muss, oder schon eine geöffnete vorliegen hat.

Zitat:
aber ich will in diesem Fall mal ausnahmsweise was gescheites auf die Beine stellen
Wozu das ganze überhaupt? Das einzige, was deine Klasse momentan macht, ist MySQLi zu „kapseln“ und eine getAll-Methode hinzu zu fügen. Wenn diese der Hauptzweck des ganzen ist – warum nimmst du dann nicht gleich PDO, das bringt bereits eine fetchAll-Methode mit …?

(Außerdem hast du die Absicherung gegen SQL Injection noch vernachlässigt in deiner Klasse – prepared statements nehmen dir auch das ab.)
__________________
I don't believe in rebirth. Actually, I never did in my whole lives.
Mit Zitat antworten
  #3 (permalink)  
Alt 24-08-2013, 22:36
Chrissi007
 Registrierter Benutzer
Links : Onlinestatus : Chrissi007 ist offline
Registriert seit: Jul 2004
Beiträge: 49
Chrissi007 ist zur Zeit noch ein unbeschriebenes Blatt
Chrissi007 eine Nachricht über ICQ schicken
Standard

Hey,

vielen Dank für deine Antwort!

Zitat:
Was ist denn der Rückgabetyp der Methode mysqli::query laut Handbuch …?
Laut Handbuch handelt es sich um ein Objekt. Deswegen war dort auch mein Gedanke, dass ich eine Methode auf das Objekt anwenden möchte.

Zitat:
Wozu das ganze überhaupt? Das einzige, was deine Klasse momentan macht, ist MySQLi zu „kapseln“ und eine getAll-Methode hinzu zu fügen. Wenn diese der Hauptzweck des ganzen ist – warum nimmst du dann nicht gleich PDO, das bringt bereits eine fetchAll-Methode mit …?
Bei mir gings in diesem Fall jetzt eher so ums Prinzip. Das Handbuch zu mysqli_result hat mich da so ein bisschen in Versuchung geführt. Dort wird auch mittels
PHP-Code:
$row $result->fetch_array() 
auf ein Objekt zugegriffen. Und, wenn ich es richtig verstehe, wurde dieses Objekt via
PHP-Code:
 $result $mysqli->query($query); 
erzeugt. Also es handelt sich bei $result nicht um eine Klasse, die instanziert wurde(?), sondern nur um ein Objekt. Ich würde soetwas auch gerne mit einer eigenen Klasse und Methoden hinkriegen, nur fehlt mir hierzu der Gedanke, wie man soetwas zu realisieren hat? Wenn ich meinen Code von oben direkt nur mit der mysqli-Klasse aufrufe, dann funktioniert das Script problemlos (also quasi nicht meine eigene Klasse ins Spiel bring...).



Was meinst du, wäre es sinnvoll für jede Query eine eigene Instanz der Klasse aufzurufen (für den Fall, dass dort noch weitere, brauchbare Methoden hinterlegt sind)?

Wäre es möglich, in diesem Fall die Datenbankverbindung in der Klasse aufbauen zu lassen (z.B. im Konstruktor) und im Fall einer Instanzierung der Klasse zu überprüfen, ob die Datenbankverbindung bereits durch eine andere Instanz eröffnet würde? (Ist es möglich quasi ein Objekt einer anderen Instanz automatisch in die nächste Instanz der selben Klasse zu importieren?) Oder sollte ich in diesem Fall die DB-Verbindung außerhalb der Klasse aufbauen und via global die DB-Verbindung in die Klasse reinholen?
Entspräche das noch dem Sinn des objektorientierten Programmierens?

Sorry für die vielen Fragen...
__________________
Grüße, Chrissi
Our Dreams are Wings
Mit Zitat antworten
  #4 (permalink)  
Alt 25-08-2013, 08:32
combie
 PHP Expert
Links : Onlinestatus : combie ist offline
Registriert seit: May 2006
Beiträge: 3.296
combie wird schon bald berühmt werden
Standard

Zitat:
dass ich eine Methode auf das Objekt anwenden möchte.
Man kann keine "Methoden auf Objekte anwenden"!
Zumindest ist das eine sehr verschrobenen Sicht auf die Dinge.


Methoden sind Bestandteile eines Objektes.
Und diese kann man aufrufen!

Eine Bessere Sicht wäre:
Durch den Methodenaufruf sendet man dem Objekt eine Nachricht.


Zitat:
Wäre es möglich, in diesem Fall die Datenbankverbindung in der Klasse aufbauen zu lassen (z.B. im Konstruktor) und im Fall einer Instanzierung der Klasse zu überprüfen, ob die Datenbankverbindung bereits durch eine andere Instanz eröffnet würde? (Ist es möglich quasi ein Objekt einer anderen Instanz automatisch in die nächste Instanz der selben Klasse zu importieren?) Oder sollte ich in diesem Fall die DB-Verbindung außerhalb der Klasse aufbauen und via global die DB-Verbindung in die Klasse reinholen?
Entspräche das noch dem Sinn des objektorientierten Programmierens?
Mache dich mit dem "Dependency Injection Design Pattern" vertraut. Das wird deine Sorgen lösen/mildern.
__________________
Wir werden alle sterben
Mit Zitat antworten
  #5 (permalink)  
Alt 25-08-2013, 13:53
Chrissi007
 Registrierter Benutzer
Links : Onlinestatus : Chrissi007 ist offline
Registriert seit: Jul 2004
Beiträge: 49
Chrissi007 ist zur Zeit noch ein unbeschriebenes Blatt
Chrissi007 eine Nachricht über ICQ schicken
Standard

Hi,

vielen Dank euch beiden soweit. Ich werd mich mal auf die Suche begeben...
__________________
Grüße, Chrissi
Our Dreams are Wings
Mit Zitat antworten
  #6 (permalink)  
Alt 25-08-2013, 14:16
Chrissi007
 Registrierter Benutzer
Links : Onlinestatus : Chrissi007 ist offline
Registriert seit: Jul 2004
Beiträge: 49
Chrissi007 ist zur Zeit noch ein unbeschriebenes Blatt
Chrissi007 eine Nachricht über ICQ schicken
Standard

Für andere, die evtl. mal an einem ähnlichen Problem hängen: Bin gerade über ein interessantes Tutorial gestolpert, zum Nachlesen: The Dependency Injection Design Pattern in PHP 5 - PHP
__________________
Grüße, Chrissi
Our Dreams are Wings
Mit Zitat antworten
  #7 (permalink)  
Alt 26-08-2013, 12:32
Guenni61
 Registrierter Benutzer
Links : Onlinestatus : Guenni61 ist offline
Registriert seit: Nov 2011
Ort: Viersen
Beiträge: 128
Guenni61 befindet sich auf einem aufstrebenden Ast
Standard

Hi Chrissi007,

ich denke mal, es liegt daran, dass du nicht auf eine klasseneigene Variable verweist. Statt . . .
PHP-Code:
. . .
$data[] = $row;
. . .
return 
$data
. . . solltest du es so formulieren . . .
PHP-Code:
. . .
$this->data[] = $row;
. . .
return 
$this->data
Die Variable $data sollte im Funktionsaufruf vor einer Neubelegung auch gelöscht werden, sonst sind die Abfragergebnisse
einer vorherigen Abfrage auch noch darin enthalten. Der Vollständigkeit halber würde ich diese Variablen auch in der Klasse deklarieren.
PHP-Code:
<?php
class mysqldb extends mysqli
{
    private 
$result;
    private 
$data = array();
  
/**
     * DB Verbindung herstellen und Charset setzen
     **/
    
public function __construct()
    {    
        
parent::__construct('localhost','guenni','guenni','test');
    }
    
    
/**
     * Führt die Datenbankanfrage durch
     **/
    
public function query ($sql)
    {
        
//Vor (neuer) Abfrage $result löschen
        
$this->result NULL;
        
$this->result parent::query($sql);
        return 
$this->result;
    }
    
    
    
/**
     * Liefert alle Datensätze der abgefragten SQL Query
     **/
    
public function getAll ()
    {        
        
//Vor (neuer) Abfrage $data löschen, sonst sind vorher abgefragte Daten
       //auch noch im Array enthalten
       
$this->data NULL;
       
//Konstante MYSQLI_ASSOC liefert ein assoziatives Array
       
while ($row $this->result->fetch_array(MYSQLI_ASSOC))
        {
            
$this->data[] = $row;
        }
        return 
$this->data;
    }
}  
 
?>
PHP-Code:
<?php 
$db 
= new mysqldb;

 
//Abrage Tabelle A
$result_a $db->query('select * from tabelle2 where id = 5');
$data_a $db->getAll();

 
//Abrage Tabelle B
$result_b $db->query('select * from tabelle5 where id > 8 and id < 12');
$data_b $db->getAll();

echo 
'<pre>';
echo 
'var_dump data_a<br>';
var_dump($data_a);
echo 
'var_dump data_b<br>';
var_dump($data_b);
?>
Gruß
Günni

PS.: Das funktioniert zwar so, wie du es erhofft hast, ob es allerdings sinnvoll (praktikabel) ist, muß ich mich den Vorrednern anschließen.
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Das Objekt unterstützt diese Eigenschaft oder Methode nicht der_meier_hans HTML, JavaScript, AJAX, jQuery, CSS, Bootstrap, LESS 11 26-02-2008 17:47
wie methode eines objekts in objekt ansprechen? dr_rimmel PHP Developer Forum 6 04-09-2007 17:23
[PHP5] Statische methode aus anderem Objekt aufrufen. IchBinIch PHP Developer Forum 2 23-02-2007 17:50
Fehler: Objekt unterstützt Eingenschaft oder Methode nicht Burnout HTML, JavaScript, AJAX, jQuery, CSS, Bootstrap, LESS 9 15-12-2006 23:03
function () objekt unterstützt methode nicht ?!? JSkrok HTML, JavaScript, AJAX, jQuery, CSS, Bootstrap, LESS 3 15-04-2003 10:05

Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre 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


PHP News

ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlicht
ebiz-trader 7.5.0 mit PHP7 Unterstützung veröffentlichtDie bekannte Marktplatzsoftware ebiz-trader ist in der Version 7.5.0 veröffentlicht worden.

28.05.2018 | Berni

Wissensbestand in Unternehmen
Wissensbestand in UnternehmenLebenslanges Lernen und Weiterbilden sichert Wissensbestand in Unternehmen

25.05.2018 | Berni


 

Aktuelle PHP Scripte

PHP Server Monitor

PHP Server Monitor ist ein Skript, das prüft, ob Ihre Websites und Server betriebsbereit sind.

11.09.2018 Berni | Kategorie: PHP/ Security
PHP WEB STATISTIK ansehen PHP WEB STATISTIK

Die PHP Web Statistik bietet Ihnen ein einfach zu konfigurierendes Script zur Aufzeichnung und grafischen und textuellen Auswertung der Besuchern Ihrer Webseite. Folgende zeitlichen Module sind verfügbar: Jahr, Monat, Tag, Wochentag, Stunde Folgende son

28.08.2018 phpwebstat | Kategorie: PHP/ Counter
Affilinator - Affilinet XML Produktlisten Skript

Die Affilinator Affilinet XML Edition ist ein vollautomatisches Skript zum einlesen und darstellen der Affili.net (Partnerprogramm Netzwerk) Produktlisten und Produktdaten. Im Grunde gibt der Webmaster seine Affilinet PartnerID ein und hat dann unmittelb

27.08.2018 freefrank@ | Kategorie: PHP/ Partnerprogramme
 Alle PHP Scripte anzeigen

Alle Zeitangaben in WEZ +2. Es ist jetzt 09:07 Uhr.