2016-04-16 11 views
0

Ich habe eine benutzerdefinierte Befehlsklasse unter einem DB-Abstraktionsbündel, das ich verwende, um die Modellobjekte zu generieren, die für PDO :: FETCH_CLASS benötigt werden. Funktioniert ziemlich ähnlich zu Doctrine-Modellen. Das Problem, mit dem ich konfrontiert bin, ist, dass ich den Dienst für die PDO-Instanz abrufen muss, damit ich ihn für die generierten Klassen wiederverwenden kann. Gibt es eine Möglichkeit, etwas aus dem Symfony-Bereich zu injizieren, um den Dienstparameter zu erhalten?Wie kann ich auf Symfony-Containerparameter in benutzerdefinierten Klassen zugreifen?

Der Befehl Ich php bin/console pdo:generate:model <NameOfBundle> ausführen, legt ein Base/Peer-Modell (ähnlich Propel) im Stammverzeichnis des Bundles in einem Verzeichnis namens Model.

Unten finden Sie ein Beispiel für eines der DB Peer-Modell generiert:

namespace Ode\AppBundle\Model; 

use Ode\AppBundle\Model\HflogsBase; 
use Symfony\Component\DependencyInjection\ContainerAwareInterface; 
use Symfony\Component\DependencyInjection\ContainerInterface; 

class Hflogs extends HflogsBase implements \JsonSerializable, ContainerAwareInterface { 
    private $container; 

    public function __construct() { 
     parent::__construct(); 
    } 

    public function setContainer(ContainerInterface $container = null) { 
     $this->container = $container; 
    } 

    public function frequency() { 
     return number_format($this->frequency, 2, '.', ''); 
    } 

    /** 
    * @todo Run another query on the database to acquire a relational element 
    */ 

    public function getPdoInstance() { 
     $pdo = $this->container->get('ode_pdo.db'); 
    } 
} 

Bitte entschuldigen Sie meine Unwissenheit von Symfony Struktur, aber ich bin zu einem vollständigen Verlust auf, wie meine eigenen Klassen zu erhalten, sagte inherit Struktureigenschaften.

UPDATE 1

Per Anfrage hier ist das Basismodell Klasse:

namespace Ode\AppBundle\Model; 

class HflogsBase { 
    const TABLE_NAME = 'hflogs'; 
    const MODEL_NAME = 'Ode\AppBundle\Model\Hflogs'; 

    public $id; 
    public $frequency; 
    public $mode; 
    public $description; 
    public $time_on; 
    public $time_off; 
    public $lat; 
    public $lng; 
    public $user_id; 
    public $submitted; 

    const COLUMNS = 'a.id,a.frequency,a.mode,a.description,a.time_on,a.time_off,a.lat,a.lng,a.user_id,a.submitted'; 

    public function __construct() {} 
} 

UPDATE 2

Statt die Kommentare unter einem anderen Benutzer der Sprengung gefragt, wie ich die instanziiert Peer-Model-Klasse. Ich benutze es im Controller als PDO-Klassen-Typ für \ PDO: FETCH_CLASS. In PDO wird das Objekt instanziiert und alle Zeilenwerte aus einer Abfrage gefüllt, so dass ich stark getippte Ergebnisse aus der Datenbank eingegeben habe (es reduziert die Zeit, die benötigt wird, um lose gebildete Standardklassen oder assoziative Matrixergebnisse zu debuggen).

So zum Beispiel, hier ist ein Beispiel dessen, was ich in einem Controller zu tun:

class DefaultController extends Controller 
{ 

    /** 
    * @Route("/test", name="testpage") 
    */ 
    public function testAction() { 
     $logs = $this->get('ode_pdo.db')->query(" 
      SELECT " . HflogsBase::COLUMNS . " 
      FROM " . HflogsBase::TABLE_NAME . " AS a 
      WHERE a.id NOT IN (
       SELECT id 
       FROM " . HflogMetaBase::TABLE_NAME . " 
       WHERE meta_key != 'is_inactive' 
       AND meta_value = 1 
      ) 
     ")->fetchAll(\PDO::FETCH_CLASS, HflogsBase::MODEL_NAME); 


     return new Response(''); 
    } 
} 

Die MODEL_NAME Konstante von HflogsBase an den Peer-Klasse Name bezieht sich:

const MODEL_NAME = 'Ode\AppBundle\Model\Hflogs'; 
+0

können wir HflogsBase Quelle bitte sehen? –

+0

@OlivierHenry siehe aktualisierten Beitrag! – cj5

+1

Ich denke, Sie müssen ContainerAware in Ihrer HfLogBase erweitern und ContainerAwareInterface implementieren. Sie können sich die Controller-Klasse und ihre Eltern ansehen. –

Antwort

1

wenn Sie Verwenden Sie nur den Container, um den ode_pdo-Service zu erhalten. Warum geben Sie das nicht auf, indem Sie Ihre Klasse zu einem Dienst machen?

services.yml:

app.hflogs: 
    class: Ode\AppBundle\Model\Hflogs 
    arguments: ["@ode_pdo.db"] 

Und dann in der Klasse:

public function __construct($pdo) { 
    parent::__construct(); 
    $this->pdo = $pdo; 
} 
+0

Sie sagen also, dies für alle generierten Klassen zu tun? Mein Konsolenbefehl hat diese Klassen aus den Datenbanktabellen generiert, und für dieses Projekt gibt es 67 weitere Tabellen neben 'Hflogs'. – cj5

+1

Aktualisieren Sie Ihre benutzerdefinierte Befehlsklasse, die diese Modellobjekte generiert? Oder tun Sie dies in der Basisklasse, und wenn Sie es erweitern, haben Sie Zugriff darauf? – siguy85

+0

Okay, das ist eine gute Lösung, aber ich hatte gehofft, die Generierung der Klassen von der manuellen Konfiguration in der Yaml zu entkoppeln. Ich werde sehen, ob der Generatorbefehl bei der ersten Erstellung von Modellklassen etwas in die Dienstkonfiguration schreiben kann. – cj5

1

Sie können versuchen, das zu tun?

namespace Ode\AppBundle\Model; 

use Ode\AppBundle\Model\HflogsBase; 


class Hflogs extends HflogsBase { 


/** 
* 
* @var \PDO 
*/ 
private $pdo; 


public function __construct(Array $ctor_args) { 
    parent::__construct(); 
    if(count($ctor_args)){ 
     $this->pdo = $ctor_args[0]; 
    } 

} 

public function frequency() { 
    return number_format($this->frequency, 2, '.', ''); 
} 

/** 
* @todo Run another query on the database to acquire a relational element 
*/ 

public function getPdoInstance() { 
    return $this->pdo; 
} 

} 

und in Ihrem Controller:

$logs = $this->get('ode_pdo.db')->query(" 
     SELECT " . HflogsBase::COLUMNS . " 
     FROM " . HflogsBase::TABLE_NAME . " AS a 
     WHERE a.id NOT IN (
      SELECT id 
      FROM " . HflogMetaBase::TABLE_NAME . " 
      WHERE meta_key != 'is_inactive' 
      AND meta_value = 1 
     ) 
    ")->fetchAll(\PDO::FETCH_CLASS, HflogsBase::MODEL_NAME, array($this->get('ode_pdo.db'))); 
+0

Danke für diesen Vorschlag. Ich habe das berücksichtigt, aber das Hinzufügen dieser Parameter zu jeder Abfrage in der Codebasis ist zu wiederholend und umständlich für meinen Workflow. Ich schätze deine Hilfe wirklich.^1 – cj5

1

Danke, an alle, die geholfen haben, aber nach ein paar Tagen meinen Kopf gegen eine Wand schlagen, dachte ich, eine Lösung aus. In der Basismodellklasse habe ich eine geschützte Eigenschaft $pdo hinzugefügt. Im Konstrukt dieser Klasse initiiere ich es mit einer statischen Methode aus der PDOService-Klasse.

namespace Ode\PDOBundle\Services; 

class PDOService extends \PDO 
{ 
    private static $instance = null; 

    public function __construct($host, $dbname, $user, $passwd) 
    { 
     parent::__construct(
      'mysql:host=' . $host . ';dbname=' . $dbname, 
      $user, 
      $passwd 
     ); 

     self::$instance = $this; 
    } 

    public static function getInstance() { 
     return self::$instance; 
    } 
} 

Der Konsolenbefehl-Generator erzeugt nun eine Basismodell-Klasse, die wie folgt aussieht:

namespace Ode\AppBundle\Model; 

use Ode\PDOBundle\Services\PDOService; 

class HflogsBase { 
    protected $pdo; 

    const TABLE_NAME = 'hflogs'; 
    const MODEL_NAME = 'Ode\AppBundle\Model\Hflogs'; 

    public $id; 
    public $frequency; 
    public $mode; 
    public $description; 
    public $time_on; 
    public $time_off; 
    public $lat; 
    public $lng; 
    public $user_id; 
    public $submitted; 

    const COLUMNS = 'a.id,a.frequency,a.mode,a.description,a.time_on,a.time_off,a.lat,a.lng,a.user_id,a.submitted'; 

    public function __construct() { 
     $this->pdo = PDOService::getInstance(); 
    } 
} 

Es ist nicht genau die Lösung, die ich suchte, aber zumindest funktioniert es ohne zusätzliche Schritte hinzugefügt werden müssen die DBAL.

Verwandte Themen