2016-05-14 11 views
1

Ich muss einen benutzerdefinierten Filter, der einen Preis in die Benutzerwährung Präferenz konvertieren wird. So habe ich jeden Tag eine Tabelle mit den neuesten Wechselkursen aktualisiert.Zweig Erweiterung: Datenbankabfrage

Ich plane, auf diese Weise den Filter nennen {{ '200' | price}} oder {{ '200' | Preis ('USD')}}

Der Filter würde zuerst den Benutzer bevorzugt ein Plätzchen.

Dann wird es den neuesten Wechselkurs basierend auf dem Währungscode abfragen und den tatsächlichen Preis umrechnen.

Meine Frage ist, ist es in Ordnung, eine Datenbankabfrage in einer Zweig-Erweiterung (Filter hier) zu tun.

Ich muss diesen Filter 10 mal auf einer Seite aufrufen. Bedeutet das 10 weitere Anfragen?

Welche besseren Möglichkeiten würden Sie empfehlen?

Antwort

3

Ja, wenn Sie die Cache-Konfiguration für Doctrine nicht definieren, bedeutet dies, dass Sie eine Anforderung an die Datenbank senden, um die Daten jedes Mal abzurufen.

Sie können wählen, ob Sie die Umrechnungskurse abfragen, sie selbst im Cache speichern oder die Cache-Funktion von Doctrine verwenden möchten.

Symfony 2 cache Doctrine query results

Beide Wege sind besser als die Daten aus der Datenbank direkt jedes Mal abgefragt wird.

+0

Vielen Dank das ist, was ich hören musste. – Brieuc

+0

Es ist genug, statische Eigenschaft in der Erweiterung zu machen, die Wechselkurse für ganze Anfrage behalten. – malcolm

+0

Hallo @ Malcolm, ich stimme völlig zu, dass eine statische Eigenschaft eine gute Lösung ist. Wie Sie jedoch bereits erwähnten, ist es lebenslang nur eine einzige Anfrage, also denke ich, wenn der Wechselkurs in Ihrer App nicht signifikant ist und in Echtzeit aktualisiert werden muss (in diesem Fall benötigen Sie möglicherweise eine bessere Lösung als jede Anfrage) Ich denke immer noch, dass sie in den Cache stellen eine gute Lösung ist. –

2

Verwenden Sie Doktrin Ereignisse System, in diesem Fall postLoad Ereignis wird geeignet sein. Sie können die Preise nicht abgebildet Eigenschaft in Ihrem Unternehmen hinzufügen, und rufen Sie dann in Zweig wie: {{ entity.prices.usd }}

services: 
    app.postload.listener: 
     class: AppBundle\EventListener\PostLoadListener 
     tags: 
      - { name: doctrine.event_listener, event: postLoad } 

Listener Klasse:

namespace AppBundle\EventListener; 

use Doctrine\ORM\Event\LifecycleEventArgs; 
use AppBundle\Entity\Product; 



class PostLoadListener 
{ 

protected static $currencies = []; 

public function postLoad(LifecycleEventArgs $args) 
{ 
    $entity = $args->getEntity(); 


    $entityManager = $args->getEntityManager(); 


    if ($entity instanceof Product) { 
     $price = $entity->getPrice(); 
     if (empty($this->currencies) { 
      // get currencies from db and calculate prices 
      $this->currencies = $entityManager->getConnection()->prepare('SELECT.....')->execute()->fetchAll(); 
     } 

     // Calculate prices and make them as array: $prices = ['usd' => 34, 'eur` => 30 .....] 

    $entity->setPrices($prices); 
} 

}

Rufen Sie sie in Zweig:

{{ entity.prices[app.request.cookies.get('currency')] }} 
+0

Das ist auch eine gute Idee. Ich kann auf diese Weise nicht auf die Eigenschaft entity.prices.usd zugreifen, da ich die Währung {{app.request.cookies.get ('currency')}}} bekomme. Aber das Doktrin-Ereignissystem zu erwähnen, ist eine gute Idee. Vielen Dank! – Brieuc

+1

Sie können: '{{entity.prices [app.request.cookies.get ('Währung')]}}' – malcolm

+0

Oh ja, danke! – Brieuc

1

Sie können die Klasse CurrencyConverter erstellen, die nur die Datenbank abfragt ce und die Verwendung des Ergebnisses unter der Annahme, dass die Rate während der Benutzeranforderung nicht geändert wird. Einige einfache Service (Sie es mit DI zu Ihrem Zweig Erweiterung injizieren können) wie

class CurrencyConverter 
{ 
    /** @var EntityManager */ 
    private $em; 

    private $rates = []; 

    public function __construct(EntityManager $em) 
    { 
     $this->em = $em; 
    } 

    public function convert($amount, $currency) 
    { 
     return $amount * $this->getRate($currency); 
    } 

    private function getRate($currency) 
    { 
     if (!isset($this->rates[$currency])) { 
      $repository = $this->em->getRepository('AppBundle:Rate'); 
      $this->rates[$currency] = $repository->getLatestRate($currency); 
     } 

     return $this->rates[$currency]; 
    } 
} 

Auf diese Weise werden Sie 1 haben Datenbankabfrage pro Anfrage pro Währung. Wenn Sie nicht viele Benutzer haben, die möglicherweise genug sind. MySQL wird höchstwahrscheinlich die ganze Währungstempo-Tabelle in den Speicher laden und wird blitzschnell sein.

Lehre Cache kann bis mehr beschleunigen, aber jeder Cache führt zu zusätzlichen Problemen und Fragen:

  • Wie lange sollte Abfrageergebnis im Cache sein?
  • Muss ich den Cache beim Raten-Update manuell leeren?
  • Habe ich gerade Ergebnis aus Cache oder Datenbank?

und so weiter.