{"id":31385,"date":"2019-10-31T21:40:58","date_gmt":"2019-10-31T18:40:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\/"},"modified":"2019-10-31T21:40:58","modified_gmt":"2019-10-31T18:40:58","slug":"biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","title":{"rendered":"Gesch\u00e4ftslogik in der Datenbank mit SchemaKeeper","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ziel dieses Artikels ist es, am Beispiel der Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> Werkzeuge zu zeigen, die den Entwicklungsprozess von Datenbanken in PHP-Projekten mit PostgreSQL-Datenbanken erheblich erleichtern.<\/p>\n<p><\/p>\n<p>Die Informationen aus diesem Artikel werden vor allem f\u00fcr Entwickler n\u00fctzlich sein, die die M\u00f6glichkeiten von PostgreSQL maximieren m\u00f6chten, aber auf Probleme bei der Pflege der in die Datenbank ausgelagerten Gesch\u00e4ftlogik sto\u00dfen. <\/p>\n<p><\/p>\n<p>Der Artikel wird die Vor- oder Nachteile der Speicherung von Gesch\u00e4ftlogik in der Datenbank nicht beschreiben. Es wird davon ausgegangen, dass die Wahl bereits vom Leser getroffen wurde.<\/p>\n<p><\/p>\n<p>Es werden folgende Fragen behandelt:<\/p>\n<p><\/p>\n<ol>\n<li>In welcher Form soll der Dump der Datenbankstruktur im Versionskontrollsystem (nachfolgend VCS) gespeichert werden?<\/li>\n<li>Wie k\u00f6nnen \u00c4nderungen an der Datenbankstruktur nach der Speicherung des Dumps verfolgt werden?<\/li>\n<li>Wie k\u00f6nnen \u00c4nderungen an der Datenbankstruktur ohne Konflikte und riesige Migrationsdateien auf andere Umgebungen \u00fcbertragen werden?<\/li>\n<li>Wie kann der Prozess der parallelen Arbeit mehrerer Entwickler am Projekt organisiert werden?<\/li>\n<li>Wie k\u00f6nnen mehrere \u00c4nderungen an der Datenbankstruktur sicher in die Produktionsumgebung deployed werden?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<blockquote><p><strong>SchemaKeeper<\/strong> ist auf die Arbeit mit gespeicherten Prozeduren ausgelegt, die in der Sprache <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex>geschrieben sind. Tests mit anderen Sprachen wurden nicht durchgef\u00fchrt, daher k\u00f6nnte die Nutzung weniger effektiv oder unm\u00f6glich sein.\n<\/p><\/blockquote>\n<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"v-kakom-vide-hranit-damp-struktury-bd-v-vcs\">In welcher Form soll der Dump der Datenbankstruktur im VCS gespeichert werden?<\/h2>\n<p><\/p>\n<p>Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> stellt die Funktion <code>saveDump<\/code>bereit, die die Struktur aller Objekte aus der Datenbank in Form von separaten Textdateien speichert. Als Ergebnis wird ein Verzeichnis erstellt, das die Struktur der Datenbank enth\u00e4lt, aufgeteilt in gruppierte Dateien, die leicht ins VCS hinzugef\u00fcgt werden k\u00f6nnen.<\/p>\n<p><\/p>\n<p>Betrachten wir die Umwandlung von Objekten aus der Datenbank in Dateien an mehreren Beispielen:<\/p>\n<p><\/p>\n<p>Objekttyp<br \/>\nDiagramm<br \/>\nBezeichnung<br \/>\nRelativer Pfad zur Datei<\/p>\n<p>Tabelle<br \/>\npublic<br \/>\naccounts<br \/>\n<code>.\/public\/tables\/accounts.txt<\/code><\/p>\n<p>Gespeicherte Prozedur<br \/>\npublic<br \/>\nauth(hash bigint)<br \/>\n<code>.\/public\/functions\/auth(int8).sql<\/code><\/p>\n<p>Darstellung<br \/>\nbooking<br \/>\ntariffs<br \/>\n<code>.\/booking\/views\/tariffs.txt<\/code><\/p>\n<p><\/p>\n<p>Der Inhalt der Dateien ist eine textuelle Darstellung der Struktur eines bestimmten Datenbankobjekts. Zum Beispiel wird der Inhalt der Datei f\u00fcr gespeicherte Prozeduren die vollst\u00e4ndige Definition der gespeicherten Prozedur enthalten, die mit dem Block beginnt <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Wie aus der obigen Tabelle ersichtlich, enth\u00e4lt der Pfad zur Datei Informationen \u00fcber den Typ, das Schema und den Namen des Objekts. Dieser Ansatz erleichtert die Navigation durch den Dump und das Code-Review von \u00c4nderungen in der Datenbank.<\/p>\n<p><\/p>\n<blockquote><p>Erweiterung <code>.sql<\/code> F\u00fcr Dateien mit Quellcode von gespeicherten Prozeduren wurde gew\u00e4hlt, damit die IDE beim \u00d6ffnen der Datei automatisch Tools zur Interaktion mit der Datenbank bereitstellt.<\/p><\/blockquote>\n<p><\/p>\n<h2 id=\"kak-otslezhivat-izmeneniya-v-strukture-bd-posle-sohraneniya-dampa\">Wie k\u00f6nnen \u00c4nderungen an der Datenbankstruktur nach der Speicherung des Dumps verfolgt werden?<\/h2>\n<p><\/p>\n<p>Durch das Speichern eines Dumps der aktuellen Datenbankstruktur in VCS erhalten wir die M\u00f6glichkeit, zu \u00fcberpr\u00fcfen, ob \u00c4nderungen an der Struktur der Datenbank nach der Erstellung des Dumps vorgenommen wurden. In der Bibliothek <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> gibt es eine Funktion zur Erkennung von \u00c4nderungen in der Datenbankstruktur. <code>verifyDump<\/code>, die ohne Nebenwirkungen Informationen \u00fcber die Unterschiede zur\u00fcckgibt. <\/p>\n<p><\/p>\n<p>Ein alternativer Pr\u00fcfweg besteht darin, die Funktion noch einmal aufzurufen <code>saveDump<\/code>, wobei das gleiche Verzeichnis angegeben wird, und die \u00c4nderungen im VCS zu \u00fcberpr\u00fcfen. Da alle Objekte der Datenbank in separaten Dateien gespeichert sind, wird VCS nur die ge\u00e4nderten Objekte anzeigen.<br \/>\nDer Hauptnachteil dieser Methode ist die Notwendigkeit, die Dateien zu \u00fcberschreiben, um die \u00c4nderungen zu sehen.<\/p>\n<p><\/p>\n<h2 id=\"kak-perenosit-izmeneniya-v-strukture-bd-na-drugie-okruzheniya-bez-konfliktov-i-gigantskih-faylov-migraciy\">Wie k\u00f6nnen \u00c4nderungen an der Datenbankstruktur ohne Konflikte und riesige Migrationsdateien auf andere Umgebungen \u00fcbertragen werden?<\/h2>\n<p><\/p>\n<p>wissen wir dank der Funktion <code>deployDump<\/code> Der Quellcode von gespeicherten Prozeduren kann ganz \u00e4hnlich wie der regul\u00e4re Quellcode einer Anwendung bearbeitet werden. Man kann neue Zeilen im Code der gespeicherten Prozeduren hinzuf\u00fcgen\/entfernen und sofort die \u00c4nderungen in das Versionskontrollsystem \u00fcbermitteln oder gespeicherte Prozeduren erstellen\/l\u00f6schen, indem man entsprechende Dateien im Dump-Verzeichnis erstellt\/l\u00f6scht. <\/p>\n<p><\/p>\n<p>Zum Beispiel reicht es aus, um eine neue gespeicherte Prozedur im Schema <code>public<\/code> zu erstellen, eine neue Datei mit der Erweiterung <code>.sql<\/code> wird im Verzeichnis <code>public\/functions<\/code>, zu erstellen, den Quellcode der gespeicherten Prozedur inklusive des Blocks <code>CREATE OR REPLACE FUNCTION<\/code>, dort einzuf\u00fcgen und dann die Funktion <code>deployDump<\/code>aufzurufen. Auf die gleiche Weise erfolgt die \u00c4nderung und L\u00f6schung einer gespeicherten Prozedur. Auf diese Weise gelangt der Code gleichzeitig in VCS und in die Datenbank. <\/p>\n<p><\/p>\n<p>Wenn im Quellcode einer gespeicherten Prozedur ein Fehler auftritt oder eine Diskrepanz zwischen dem Dateinamen und der gespeicherten Prozedur besteht, wird <code>deployDump<\/code> nicht ausgef\u00fchrt und gibt den Fehlertext aus. Eine Diskrepanz zwischen den gespeicherten Prozeduren im Dump und der aktuellen Datenbank ist mit Hilfe von <code>deployDump<\/code>.<\/p>\n<p><\/p>\n<blockquote><p>bei der Erstellung einer neuen gespeicherten Prozedur nicht erforderlich, den richtigen Dateinamen manuell einzugeben. Es reicht aus, dass die Datei die Erweiterung <code>.sql<\/code>hat. Nach dem Aufruf wird <code>deployDump<\/code> der Fehlertext den richtigen Namen enthalten, der verwendet werden kann, um die Datei umzubenennen.<\/p><\/blockquote>\n<p><code>deployDump<\/code> erlaubt es, die Parameter der Funktion oder den R\u00fcckgabetyp ohne zus\u00e4tzliche Ma\u00dfnahmen zu \u00e4ndern, w\u00e4hrend man beim klassischen Ansatz zuerst<br \/>\nDROP FUNCTION <code>ausf\u00fchren m\u00fcsste, und erst danach<\/code>, und dann erst <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Leider gibt es einige Situationen, in denen <code>deployDump<\/code> die \u00c4nderungen nicht automatisch \u00fcbernommen werden k\u00f6nnen. Zum Beispiel, wenn eine Triggerfunktion gel\u00f6scht wird, die von mindestens einem Trigger verwendet wird. Solche Situationen m\u00fcssen manuell mit Migrationsdateien gel\u00f6st werden.<\/p>\n<p><\/p>\n<p>Wenn der Transfer von \u00c4nderungen in gespeicherten Prozeduren durch die <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex>verantwortlich ist, m\u00fcssen f\u00fcr den Transfer der anderen \u00c4nderungen in der Struktur Migrationsdateien verwendet werden. Eine gute Bibliothek f\u00fcr die Arbeit mit Migrationen ist <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/doctrine\/migrations\">doctrine\/migrations<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Migrationen m\u00fcssen vor dem Start angewendet werden <code>deployDump<\/code>. Dadurch k\u00f6nnen alle \u00c4nderungen an der Struktur vorgenommen und Probleme gel\u00f6st werden, damit die \u00c4nderungen in den gespeicherten Prozeduren sp\u00e4ter problemlos \u00fcbertragen werden k\u00f6nnen.<\/p>\n<p><\/p>\n<p>Eine detailliertere Arbeit mit Migrationen wird in den folgenden Abschnitten beschrieben.<\/p>\n<p><\/p>\n<h2 id=\"kak-naladit-process-parallelnoy-raboty-nad-proektom-neskolkih-razrabotchikov\">Wie kann der Prozess der parallelen Arbeit mehrerer Entwickler am Projekt organisiert werden?<\/h2>\n<p><\/p>\n<p>Es ist notwendig, ein Skript zur vollst\u00e4ndigen Initialisierung der Datenbank zu erstellen, das von den Entwicklern auf ihren Arbeitsmaschinen ausgef\u00fchrt wird, um die Struktur der lokalen Datenbank mit dem in VCS gespeicherten Dump abzugleichen. Am einfachsten ist es, die Initialisierung der lokalen Datenbank in 3 Schritte zu teilen:<\/p>\n<p><\/p>\n<ol>\n<li>Importieren der Datei mit der Basisstruktur, die beispielsweise genannt wird <code>base.sql<\/code> <\/li>\n<li>Anwendung der Migrationen<\/li>\n<li>Aufruf <code>deployDump<\/code><\/li>\n<\/ol>\n<p><\/p>\n<blockquote><p><code>base.sql<\/code> \u2014 dies ist der Ausgangspunkt, \u00fcber dem Migrationen angewendet werden, und es wird <code>deployDump<\/code>, das hei\u00dft <code>base.sql + Migrationen + deployDump = aktuelle Struktur der Datenbank<\/code>. Eine solche Datei kann mit dem Dienstprogramm erstellt werden <code>pg_dump<\/code>. Wird <code>base.sql<\/code> ausschlie\u00dflich bei der Initialisierung einer Datenbank von Grund auf verwendet.<\/p><\/blockquote>\n<p>Nennen wir das Skript zur vollst\u00e4ndigen Initialisierung der Datenbank <code>refresh.sh<\/code>. Der Arbeitsprozess k\u00f6nnte folgenderma\u00dfen aussehen:<\/p>\n<p><\/p>\n<ol>\n<li>Der Entwickler startet in seiner Umgebung <code>refresh.sh<\/code> und erh\u00e4lt die aktuelle Struktur der Datenbank<\/li>\n<li>Der Entwickler beginnt mit der Arbeit an der gestellten Aufgabe, indem er die lokale Datenbank an die Bed\u00fcrfnisse der neuen Funktionalit\u00e4t anpasst (<code>ALTER TABLE ... ADD COLUMN<\/code> usw.)<\/li>\n<li>Nach der Durchf\u00fchrung der Aufgabe ruft der Entwickler die Funktion <code>saveDump<\/code>auf, um die in der Datenbank vorgenommenen \u00c4nderungen in VCS zu dokumentieren<\/li>\n<li>Der Entwickler startet erneut <code>refresh.sh<\/code>, dann <code>verifyDump<\/code>, was jetzt eine Liste der \u00c4nderungen zeigt, die in die Migration aufgenommen werden sollen<\/li>\n<li>Der Entwickler \u00fcbertr\u00e4gt alle Struktur\u00e4nderungen in die Migrationsdatei, startet ein weiteres Mal <code>refresh.sh<\/code> und <code>verifyDump<\/code>, und wenn die Migration korrekt erstellt wurde, <code>verifyDump<\/code> zeigt es keine Unterschiede zwischen der lokalen Datenbank und dem gespeicherten Dump an.<\/li>\n<\/ol>\n<p><\/p>\n<p>Der oben beschriebene Prozess ist mit den Prinzipien von Gitflow kompatibel. Jeder Branch im VCS wird seine eigene Version des Dumps enthalten, und beim Zusammenf\u00fchren der Branches wird die Zusammenf\u00fchrung der Dumps durchgef\u00fchrt. In den meisten F\u00e4llen sind nach dem Zusammenf\u00fchren keine weiteren Schritte erforderlich, aber wenn in verschiedenen Branches \u00c4nderungen vorgenommen wurden, beispielsweise an derselben Tabelle, kann ein Konflikt auftreten.<\/p>\n<p><\/p>\n<p>Betrachten wir eine Konfliktsituation am Beispiel: Es gibt einen Branch <em>develop<\/em>, von dem zwei Branches abgezweigt werden: <em>feature1<\/em> und <em>feature2<\/em>, die keine Konflikte mit <em>develop<\/em>haben, aber Konflikte miteinander. Es steht die Aufgabe an, beide Branches in <em>develop<\/em>zusammenzuf\u00fchren. In einem solchen Fall wird empfohlen, zun\u00e4chst einen der Branches in <em>develop<\/em>zusammenzuf\u00fchren und dann die <em>develop<\/em> in den verbleibenden Branch zu mergen, dabei die Konflikte im verbleibenden Branch zu l\u00f6sen, bevor man den letzten Branch in <em>develop<\/em>zusammenf\u00fchrt. In der Phase der Konfliktl\u00f6sung k\u00f6nnte es notwendig sein, die Migrationsdatei im letzten Branch zu korrigieren, damit sie dem endg\u00fcltigen Dump entspricht, der die Ergebnisse der Zusammenf\u00fchrungen umfasst.<\/p>\n<p><\/p>\n<h2 id=\"kak-bezopasno-deploit-bolshee-kolichestvo-izmeneniy-v-strukture-bd-na-production-okruzhenie\">Wie k\u00f6nnen mehrere \u00c4nderungen an der Datenbankstruktur sicher in die Produktionsumgebung deployed werden?<\/h2>\n<p><\/p>\n<p>Durch die Verf\u00fcgbarkeit eines aktuellen Dumps der DB-Struktur im VCS wird es m\u00f6glich, die Produktionsdatenbank auf die genaue \u00dcbereinstimmung mit der erforderlichen Struktur zu \u00fcberpr\u00fcfen. Dies garantiert, dass alle \u00c4nderungen, die die Entwickler vorgesehen hatten, erfolgreich in die Produktionsdatenbank \u00fcbertragen wurden.<\/p>\n<p><\/p>\n<p>Da das <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl.html\">DDL<\/a><\/noindex> in PostgreSQL ist <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis\">transaktional<\/a><\/noindex>, es wird empfohlen, die folgende Reihenfolge beim Deployment einzuhalten, um im Falle eines unerwarteten Fehlers das Ganze \"schmerzlos\" auszuf\u00fchren: <code>ROLLBACK<\/code>:<\/p>\n<p><\/p>\n<ol>\n<li>Transaktion starten<\/li>\n<li>Alle Migrationen in der Transaktion ausf\u00fchren<\/li>\n<li>In derselben Transaktion <code>deployDump<\/code><\/li>\n<li>ausf\u00fchren <code>verifyDump<\/code>. Ohne die Transaktion zu beenden, durchf\u00fchren <code>COMMIT<\/code>. Wenn keine Fehler auftreten, die <code>ROLLBACK<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>. Wenn Fehler auftreten, f\u00fchren Sie<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Fazit<\/h1>\n<p><\/p>\n<p>Diese Schritte lassen sich recht leicht in bestehende Deployment-Ans\u00e4tze integrieren, einschlie\u00dflich zero-downtime. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex> Dank der oben beschriebenen Methoden kann man das Maximum an Leistung aus \"PHP + PostgreSQL\"-Projekten herausholen, und dabei wird im Vergleich zur Implementierung der gesamten Gesch\u00e4ftslogik im Hauptcode des Projekts relativ wenig an Entwicklungskomfort geopfert. Dar\u00fcber hinaus erscheint die Datenverarbeitung in<\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/447746\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 PHP-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0445 \u0421\u0423\u0411\u0414 PostgreSQL. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 \u0445\u043e\u0442\u044f\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 PostgreSQL, \u043d\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043d\u043e\u0439 \u0432 \u0411\u0414. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-31385","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Gesch\u00e4ftslogik in der Datenbank mit SchemaKeeper | ProHoster","description":"oft transparenter und erfordert weniger Code als dieselbe Funktionalit\u00e4t, die in PHP geschrieben wurde.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster","og:description":"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:40:58+00:00","article:modified_time":"2019-10-31T18:40:58+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31385","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 05:54:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:17:26","updated":"2026-01-21 05:54:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/31385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=31385"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/31385\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=31385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=31385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=31385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}