{"id":2005,"date":"2013-01-20T14:33:20","date_gmt":"2013-01-20T13:33:20","guid":{"rendered":"http:\/\/olbertz.de\/blog\/?p=2005"},"modified":"2013-01-20T20:02:19","modified_gmt":"2013-01-20T19:02:19","slug":"native-sql-anfragen-in-doctrine-symfony2","status":"publish","type":"post","link":"https:\/\/olbertz.de\/blog\/2013\/01\/20\/native-sql-anfragen-in-doctrine-symfony2\/","title":{"rendered":"Native SQL-Anfragen in Doctrine \/ Symfony2"},"content":{"rendered":"<p>\nIch bin jetzt schon seit l&#228;ngerem ein gro&#223;er Fan von <a href=\"http:\/\/symfony.com\">Symfony 2<\/a> und verwende <a href=\"http:\/\/www.doctrine-project.org\">Doctrine<\/a> als ORM. Das klappt alles super, manchmal muss man sich aber in die Grenzgebiete wagen.\n<\/p>\n<p>\nIm vorliegenden Fall ging es um Statistikwerte in einer Tabelle. Im wesentlichen besteht die Tabelle (neben einer ID) noch aus einem Timestamp und um einen Wert, der im aktuelle Fall immer zwischen 1 und 3 liegt und eine Bewertung darstellt. Die Tabelle selbst wird auch in einer Entit&#228;t abgebildet folgende einfache Query sollte aber nun umgesetzt werden:\n<\/p>\n<pre>\r\nSELECT DATE(created_at), rating, COUNT(rating) \r\nFROM ratings \r\nGROUP BY DATE(created_at), rating \r\nORDER BY DATE(created_at) ASC, rating ASC;\r\n<\/pre>\n<p>\nDamit wollte ich also eine Zeitreihe erhalten, die neben dem Datum noch enth&#228;lt, wie h&#228;ufig die entsprechende Bewertung an dem Tag vorkam.\n<\/p>\n<p>\nHierzu musste ich auf die <a href=\"http:\/\/docs.doctrine-project.org\/en\/2.1\/reference\/native-sql.html\">NativeQuery<\/a> von Doctrine zur&#252;ckgreifen. Die Ergebnisse werden aber trotzdem von Doctrine verwaltet und verlangen ein <em>ResultSetMapping<\/em>, damit Doctrine wei&#223;, wie die Ergebnisdaten umgesetzt werden sollen. Damit l&#228;sst sich zum Beispiel bewerkstelligen, dass Doctrine automatisch passende Objekte zur&#252;ckgibt, die die Daten enthalten.\n<\/p>\n<p>\nIn meinem Fall wollte ich aber nur die nackten Zahlen haben, da ich die Werte zur sp&#228;teren Visualisierung in JS eh noch einmal umschreiben muss. Den Code habe ich in einem EntityRepository gekapselt, wer einen &#228;hnlichen Code in einem Service oder einer Controller-Action verwenden will, muss sich ggf. anderweitig den EntityManager besorgen. So sieht der Code aus:\n<\/p>\n<pre>\r\n$rsm = new \\Doctrine\\ORM\\Query\\ResultSetMapping();\r\n$rsm->addEntityResult('CfMainBundle:Rating', 'r');\r\n$rsm->addScalarResult('dateCreatedAt', 'date');\r\n$rsm->addScalarResult('rating', 'rating');\r\n$rsm->addScalarResult('countRating', 'count');\r\n$data = $this->getEntityManager()\r\n    ->createNativeQuery(\r\n        'SELECT DATE(r.created_at) AS dateCreatedAt, r.rating, COUNT(r.rating) AS countRating\r\n          FROM ratings r\r\n          GROUP BY DATE(r.created_at), r.rating\r\n          ORDER BY DATE(r.created_at) ASC, rating ASC',\r\n         $rsm\r\n    )\r\n    ->getResult();\r\n<\/pre>\n<p>Das Ergebnisarray sieht so aus:<\/p>\n<pre>\r\nArray\r\n(\r\n    [0] => Array\r\n        (\r\n            [date] => 2013-01-05\r\n            [rating] => 1\r\n            [count] => 8\r\n        )\r\n\r\n    [1] => Array\r\n        (\r\n            [date] => 2013-01-05\r\n            [rating] => 2\r\n            [count] => 4\r\n        )\r\n\r\n    [2] => Array\r\n        (\r\n            [date] => 2013-01-05\r\n            [rating] => 3\r\n            [count] => 1\r\n        )\r\n\r\n    [3] => Array\r\n        (\r\n            [date] => 2013-01-07\r\n            [rating] => 1\r\n            [count] => 22\r\n        )\r\n...\r\n)\r\n<\/pre>\n<p>\nDamit kann man nun prima weiterarbeiten. Zu beachten ist, dass in der Query die Originalnamen der Spalten aus der Datenbank genutzt werden m&#252;ssen und nicht die Namen der gemappten Attribute aus der Entit&#228;t. Dazu gibt es auch eine Abhilfe, die in der Doctrine-Dokumentation zur <a href=\"http:\/\/docs.doctrine-project.org\/en\/2.1\/reference\/native-sql.html\">NativeQuery<\/a> erkl&#228;rt wird.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ich bin jetzt schon seit l&#228;ngerem ein gro&#223;er Fan von Symfony 2 und verwende Doctrine als ORM. Das klappt alles super, manchmal muss man sich aber in die Grenzgebiete wagen. Im vorliegenden Fall ging es um Statistikwerte in einer Tabelle. &hellip; <a href=\"https:\/\/olbertz.de\/blog\/2013\/01\/20\/native-sql-anfragen-in-doctrine-symfony2\/\">Weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,74],"tags":[],"class_list":["post-2005","post","type-post","status-publish","format-standard","hentry","category-augenblicke","category-technik"],"_links":{"self":[{"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/posts\/2005","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/comments?post=2005"}],"version-history":[{"count":9,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/posts\/2005\/revisions"}],"predecessor-version":[{"id":2021,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/posts\/2005\/revisions\/2021"}],"wp:attachment":[{"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/media?parent=2005"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/categories?post=2005"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/olbertz.de\/blog\/wp-json\/wp\/v2\/tags?post=2005"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}