MB: Ist PDOStatement::setFetchMode Overloading?

moin,

ich will mir meine Database-Klasse erneuern und habe dazu eine neues Property PDO::FETCH_CLASS neben PDO::FETCH_OBJ in meiner gebauten Methode verwendet.

ich bin etwas stutzig geworden weil man ja in PHP kein Overloading betreiben sondern nur Parameter Defaults verwenden darf wie z.B. function foobar( $param1 = 'tok', $param2 = 'qux' ) {} Ich kann ja beliebig viele Parameter mit Wert null angeben und die Funktion aufrufen, das funzt. Anders die Methode PDOStatement::setFetchMode😕.

public PDOStatement::setFetchMode ( int $mode ) : bool
public PDOStatement::setFetchMode ( int $PDO::FETCH_COLUMN , int $colno ) : bool
public PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : bool
public PDOStatement::setFetchMode ( int $PDO::FETCH_INTO , object $object ) : bool

Hier einen Auszug pdostatement.setfetchmode.php aus php.net

könnten da Try-Catch-Blöcke, welches die Parameter behandelt, in dieser setFetchMode enthalten sein? Dann ergibt es für mich einen Sinn sonst bin ich überfragt.

Ich möchte saubere Codes schreiben können für eine Wiederverwendung.

try {
  $statement = self::$_handler->prepare( $query );
  $statement->setFetchMode( /* wie gefetcht */ );
  $statement->execute( $params );
  $result = $cargo( $statement );
} catch( PDOException $ex ) {
  throw new PDOException( $ex );
}

Wenn ich jetzt $statement->setFetchMode( $mode, null, null ); mit PDO::FETCH_ASSOC schreibe meckert er. Wenn ich den Parameter Wert null weglasse funzt es.

Warning:  PDOStatement::setFetchMode(): SQLSTATE[HY000]: General error: fetch mode doesn't allow any extra arguments [...]

ich bin einwenig überfordert

lgmb

  1. Tach!

    ich bin etwas stutzig geworden weil man ja in PHP kein Overloading betreiben sondern nur Parameter Defaults verwenden darf

    Das ist eher eine Frage des Könnens. Man kann es einfach nicht, weil Methoden eindeutig benannt sein und einzig müssen. Man kann andererseits in der Deklaration einer Funktion sämtliche Parameterangaben weglassen und lediglich über Function handling Functions auf die zur Laufzeit tatsächlich übergebenen Parameterwerte zugreifen.

    public PDOStatement::setFetchMode ( int $mode ) : bool
    
    public PDOStatement::setFetchMode ( int $PDO::FETCH_COLUMN , int $colno ) : bool
    
    public PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) : bool
    
    public PDOStatement::setFetchMode ( int $PDO::FETCH_INTO , object $object ) : bool
    

    Hier einen Auszug pdostatement.setfetchmode.php aus php.net

    könnten da Try-Catch-Blöcke, welches die Parameter behandelt, in dieser setFetchMode enthalten sein?

    Unwahrscheinlich. PHP ist ja nicht selbst in PHP geschrieben, und muss sich deshalb nicht zwingend an seine eigenen Syntaxregeln halten. So ist es möglich, dass Sprachkonstrukte existieren, die wie Funktionen aussehen, aber sich nicht wie andere PHP-Funktionen verhalten. Nur so können sie ihre Aufgabe erfüllen, ohne an den üblichen Mechanismen von PHP zu scheitern. Die Rede ist von isset() und empty(). Beide bekommen beim Aufrufen nicht lediglich den Wert des vorab aufgelösten Ausdrucks übergeben, sondern sie können auf den Variablennamen selbst zugreifen, um nach ihm in der internen Variablenverwaltung suchen zu können. Auf diese Weise können Fehlermeldungen beim Zugreifen auf nicht existierende Variablen vermieden werden. Andererseits (bei empty() vor PHP 5.5) können auch spezielle Meldungen generiert werden, wenn andere Ausdrücke statt nur Variablen übergeben werden. Diese Ausdrücke würden sonst vom übliche Mechanismus in ihren Wert aufgelöst werden, bevor sie empty() zu Gesicht bekommen könnte.

    In deinem Fall ist es wohl eher so, dass das PHP-Handbuch sozusagen Phyntasie-Syntax zeigt. Das tut es bereits seit langem, wenn es die Tyen der erwarteten Parameter anzeigt, noch lange bevor solche Type Hints für PHP-Scripts selbst verfügbar waren. Auch nicht existierende Pseudotypen findet man in diesen Funktionsbeschreibungen.

    Konkret wird es wohl eher so sein, dass der interne C-Code für diese Funktion lediglich bis zu drei generische Parameter (also ohne konkrete Typvorgabe) entgegennimmt und dann selbst entscheidet, wie sie ausgewertet werden.

    Ich möchte saubere Codes schreiben können für eine Wiederverwendung.

    Ja, was konkret hindert dich daran, die Funktion auf die eine oder (exklusives Oder) andere Weise aufzurufen, je nachdem, welchen Mode du einstellen möchtest?

    Wenn ich jetzt $statement->setFetchMode( $mode, null, null ); mit PDO::FETCH_ASSOC schreibe meckert er. Wenn ich den Parameter Wert null weglasse funzt es.

    Wen du verschiedene Fetch-Modes verwenden möchtest, diese aber über lediglich eine Funktion/Methode einstellen lassen möchtest, muss du letztlich genauso flexibel arbeiten und bis zu 4 Funktionsaufrufe darin unterbringen, und zu einem von ihnen je nach Mode verzweigen.

    dedlfix.

  2. Lieber MB,

    ich will mir meine Database-Klasse erneuern

    warum nicht so?

    class MyPDO {
      protected $pdo; // \PDO object
      public function __construct($dsn, $user=NULL, $pass=NULL, $driver_options=NULL) {
        $this->pdo = new PDO($dsn, $user, $pass, $driver_options);
        // ...
      }
    }
    

    So kannst Du alle Deine PDO-Objekte (auch PDOStatement etc.) nach Belieben erweitern.

    Liebe Grüße,

    Felix Riesterer.

    1. moin,

      ich will mir meine Database-Klasse erneuern

      warum nicht so?

      [...]

      So kannst Du alle Deine PDO-Objekte (auch PDOStatement etc.) nach Belieben erweitern.

      hab ich ja konstruiert mit einer DatabaseModel Klasse die Driver, Host, Charset, User, Password und Options beinhaltet und per Constructor Injection diese Werte als Objekt an die eigentliche Database mit statischen Methoden übergibt. Mir gehts um anschaulicher, wiederverwendbarer Code was mich vor ein Problem stellt wie ich diese Fetchts verwenden kann. Über ein internes Closure komme ich an die Daten ran.

      Interface DatabaseInterface {
          
          /**
           * @param type $category
           * @param type $constant
           */
          public static function setAttributes( int $category, $constant ) : void;
          
          /**
           * @param string $query
           * @param array $params
           */
          public static function get( string $query, array $params = [] );
          
          /**
           * @param string $query
           * @param array $params
           */
          public static function all( string $query, array $params = [] ) : array;
          
          /**
           * @param string $query
           * @param array $params
           */
          public static function send( string $query, array $params = [] ) : bool;
          
          /**
           * 
           */
          public static function fetchNum() : bool;
          
          /**
           * 
           */
          public static function fetchAssoc() : bool;
          
          /**
           * 
           */
          public static function fetchObject() : bool;
          
          /**
           * 
           */
          public static function fetchClass( string $class_name ) : bool;
      }
      

      lgmb

  3. ich bin etwas stutzig geworden weil man ja in PHP kein Overloading betreiben

    Was in PHP (noch) nicht geht ist Overloading von Operatoren, Methoden jedoch kannst Du selbstverständlich überlagern in Deinen eigenen Klassenerweiterungen. So ist ein StatementHandler eine Instanz der Klasse PDOStatement und solange Du diese Klasse erweitern kannst ist es auch möglich deren Methoden zu überschreiben. MFG

    1. moin,

      ich bin etwas stutzig geworden weil man ja in PHP kein Overloading betreiben

      Was in PHP (noch) nicht geht ist Overloading von Operatoren, Methoden [...]

      Das ist mir bewusst. Ich war auf anderen Wege dieses Problem anzupacken, und da habe ich diese möglichkeit des Überschreibens aus den augen verloren. Danke das du mich dran erinnerst ;-). Vielleicht wird es über das Überschreiben das Problerm lösen. Bedankt

      lgmb

  4. moin,

    ich hab in der Methode self::transmission( callable $cargo, string $query, array $params = [] ) zusätzlich ein weitere Methode geschrieben self::getFetchMode( PDOStatement $statement ) : PDOStatement die vom private array Property self::$fetchMode in den public Methoden self::fetchXXX() : bool ihren FETCH_MODE bekommt. Danke aber viel mals das ihrt mich dahin gebracht habt. Code könnt ihr gern in einer PN von mir haben.

    lgmb