[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"9_t0YFtO844PW3-iCfPxRTbw8yv0-2zzu2bChZFenjo":3,"btz8hO-MXSFLpybqvfjYVBre4OvrEJO1wFySe3Zmv-s":49,"kpYjCMXEhHqoDGof5NDDNV5jdMdJAFrId6D_PNXF6Ck":75,"NSSIAufQcEKrgEL6nCON_nHMjPILGPa5XjZlEP8obqk":183,"_apollo:default":225},{"menu":4},{"__typename":5,"id":6,"name":7,"items":8},"Menu","nuxt-main-menu","Nuxt Hauptmenü",[9,24,29,34,39,44],{"__typename":10,"id":11,"title":12,"description":13,"url":14,"langcode":15,"internal":20,"expanded":21,"attributes":22},"MenuItem","9ffc5019-cbd8-4b2e-8eb7-9feae486d4a1","Blog",null,"/know-how",{"__typename":16,"id":17,"name":18,"direction":19},"Language","de","German","ltr",true,false,{"__typename":23,"class":13},"MenuItemAttributes",{"__typename":10,"id":25,"title":26,"description":13,"url":27,"langcode":15,"internal":20,"expanded":21,"attributes":28},"1c7a5430-8a42-4b24-9544-252adabc2f4c","Projekte","/projekte",{"__typename":23,"class":13},{"__typename":10,"id":30,"title":31,"description":13,"url":32,"langcode":15,"internal":20,"expanded":21,"attributes":33},"9c4feedc-79e4-4fbf-b68c-065f33ebfe4c","Sparring","/workshop-ux-sparring-fuer-unternehmen",{"__typename":23,"class":13},{"__typename":10,"id":35,"title":36,"description":13,"url":37,"langcode":15,"internal":20,"expanded":21,"attributes":38},"3b77a27b-272a-489f-843e-53e23ed07741","Trainings","/liechtenecker-ux-academy",{"__typename":23,"class":13},{"__typename":10,"id":40,"title":41,"description":13,"url":42,"langcode":15,"internal":20,"expanded":21,"attributes":43},"ce0bb82b-e1ee-4036-be95-f693a62e9f4a","Über uns","/about",{"__typename":23,"class":13},{"__typename":10,"id":45,"title":46,"description":13,"url":47,"langcode":15,"internal":20,"expanded":21,"attributes":48},"04a19381-81a9-4694-8653-182d8855d2b5","Kontakt","/kontakt",{"__typename":23,"class":13},{"menu":50},{"__typename":5,"id":51,"name":52,"items":53},"footer","Fußzeile",[54,60,65,70],{"__typename":10,"id":55,"title":56,"description":13,"url":57,"langcode":58,"internal":20,"expanded":21,"attributes":59},"e2873307-b50a-4aab-b6b2-1950fd99c72e","Impressum","/impressum",{"__typename":16,"id":17,"name":18,"direction":19},{"__typename":23,"class":13},{"__typename":10,"id":61,"title":62,"description":13,"url":63,"langcode":58,"internal":20,"expanded":21,"attributes":64},"2cd9b7c9-142a-4ea3-b898-a0952c54a195","Datenschutz","/datenschutz",{"__typename":23,"class":13},{"__typename":10,"id":66,"title":67,"description":13,"url":68,"langcode":58,"internal":20,"expanded":21,"attributes":69},"a5effba3-5a8c-4125-8d78-0cdba09824db","AGB","/agb",{"__typename":23,"class":13},{"__typename":10,"id":71,"title":72,"description":13,"url":73,"langcode":58,"internal":21,"expanded":21,"attributes":74},"114bf071-bdbb-44cf-85c1-69e9d9e0777d","Newsletter","https://liechtenecker.at/newsletter-subscribe",{"__typename":23,"class":13},{"route":76},{"__typename":77,"entity":78},"RouteInternal",{"__typename":79,"id":80,"title":81,"changed":82,"created":88,"langcode":91,"path":92,"promote":21,"status":20,"sticky":21,"metatag":93,"postCategory":113,"postContentElements":13,"evergreen":13,"tags":138,"postWpBody":152,"wpHeaderImage":13,"wpHeaderImageOld":155,"wpHeaderImageOldSmall":168,"wpOgImage":13,"wpPromotedTeaserImage":13,"wpShareDescription":13,"wpShareTitle":13,"wpTeaserText":13,"wpYoastHead":176,"author":177},"NodeWpPost","813","Laravel: Performante Suche",{"__typename":83,"timestamp":84,"timezone":85,"offset":86,"time":87},"DateTime",1554794655,"UTC","+00:00","2019-04-09T07:24:15+00:00",{"__typename":83,"timestamp":89,"timezone":85,"offset":86,"time":90},1533039033,"2018-07-31T12:10:33+00:00",{"__typename":16,"id":17,"name":18,"direction":19},"/blog/laravel-performante-suche",[94,101,108],{"__typename":95,"tag":96,"attributes":97},"MetaTagValue","meta",{"__typename":98,"name":99,"content":100},"MetaTagValueAttributes","title","Laravel: Performante Suche | Liechtenecker UX Design Studio",{"__typename":102,"tag":103,"attributes":104},"MetaTagLink","link",{"__typename":105,"href":106,"hreflang":13,"rel":107,"media":13,"sizes":13,"type":13},"MetaTagLinkAttributes","http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/blog/laravel-performante-suche","canonical",{"__typename":109,"tag":96,"attributes":110},"MetaTagProperty",{"__typename":111,"property":112,"content":81},"MetaTagPropertyAttributes","og:title",{"__typename":114,"id":115,"name":116,"path":117,"status":20,"weight":118,"description":119,"langcode":123,"changed":124,"metatag":127},"TermCategories","7","Technologie","/kategorie/technologie",0,{"__typename":120,"processed":121,"format":122},"Text","Development Themen sowie zukünftige Technologien, mit denen wir uns auseinandersetzen. ","wp_html",{"__typename":16,"id":17,"name":18,"direction":19},{"__typename":83,"timestamp":125,"timezone":85,"offset":86,"time":126},1713772777,"2024-04-22T07:59:37+00:00",[128,131,135],{"__typename":95,"tag":96,"attributes":129},{"__typename":98,"name":99,"content":130},"Technologie | Liechtenecker UX Design Studio",{"__typename":95,"tag":96,"attributes":132},{"__typename":98,"name":133,"content":134},"description","Development Themen sowie zukünftige Technologien, mit denen wir uns auseinandersetzen.",{"__typename":102,"tag":103,"attributes":136},{"__typename":105,"href":137,"hreflang":13,"rel":107,"media":13,"sizes":13,"type":13},"http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/kategorie/technologie",[139,144,148],{"__typename":140,"id":141,"name":142,"path":143,"weight":118},"TermTags","742","laravel","/tag/laravel",{"__typename":140,"id":145,"name":146,"path":147,"weight":118},"965","php","/tag/php",{"__typename":140,"id":149,"name":150,"path":151,"weight":118},"1126","search","/tag/search",{"__typename":153,"processed":154,"format":122,"summary":13},"TextSummary","\u003Cdiv class=\"grid-wrapper\">\n    \u003Cdiv class=\"row\">\n        \u003Cdiv class=\"default-left col-xsmall-12 col-medium-6 col-medium-offset-2 col-large-6 col-large-offset-3 \">\n            \n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Bei unseren großen Projekten haben wir hauptsächlich Symfony- und Laravel Komponenten im Einsatz, erweitern den Kern um die spezifischen Anforderungen abzudecken und bauen dann ein Modul-Management darüber, um Erweiterbarkeit zu gewährleisten.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Beim Aufsetzen des Kerns bin ich immer wieder auf den Use-Case gestoßen, dass Daten aus unterschiedlichsten Tabellen irgendwo im System zentral benötigt werden. Das einfachste Beispiel dafür ist eine zentrale Suche, welche verschiedenste Inhaltstypen durchsucht. In diesem Beitrag werde ich euch erklären, wie einfach es ist, so eine Suche in Laravel zu integrieren.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Als Entwickler sucht man gewöhnlich immer nach fertigen Packages, bevor man selbst einen Finger rührt. Das habe ich in diesem Fall natürlich auch gemacht, und bin auf “\u003C/span>\u003Ca href=\"https://laravel.com/docs/5.6/scout\">\u003Cspan style=\"font-weight: 400;\">Laravel Scout\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\">” — die hauseigene Suche von Laravel — gestoßen. Für unser Projekt ist das Package aber nicht gut geeignet, da unsere Datenstruktur &amp; unser Ranking zu komplex ist. Keine Sorge: in diesem Beitrag konzentriere ich mich auf die Basics, um den Rahmen nicht zu sprengen 😉\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Nach kurzem Grübeln war schnell mal klar:\u003Cbr>\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">Um die Suche performant zu halten, muss eine neue Datenbanktabelle angelegt werden, welche bei Suchen abgefragt wird. \u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Sollte es diese nämlich nicht geben, müssten alle Tabellen, welche durchsuchbar sind, einzeln abgefragt werden!! Das wäre für die Performance natürlich ein No-Go!\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Im einfachsten Fall reicht eine Tabelle mit folgenden Spalten:\u003C/span>\u003C/p>\n\u003Cul>\n\u003Cli style=\"font-weight: 400;\">\u003Cb>Suchtext\u003C/b>\u003Cspan style=\"font-weight: 400;\">: nach dem Text wird bei Abfragen gesucht\u003C/span>\u003C/li>\n\u003Cli style=\"font-weight: 400;\">\u003Cb>Inhaltstyp-Klasse\u003C/b>\u003Cspan style=\"font-weight: 400;\">: damit beim Ergebnis der richtige Inhaltstyp geladen werden kann\u003C/span>\u003C/li>\n\u003Cli style=\"font-weight: 400;\">\u003Cb>Inhalts-ID\u003C/b>\u003Cspan style=\"font-weight: 400;\">: die ID des Inhaltselements\u003C/span>\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Diese Tabelle soll beim Erstellen, Updaten und Löschen von durchsuchbaren Inhalten automatisch geupdatet werden.\u003C/span>\u003C/p>\n\u003Ch2>\u003Cspan style=\"font-weight: 400;\">Laravel erweitern &amp; Models vorbereiten\u003C/span>\u003C/h2>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Für diesen Schritt wird ein “Manager” benötigt, welcher alle durchsuchbaren Inhalte überwacht, und bei bestimmten Events die Suchtabelle updatet. Ich werde den Manager in den nächsten Zeilen einfach “Search-Engine” oder “Suchmaschine” nennen.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Laravel bietet die einfache Möglichkeit, das System mit sogenannten \u003C/span>\u003Ca href=\"https://laravel.com/docs/5.6/providers\">\u003Cspan style=\"font-weight: 400;\">Service-Providern\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\"> zu erweitern. Ein solcher muss erstellt werden, um darin die Search-Engine zu instanzieren. Dann braucht die Suchmaschine noch die Information, welche Models durchsuchbar sind. Wie sie zu dieser Information kommt ist eigentlich egal. In kleinen Projekten löse ich das über ein config-Array, welches alle Klassen enthält. Bei großen Projekten überlasse ich diesen Task dem Modul-Management, um auch Inhalte aus Modulen für die Suche bereitzustellen.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Um sicherzustellen, dass die Inhalte korrekte Daten für die Suchtabelle zur Verfügung stellen, und bei einem Such-Request die richtigen Daten zurückgeben, verpflichte ich diese, ein Searchable \u003C/span>\u003Ca href=\"http://php.net/manual/de/language.oop5.interfaces.php\">\u003Cspan style=\"font-weight: 400;\">Interface\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\"> implementieren.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Ein einfaches Beispiel dafür wäre:\u003C/span>\u003C/p>\n\u003Cpre>\u003Cspan style=\"font-weight: 400;\">interface Searchable {\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">&nbsp; &nbsp; public function searchFields(): array;\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">&nbsp; &nbsp; public function searchResult(); array;\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">}\u003C/span>\u003C/pre>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Damit ist sichergestellt, dass alle durchsuchbaren Models angeben, welche Felder bei der Suche berücksichtigt werden. Außerdem muss das Model auch definieren, welche Daten als Suchergebnis zurückgegeben werden. \u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Somit sind die Models für die Suche vorbereitet.\u003C/span>\u003C/p>\n\u003Ch2>\u003Cspan style=\"font-weight: 400;\">Suchtabelle aktuell halten\u003C/span>\u003C/h2>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Hier kommt Laravel’s Event-System zum Einsatz. Ein mächtiges Instrument, welches einem die Arbeit um ein Vielfaches erleichtert! \u003C/span>\u003Ca href=\"https://laravel.com/docs/5.6/eloquent\">\u003Cspan style=\"font-weight: 400;\">Eloquent\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\"> (Laravels ORM — \u003Ca href=\"https://en.wikipedia.org/wiki/Object-relational_mapping\">Object-relational mapping\u003C/a>\u003C/span>\u003Cspan style=\"font-weight: 400;\">) bietet bereits viele vordefinierte \u003C/span>\u003Ca href=\"https://laravel.com/docs/5.6/eloquent#events\">\u003Cspan style=\"font-weight: 400;\">Events\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\"> für Models. Wenn man auf mehrere Events eines Models reagieren will, kann man sogenannte “\u003C/span>\u003Ca href=\"https://laravel.com/docs/5.6/eloquent#observers\">\u003Cspan style=\"font-weight: 400;\">Event-Observer\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\">” registrieren. Wenn ein Model-Event auftritt, wird dann die gleichnamige Methode des Observers aufgerufen. \u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Das bedeutet, wenn auf das “created” Event reagiert werden soll, muss im Observer stets eine Methode namens “created” implementiert werden. Alle Event-Methoden bekommen das jeweilige Model als Parameter übergeben. Da alle Models das Searchable Interface implementieren, kann als \u003C/span>\u003Ca href=\"http://php.net/manual/de/functions.arguments.php#functions.arguments.type-declaration\">\u003Cspan style=\"font-weight: 400;\">Argumenttyp-Deklaration\u003C/span>\u003C/a>\u003Cspan style=\"font-weight: 400;\"> “Searchable” angegeben werden.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Um die Inhalte der Suchtabelle aktuell zu halten, muss für alle Searchables auf die Events “saved” und “deleted” reagiert werden. Der Observer muss sich dann nur darum kümmern, dass beim “saved”-Event ein Eintrag erstellt beziehungsweise upgedatet wird, und beim “deleted” die jeweiligen Einträge aus der Suchtabelle gelöscht werden.\u003C/span>\u003C/p>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Um das zu arrangieren, muss die Search-Engine über alle registrierten Searchable-Klassen iterieren und jeweils die statische Methode “observe” ausführen, um für das Model einen Event-Observer zu registrieren:\u003C/span>\u003C/p>\n\u003Cpre>\u003Cspan style=\"font-weight: 400;\">foreach ($searchableClasses as $searchableClass) {\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">&nbsp; &nbsp; // hier prüfen, ob $searchableClass das Interface implementiert!\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">&nbsp; &nbsp; $searchableClass::observe(SearchObserver::class);\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">}\u003C/span>\u003C/pre>\n\u003Ch2>\u003Cspan style=\"font-weight: 400;\">Ergebnisse Finden\u003C/span>\u003C/h2>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Um nun zu Suchergebnissen zu kommen, muss jetzt einfach nur die Suchtabelle nach einem bestimmten Text abgefragt werden:\u003C/span>\u003C/p>\n\u003Cpre>\u003Cspan style=\"font-weight: 400;\">SELECT model_class, model_id\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">FROM search_table\n\u003C/span>\u003Cspan style=\"font-weight: 400;\">WHERE search_text\nLIKE “%danach wird gesucht%”;\u003C/span>\u003C/pre>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Diese Abfrage gibt alle Ergebnisse von allen durchsuchbaren Inhaltstypen zurück. Dann muss nur noch die model_id von der model_class laden.\u003C/span>\u003C/p>\n\u003Cpre>\u003Cspan style=\"font-weight: 400;\">$content = $modelClass::find($model_id);\u003C/span>\u003C/pre>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Der Inhalt sollte dann existieren, da beim Löschen ja auch der Inhalt aus der Suchtabelle gelöscht wird; aber um sicherzugehen, kann geprüft werden, ob \u003C/span>\u003Cspan style=\"font-weight: 400;\">$content\u003C/span>\u003Cspan style=\"font-weight: 400;\"> eine Instanz von \u003C/span>\u003Cspan style=\"font-weight: 400;\">$modelClass\u003C/span>\u003Cspan style=\"font-weight: 400;\"> ist.\u003C/span>\u003C/p>\n\u003Ch2>\u003Cspan style=\"font-weight: 400;\">Andere Use-Cases\u003C/span>\u003C/h2>\n\u003Cp>\u003Cspan style=\"font-weight: 400;\">Der Einsatz von Event-Observer in Kombination mit einem “DataManager” erweist sich auch in zahlreichen anderen Anwendungsgebieten als äußerst hilfreich. Wir haben beispielsweise ein Reporting-System, welches diverse Events speichert und Statistiken auswertet, auf Basis dieses Konzepts aufgebaut. In diesem Fall waren jedoch einige Custom-Events im Einsatz (nicht nur die default Eloquent Events). Ein weiterer Anwendungsfall, welcher mir spontan dazu einfällt, wäre ein Notification-Center.\u003C/span>\u003C/p>\n        \u003C/div>\n    \u003C/div>\n\u003C/div>\n\n\n",{"__typename":156,"id":157,"excludeFromScreenreader":13,"mediaImage":158,"name":164,"path":167,"status":20},"MediaImage","1222",{"__typename":159,"url":160,"width":161,"height":162,"alt":163,"title":164,"size":165,"mime":166},"Image","http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/sites/default/files/wp-migration/wordpress-media-image/2018/07/blog-big-3-1.jpg",1920,500,"vom Suchen und Finden","Vom Suchen und Finden",521096,"image/jpeg","/media/1222/edit",{"__typename":156,"id":169,"excludeFromScreenreader":13,"mediaImage":170,"name":164,"path":175,"status":20},"1221",{"__typename":159,"url":171,"width":172,"height":173,"alt":164,"title":164,"size":174,"mime":166},"http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/sites/default/files/wp-migration/wordpress-media-image/2018/07/blog-small-3-1.jpg",922,519,320588,"/media/1221/edit","\u003C!-- This site is optimized with the Yoast SEO plugin v15.7 - https://yoast.com/wordpress/plugins/seo/ -->\n\u003Cmeta name=\"description\" content=\"In diesem Beitrag könnt ihr nachlesen, wie eine performante Suche in Laravel implementiert werden kann. Außerdem werden Laravel-Events und Event-Observers vorgestellt.\" />\n\u003Cmeta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" />\n\u003Clink rel=\"canonical\" href=\"https://legacy.liechtenecker.dev/blog/laravel-performante-suche/\" />\n\u003Cmeta property=\"og:locale\" content=\"de_DE\" />\n\u003Cmeta property=\"og:type\" content=\"article\" />\n\u003Cmeta property=\"og:title\" content=\"How-To: Performante Suche in Laravel - Liechtenecker\" />\n\u003Cmeta property=\"og:description\" content=\"In diesem Beitrag könnt ihr nachlesen, wie eine performante Suche in Laravel implementiert werden kann. Außerdem werden Laravel-Events und Event-Observers vorgestellt.\" />\n\u003Cmeta property=\"og:url\" content=\"https://legacy.liechtenecker.dev/blog/laravel-performante-suche/\" />\n\u003Cmeta property=\"og:site_name\" content=\"Liechtenecker\" />\n\u003Cmeta property=\"article:published_time\" content=\"2018-07-31T14:10:33+00:00\" />\n\u003Cmeta property=\"article:modified_time\" content=\"2019-04-09T09:24:15+00:00\" />\n\u003Cmeta name=\"twitter:card\" content=\"summary_large_image\" />\n\u003Cmeta name=\"twitter:label1\" content=\"Geschätzte Lesezeit\">\n\t\u003Cmeta name=\"twitter:data1\" content=\"4 Minuten\">\n\u003Cscript type=\"application/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https://legacy.liechtenecker.dev/#website\",\"url\":\"https://legacy.liechtenecker.dev/\",\"name\":\"Liechtenecker\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https://legacy.liechtenecker.dev/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de-DE\"},{\"@type\":\"WebPage\",\"@id\":\"https://legacy.liechtenecker.dev/blog/laravel-performante-suche/#webpage\",\"url\":\"https://legacy.liechtenecker.dev/blog/laravel-performante-suche/\",\"name\":\"How-To: Performante Suche in Laravel - Liechtenecker\",\"isPartOf\":{\"@id\":\"https://legacy.liechtenecker.dev/#website\"},\"datePublished\":\"2018-07-31T14:10:33+00:00\",\"dateModified\":\"2019-04-09T09:24:15+00:00\",\"author\":{\"@id\":\"https://legacy.liechtenecker.dev/#/schema/person/d8b80cc046b867225321ea8b7a2a6de7\"},\"description\":\"In diesem Beitrag k\\u00f6nnt ihr nachlesen, wie eine performante Suche in Laravel implementiert werden kann. Au\\u00dferdem werden Laravel-Events und Event-Observers vorgestellt.\",\"inLanguage\":\"de-DE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https://legacy.liechtenecker.dev/blog/laravel-performante-suche/\"]}]},{\"@type\":\"Person\",\"@id\":\"https://legacy.liechtenecker.dev/#/schema/person/d8b80cc046b867225321ea8b7a2a6de7\",\"name\":\"Daniel\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https://legacy.liechtenecker.dev/#personlogo\",\"inLanguage\":\"de-DE\",\"url\":\"https://secure.gravatar.com/avatar/5708f7599c8e99528411ef29bef1ee34?s=96&d=mm&r=g\",\"caption\":\"Daniel\"}}]}\u003C/script>\n\u003C!-- / Yoast SEO plugin. -->",{"__typename":178,"id":179,"myRole":180,"name":181,"nickname":182},"User","5","Backend Development🤓","d-steindl","Daniel",{"latestKnowhow":184},[185,200,213],{"__typename":79,"id":186,"title":187,"path":188,"wpTeaserText":189,"wpPromotedTeaserImage":13,"wpHeaderImage":190},"1619","Behind the scenes: Ein Barrierefreiheits-Audit","/blog/behind-scenes-ein-barrierefreiheits-audit","”Entspricht unsere Website den gesetzlichen Anforderungen und wenn nicht, was genau müssen wir ändern?”\r\nDiese Frage lieben wir. Echt! Und so sieht unsere Antwort aus.",{"__typename":156,"id":191,"excludeFromScreenreader":13,"mediaImage":192,"name":198,"path":199,"status":20},"3364",{"__typename":159,"url":193,"width":194,"height":195,"alt":196,"title":13,"size":197,"mime":166},"http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/sites/default/files/2026-04/Headerbilder%20Blogartikel%20Behind%20the%20scene%20Accessibility%20Audit.jpg",2880,1300,"Headline mit Sujet: Tastatur mit Symbolen für Barrierefreiheit im Fokus auf hellem  Hintergrund",838204,"Headerbilder Blogartikel Behind the scene Accessibility Audit.jpg","/media/3364/edit",{"__typename":79,"id":201,"title":202,"path":203,"wpTeaserText":204,"wpPromotedTeaserImage":13,"wpHeaderImage":205},"1616","Agentic KI trifft Design-System: Wie unser Presentation Maker entstand.","/blog/agentic-ki-trifft-design-system-wie-unser-presentation-maker-entstand","Nein, wir wollen euch jetzt nicht erzählen, was KI alles kann. Aber wir möchten euch zeigen, wie wir mit KI umgehen. \r\n",{"__typename":156,"id":206,"excludeFromScreenreader":13,"mediaImage":207,"name":211,"path":212,"status":20},"3355",{"__typename":159,"url":208,"width":194,"height":195,"alt":209,"title":13,"size":210,"mime":166},"http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/sites/default/files/2026-03/BLOG_Presentation%20Tool_TITEL-2880x1300px_1.jpg","Lukas und Daniel  arbeiten an Computern im Büro.",2621988,"BLOG_Presentation Tool_TITEL-2880x1300px.jpg","/media/3355/edit",{"__typename":79,"id":214,"title":215,"path":216,"wpTeaserText":13,"wpPromotedTeaserImage":13,"wpHeaderImage":217},"1606","UI Trends 2026","/blog/ui-trends-2026",{"__typename":156,"id":218,"excludeFromScreenreader":21,"mediaImage":219,"name":223,"path":224,"status":20},"3303",{"__typename":159,"url":220,"width":194,"height":195,"alt":221,"title":13,"size":222,"mime":166},"http://liechtenecker-cms.liechtenecker-cms.svc.cluster.local/sites/default/files/2026-01/BLOG_Trendbericht%202026.jpg","UI Trends 2026, gelber Hintergrund, schwarze Schrift.",4700748,"BLOG_Trendbericht 2026.jpg","/media/3303/edit",{"Language:de":226,"MenuItem:9ffc5019-cbd8-4b2e-8eb7-9feae486d4a1":227,"MenuItem:1c7a5430-8a42-4b24-9544-252adabc2f4c":231,"MenuItem:9c4feedc-79e4-4fbf-b68c-065f33ebfe4c":234,"MenuItem:3b77a27b-272a-489f-843e-53e23ed07741":237,"MenuItem:ce0bb82b-e1ee-4036-be95-f693a62e9f4a":240,"MenuItem:04a19381-81a9-4694-8653-182d8855d2b5":243,"Menu:nuxt-main-menu":246,"ROOT_QUERY":260,"MenuItem:e2873307-b50a-4aab-b6b2-1950fd99c72e":276,"MenuItem:2cd9b7c9-142a-4ea3-b898-a0952c54a195":279,"MenuItem:a5effba3-5a8c-4125-8d78-0cdba09824db":282,"MenuItem:114bf071-bdbb-44cf-85c1-69e9d9e0777d":285,"Menu:footer":288,"TermCategories:7":298,"TermTags:742":309,"TermTags:965":310,"TermTags:1126":311,"MediaImage:1222":312,"MediaImage:1221":314,"User:5":316,"NodeWpPost:813":317,"MediaImage:3364":344,"NodeWpPost:1619":346,"MediaImage:3355":349,"NodeWpPost:1616":351,"MediaImage:3303":354,"NodeWpPost:1606":356},["null","__typename",16,"id",17,"name",18,"direction",19],["null","__typename",10,"id",11,"title",12,"description",13,"url",14,"langcode",228,"internal",20,"expanded",21,"attributes",230],{"__ref":229},"Language:de",["null","__typename",23,"class",13],["null","__typename",10,"id",25,"title",26,"description",13,"url",27,"langcode",232,"internal",20,"expanded",21,"attributes",233],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",30,"title",31,"description",13,"url",32,"langcode",235,"internal",20,"expanded",21,"attributes",236],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",35,"title",36,"description",13,"url",37,"langcode",238,"internal",20,"expanded",21,"attributes",239],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",40,"title",41,"description",13,"url",42,"langcode",241,"internal",20,"expanded",21,"attributes",242],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",45,"title",46,"description",13,"url",47,"langcode",244,"internal",20,"expanded",21,"attributes",245],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",5,"id",6,"name",7,"items",247],[248,250,252,254,256,258],{"__ref":249},"MenuItem:9ffc5019-cbd8-4b2e-8eb7-9feae486d4a1",{"__ref":251},"MenuItem:1c7a5430-8a42-4b24-9544-252adabc2f4c",{"__ref":253},"MenuItem:9c4feedc-79e4-4fbf-b68c-065f33ebfe4c",{"__ref":255},"MenuItem:3b77a27b-272a-489f-843e-53e23ed07741",{"__ref":257},"MenuItem:ce0bb82b-e1ee-4036-be95-f693a62e9f4a",{"__ref":259},"MenuItem:04a19381-81a9-4694-8653-182d8855d2b5",["null","__typename",261,"menu({\"name\":\"NUXT_MAIN_MENU\"})",262,"menu({\"name\":\"FOOTER\"})",264,"route({\"path\":\"/blog/laravel-performante-suche\"})",266,"latestKnowhow({\"excludeId\":\"813\",\"limit\":3})",269],"Query",{"__ref":263},"Menu:nuxt-main-menu",{"__ref":265},"Menu:footer",["null","__typename",77,"entity",267],{"__ref":268},"NodeWpPost:813",[270,272,274],{"__ref":271},"NodeWpPost:1619",{"__ref":273},"NodeWpPost:1616",{"__ref":275},"NodeWpPost:1606",["null","__typename",10,"id",55,"title",56,"description",13,"url",57,"langcode",277,"internal",20,"expanded",21,"attributes",278],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",61,"title",62,"description",13,"url",63,"langcode",280,"internal",20,"expanded",21,"attributes",281],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",66,"title",67,"description",13,"url",68,"langcode",283,"internal",20,"expanded",21,"attributes",284],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",10,"id",71,"title",72,"description",13,"url",73,"langcode",286,"internal",21,"expanded",21,"attributes",287],{"__ref":229},["null","__typename",23,"class",13],["null","__typename",5,"id",51,"name",52,"items",289],[290,292,294,296],{"__ref":291},"MenuItem:e2873307-b50a-4aab-b6b2-1950fd99c72e",{"__ref":293},"MenuItem:2cd9b7c9-142a-4ea3-b898-a0952c54a195",{"__ref":295},"MenuItem:a5effba3-5a8c-4125-8d78-0cdba09824db",{"__ref":297},"MenuItem:114bf071-bdbb-44cf-85c1-69e9d9e0777d",["null","__typename",114,"id",115,"name",116,"path",117,"status",20,"weight",118,"description",299,"langcode",300,"changed",301,"metatag",302],["null","__typename",120,"processed",121,"format",122],{"__ref":229},["null","__typename",83,"timestamp",125,"timezone",85,"offset",86,"time",126],[303,305,307],["null","__typename",95,"tag",96,"attributes",304],["null","__typename",98,"name",99,"content",130],["null","__typename",95,"tag",96,"attributes",306],["null","__typename",98,"name",133,"content",134],["null","__typename",102,"tag",103,"attributes",308],["null","__typename",105,"href",137,"hreflang",13,"rel",107,"media",13,"sizes",13,"type",13],["null","__typename",140,"id",141,"name",142,"path",143,"weight",118],["null","__typename",140,"id",145,"name",146,"path",147,"weight",118],["null","__typename",140,"id",149,"name",150,"path",151,"weight",118],["null","__typename",156,"id",157,"excludeFromScreenreader",13,"mediaImage",313,"name",164,"path",167,"status",20],["null","__typename",159,"url",160,"width",161,"height",162,"alt",163,"title",164,"size",165,"mime",166],["null","__typename",156,"id",169,"excludeFromScreenreader",13,"mediaImage",315,"name",164,"path",175,"status",20],["null","__typename",159,"url",171,"width",172,"height",173,"alt",164,"title",164,"size",174,"mime",166],["null","__typename",178,"id",179,"myRole",180,"name",181,"nickname",182],["null","__typename",79,"id",80,"title",81,"changed",318,"created",319,"langcode",320,"path",92,"promote",21,"status",20,"sticky",21,"metatag",321,"category",328,"contentElements",13,"evergreen",13,"tags",330,"wpBody",337,"wpHeaderImage",13,"wpHeaderImageOld",338,"wpHeaderImageOldSmall",340,"wpOgImage",13,"wpPromotedTeaserImage",13,"wpShareDescription",13,"wpShareTitle",13,"wpTeaserText",13,"wpYoastHead",176,"author",342],["null","__typename",83,"timestamp",84,"timezone",85,"offset",86,"time",87],["null","__typename",83,"timestamp",89,"timezone",85,"offset",86,"time",90],{"__ref":229},[322,324,326],["null","__typename",95,"tag",96,"attributes",323],["null","__typename",98,"name",99,"content",100],["null","__typename",102,"tag",103,"attributes",325],["null","__typename",105,"href",106,"hreflang",13,"rel",107,"media",13,"sizes",13,"type",13],["null","__typename",109,"tag",96,"attributes",327],["null","__typename",111,"property",112,"content",81],{"__ref":329},"TermCategories:7",[331,333,335],{"__ref":332},"TermTags:742",{"__ref":334},"TermTags:965",{"__ref":336},"TermTags:1126",["null","__typename",153,"processed",154,"format",122,"summary",13],{"__ref":339},"MediaImage:1222",{"__ref":341},"MediaImage:1221",{"__ref":343},"User:5",["null","__typename",156,"id",191,"excludeFromScreenreader",13,"mediaImage",345,"name",198,"path",199,"status",20],["null","__typename",159,"url",193,"width",194,"height",195,"alt",196,"title",13,"size",197,"mime",166],["null","__typename",79,"id",186,"title",187,"path",188,"wpTeaserText",189,"wpPromotedTeaserImage",13,"wpHeaderImage",347],{"__ref":348},"MediaImage:3364",["null","__typename",156,"id",206,"excludeFromScreenreader",13,"mediaImage",350,"name",211,"path",212,"status",20],["null","__typename",159,"url",208,"width",194,"height",195,"alt",209,"title",13,"size",210,"mime",166],["null","__typename",79,"id",201,"title",202,"path",203,"wpTeaserText",204,"wpPromotedTeaserImage",13,"wpHeaderImage",352],{"__ref":353},"MediaImage:3355",["null","__typename",156,"id",218,"excludeFromScreenreader",21,"mediaImage",355,"name",223,"path",224,"status",20],["null","__typename",159,"url",220,"width",194,"height",195,"alt",221,"title",13,"size",222,"mime",166],["null","__typename",79,"id",214,"title",215,"path",216,"wpTeaserText",13,"wpPromotedTeaserImage",13,"wpHeaderImage",357],{"__ref":358},"MediaImage:3303"]