{"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\/pt\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","title":{"rendered":"L\u00f3gica de neg\u00f3cios em um banco de dados usando SchemaKeeper","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>O objetivo deste artigo \u00e9, usando a biblioteca <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> mostrar ferramentas que permitem simplificar consideravelmente o processo de desenvolvimento de bancos de dados em projetos PHP que utilizam o SGBD PostgreSQL.<\/p>\n<p><\/p>\n<p>As informa\u00e7\u00f5es deste artigo ser\u00e3o especialmente \u00fateis para desenvolvedores que desejam aproveitar ao m\u00e1ximo as capacidades do PostgreSQL, mas enfrentam problemas de manuten\u00e7\u00e3o da l\u00f3gica de neg\u00f3cios que foi delegada ao banco de dados. <\/p>\n<p><\/p>\n<p>O artigo n\u00e3o ir\u00e1 descrever as vantagens ou desvantagens de armazenar a l\u00f3gica de neg\u00f3cios no banco de dados. Assume-se que a escolha j\u00e1 foi feita pelo leitor.<\/p>\n<p><\/p>\n<p>Ser\u00e3o discutidas as seguintes quest\u00f5es:<\/p>\n<p><\/p>\n<ol>\n<li>De que forma armazenar o dump da estrutura do banco de dados no sistema de controle de vers\u00f5es (daqui em diante, VCS)<\/li>\n<li>Como acompanhar as altera\u00e7\u00f5es na estrutura do banco de dados ap\u00f3s salvar o dump<\/li>\n<li>Como transferir altera\u00e7\u00f5es na estrutura do banco de dados para outros ambientes sem conflitos e arquivos gigantes de migra\u00e7\u00e3o<\/li>\n<li>Como estabelecer o processo de trabalho paralelo em um projeto com v\u00e1rios desenvolvedores<\/li>\n<li>Como implantar com seguran\u00e7a um maior n\u00famero de altera\u00e7\u00f5es na estrutura do banco de dados no ambiente de produ\u00e7\u00e3o<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<blockquote><p><strong>SchemaKeeper<\/strong> \u00e9 projetado para trabalhar com procedimentos armazenados escritos na linguagem <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex>. Testes com outras linguagens n\u00e3o foram realizados, portanto, seu uso pode n\u00e3o ser t\u00e3o eficaz ou pode ser imposs\u00edvel.\n<\/p><\/blockquote>\n<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"v-kakom-vide-hranit-damp-struktury-bd-v-vcs\">De que forma armazenar o dump da estrutura do banco de dados no VCS<\/h2>\n<p><\/p>\n<p>A biblioteca <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> oferece a fun\u00e7\u00e3o <code>saveDump<\/code>, que salva a estrutura de todos os objetos do banco de dados como arquivos de texto separados. O resultado \u00e9 um diret\u00f3rio que cont\u00e9m a estrutura do banco de dados, dividida em arquivos agrupados que podem ser facilmente adicionados ao VCS.<\/p>\n<p><\/p>\n<p>Vamos considerar a convers\u00e3o de objetos do banco de dados em arquivos com alguns exemplos:<\/p>\n<p><\/p>\n<p>Tipo de objeto<br \/>\nEsquema<br \/>\nNome<br \/>\nCaminho relativo para o arquivo<\/p>\n<p>Tabela<br \/>\npublic<br \/>\naccounts<br \/>\n<code>.\/public\/tables\/accounts.txt<\/code><\/p>\n<p>Procedimento armazenado<br \/>\npublic<br \/>\nauth(hash bigint)<br \/>\n<code>.\/public\/functions\/auth(int8).sql<\/code><\/p>\n<p>Visualiza\u00e7\u00e3o<br \/>\nbooking<br \/>\ntariffs<br \/>\n<code>.\/booking\/views\/tariffs.txt<\/code><\/p>\n<p><\/p>\n<p>O conte\u00fado dos arquivos \u00e9 uma representa\u00e7\u00e3o textual da estrutura de um determinado objeto do banco de dados. Por exemplo, para procedimentos armazenados, o conte\u00fado do arquivo ser\u00e1 a defini\u00e7\u00e3o completa do procedimento armazenado, come\u00e7ando com o bloco <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Como pode ser visto na tabela acima, o caminho para o arquivo cont\u00e9m informa\u00e7\u00f5es sobre o tipo, o esquema e o nome do objeto. Essa abordagem facilita a navega\u00e7\u00e3o pelo dump e a revis\u00e3o do c\u00f3digo das altera\u00e7\u00f5es no banco de dados.<\/p>\n<p><\/p>\n<blockquote><p>Extens\u00e3o <code>.sql<\/code> para arquivos com c\u00f3digo de procedimentos armazenados, foi escolhido para que o IDE forne\u00e7a automaticamente ferramentas para interagir com o banco de dados ao abrir o arquivo.<\/p><\/blockquote>\n<p><\/p>\n<h2 id=\"kak-otslezhivat-izmeneniya-v-strukture-bd-posle-sohraneniya-dampa\">Como acompanhar as altera\u00e7\u00f5es na estrutura do banco de dados ap\u00f3s salvar o dump<\/h2>\n<p><\/p>\n<p>Ao salvar o dump da estrutura atual do banco de dados no VCS, obtemos a possibilidade de verificar se houve altera\u00e7\u00f5es na estrutura do banco ap\u00f3s a cria\u00e7\u00e3o do dump. Na biblioteca <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> para identificar altera\u00e7\u00f5es na estrutura do banco de dados, existe a fun\u00e7\u00e3o <code>verifyDump<\/code>, que retorna informa\u00e7\u00f5es sobre as diferen\u00e7as sem efeitos colaterais. <\/p>\n<p><\/p>\n<p>Uma maneira alternativa de verifica\u00e7\u00e3o \u00e9 chamar novamente a fun\u00e7\u00e3o <code>saveDump<\/code>, especificando o mesmo diret\u00f3rio, e verificar no VCS a exist\u00eancia de altera\u00e7\u00f5es. Como todos os objetos do banco de dados s\u00e3o salvos em arquivos separados, o VCS mostrar\u00e1 apenas os objetos que foram alterados.<br \/>\nA principal desvantagem deste m\u00e9todo \u00e9 a necessidade de reescrever arquivos para ver as mudan\u00e7as.<\/p>\n<p><\/p>\n<h2 id=\"kak-perenosit-izmeneniya-v-strukture-bd-na-drugie-okruzheniya-bez-konfliktov-i-gigantskih-faylov-migraciy\">Como transferir altera\u00e7\u00f5es na estrutura do banco de dados para outros ambientes sem conflitos e arquivos gigantes de migra\u00e7\u00e3o<\/h2>\n<p><\/p>\n<p>Gra\u00e7as \u00e0 fun\u00e7\u00e3o <code>deployDump<\/code> o c\u00f3digo fonte de procedimentos armazenados pode ser editado exatamente da mesma forma que o c\u00f3digo fonte normal do aplicativo. \u00c9 poss\u00edvel adicionar\/remover novas linhas no c\u00f3digo dos procedimentos armazenados e imediatamente enviar as altera\u00e7\u00f5es para o sistema de controle de vers\u00f5es, ou criar\/remover procedimentos armazenados criando\/removendo os arquivos correspondentes no diret\u00f3rio do dump. <\/p>\n<p><\/p>\n<p>Por exemplo, para criar um novo procedimento armazenado no esquema <code>public<\/code> basta criar um novo arquivo com a extens\u00e3o <code>.sql<\/code> no diret\u00f3rio <code>public\/functions<\/code>, colocar nele o c\u00f3digo fonte do procedimento armazenado, incluindo o bloco <code>CREATE OR REPLACE FUNCTION<\/code>, e em seguida chamar a fun\u00e7\u00e3o <code>deployDump<\/code>. De maneira semelhante, ocorre a altera\u00e7\u00e3o e exclus\u00e3o de um procedimento armazenado. Assim, o c\u00f3digo \u00e9 enviado simultaneamente ao VCS e ao banco de dados. <\/p>\n<p><\/p>\n<p>Se ocorrer um erro no c\u00f3digo fonte de algum procedimento armazenado, ou uma discrep\u00e2ncia entre os nomes do arquivo e do procedimento armazenado, ent\u00e3o <code>deployDump<\/code> n\u00e3o ser\u00e1 executado, exibindo o texto do erro. A descoordena\u00e7\u00e3o dos procedimentos armazenados entre o dump e o banco de dados atual \u00e9 imposs\u00edvel ao usar <code>deployDump<\/code>.<\/p>\n<p><\/p>\n<blockquote><p>Ao criar um novo procedimento armazenado, n\u00e3o \u00e9 necess\u00e1rio inserir manualmente o nome correto do arquivo. Basta que o arquivo tenha a extens\u00e3o <code>.sql<\/code>. Ap\u00f3s a chamada, <code>deployDump<\/code> o texto do erro conter\u00e1 o nome correto, que pode ser usado para renomear o arquivo.<\/p><\/blockquote>\n<p><code>deployDump<\/code> permite alterar os par\u00e2metros da fun\u00e7\u00e3o ou o tipo de retorno sem a\u00e7\u00f5es adicionais, enquanto que com a abordagem cl\u00e1ssica seria necess\u00e1rio<br \/>\nprimeiro executar <code>DROP FUNCTION<\/code>, e somente depois <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Infelizmente, existem algumas situa\u00e7\u00f5es em que <code>deployDump<\/code> n\u00e3o \u00e9 poss\u00edvel aplicar altera\u00e7\u00f5es automaticamente. Por exemplo, se uma fun\u00e7\u00e3o de gatilho que \u00e9 utilizada por pelo menos um gatilho \u00e9 exclu\u00edda. Essas situa\u00e7\u00f5es devem ser resolvidas manualmente usando arquivos de migra\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Se a transfer\u00eancia de mudan\u00e7as em procedimentos armazenados \u00e9 responsabilidade do pr\u00f3prio <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex>, ent\u00e3o, para transferir as demais altera\u00e7\u00f5es na estrutura, \u00e9 necess\u00e1rio utilizar arquivos de migra\u00e7\u00e3o. Por exemplo, uma boa biblioteca para trabalhar com migra\u00e7\u00f5es \u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/doctrine\/migrations\">doctrine\/migrations<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>As migra\u00e7\u00f5es devem ser aplicadas antes do <code>deployDump<\/code>. Isso permite implementar todas as altera\u00e7\u00f5es na estrutura e resolver situa\u00e7\u00f5es problem\u00e1ticas, para que as mudan\u00e7as nos procedimentos armazenados sejam transferidas sem problemas posteriormente.<\/p>\n<p><\/p>\n<p>O trabalho com migra\u00e7\u00f5es ser\u00e1 descrito em mais detalhes nas se\u00e7\u00f5es seguintes.<\/p>\n<p><\/p>\n<h2 id=\"kak-naladit-process-parallelnoy-raboty-nad-proektom-neskolkih-razrabotchikov\">Como estabelecer o processo de trabalho paralelo em um projeto com v\u00e1rios desenvolvedores<\/h2>\n<p><\/p>\n<p>\u00c9 necess\u00e1rio criar um script de inicializa\u00e7\u00e3o completa do BD, que ser\u00e1 executado pelo desenvolvedor em sua m\u00e1quina de trabalho, alinhando a estrutura do BD local ao dump salvo no VCS. \u00c9 mais f\u00e1cil dividir a inicializa\u00e7\u00e3o do BD local em 3 etapas:<\/p>\n<p><\/p>\n<ol>\n<li>Importar o arquivo com a estrutura base, que ser\u00e1 chamado, por exemplo, <code>base.sql<\/code> <\/li>\n<li>Aplica\u00e7\u00e3o das migra\u00e7\u00f5es<\/li>\n<li>Chamada <code>deployDump<\/code><\/li>\n<\/ol>\n<p><\/p>\n<blockquote><p><code>base.sql<\/code> \u2014 \u00e9 o ponto de partida sobre o qual as migra\u00e7\u00f5es s\u00e3o aplicadas e \u00e9 executado <code>deployDump<\/code>, ou seja, <code>base.sql + migra\u00e7\u00f5es + deployDump = estrutura atual do BD<\/code>. Um arquivo assim pode ser gerado com a ajuda da ferramenta <code>pg_dump<\/code>. \u00c9 usado <code>base.sql<\/code> exclusivamente ao inicializar o banco de dados do zero.<\/p><\/blockquote>\n<p>Vamos chamar o script de inicializa\u00e7\u00e3o completa do BD <code>refresh.sh<\/code>. O fluxo de trabalho pode ser assim:<\/p>\n<p><\/p>\n<ol>\n<li>O desenvolvedor executa em seu ambiente <code>refresh.sh<\/code> e obt\u00e9m a estrutura atual do BD<\/li>\n<li>O desenvolvedor come\u00e7a a trabalhar na tarefa atribu\u00edda, modificando o BD local para as necessidades da nova funcionalidade (<code>ALTER TABLE ... ADD COLUMN<\/code> etc.)<\/li>\n<li>Ap\u00f3s a conclus\u00e3o da tarefa, o desenvolvedor chama a fun\u00e7\u00e3o <code>saveDump<\/code>, para registrar no VCS as altera\u00e7\u00f5es feitas no BD<\/li>\n<li>O desenvolvedor executa novamente <code>refresh.sh<\/code>, ent\u00e3o <code>verifyDump<\/code>, que agora mostra a lista de altera\u00e7\u00f5es para inclus\u00e3o na migra\u00e7\u00e3o<\/li>\n<li>O desenvolvedor transfere todas as mudan\u00e7as de estrutura para o arquivo de migra\u00e7\u00e3o, executa novamente <code>refresh.sh<\/code> e <code>verifyDump<\/code>, e, se a migra\u00e7\u00e3o estiver correta, <code>verifyDump<\/code> mostrar\u00e1 que n\u00e3o h\u00e1 diferen\u00e7as entre o BD local e o dump salvo.<\/li>\n<\/ol>\n<p><\/p>\n<p>O processo descrito acima \u00e9 compat\u00edvel com os princ\u00edpios do gitflow. Cada branch no VCS conter\u00e1 sua pr\u00f3pria vers\u00e3o do dump, e ao mesclar branches acontecer\u00e1 a fus\u00e3o dos dumps. Na maioria dos casos, ap\u00f3s a fus\u00e3o, n\u00e3o \u00e9 necess\u00e1rio realizar nenhuma a\u00e7\u00e3o adicional, mas se altera\u00e7\u00f5es foram feitas em diferentes branches, por exemplo, na mesma tabela, um conflito pode ocorrer.<\/p>\n<p><\/p>\n<p>Consideremos uma situa\u00e7\u00e3o de conflito com o seguinte exemplo: h\u00e1 uma branch <em>develop<\/em>, da qual duas branches foram criadas: <em>feature1<\/em> e <em>feature2<\/em>, que n\u00e3o t\u00eam conflitos com <em>develop<\/em>, mas t\u00eam conflitos entre si. O objetivo \u00e9 mesclar ambas as branches em <em>develop<\/em>. Para esse caso, recomenda-se primeiro mesclar uma das branches em <em>develop<\/em>, e depois mesclar <em>develop<\/em> na branch restante, resolvendo os conflitos na branch restante, ap\u00f3s o que a \u00faltima branch pode ser mesclada em <em>develop<\/em>. No est\u00e1gio de resolu\u00e7\u00e3o de conflitos, pode ser necess\u00e1rio corrigir o arquivo de migra\u00e7\u00e3o na \u00faltima branch, para que ele corresponda ao dump final, que inclui os resultados das fus\u00f5es.<\/p>\n<p><\/p>\n<h2 id=\"kak-bezopasno-deploit-bolshee-kolichestvo-izmeneniy-v-strukture-bd-na-production-okruzhenie\">Como implantar com seguran\u00e7a um maior n\u00famero de altera\u00e7\u00f5es na estrutura do banco de dados no ambiente de produ\u00e7\u00e3o<\/h2>\n<p><\/p>\n<p>Gra\u00e7as \u00e0 presen\u00e7a de um dump da estrutura atual do banco de dados no VCS, \u00e9 poss\u00edvel verificar o banco de produ\u00e7\u00e3o em rela\u00e7\u00e3o \u00e0 estrutura exigida. Isso garante que todas as altera\u00e7\u00f5es que os desenvolvedores tinham em mente foram transferidas com sucesso para o banco de produ\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>Uma vez que <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl.html\">DDL<\/a><\/noindex> no PostgreSQL \u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis\">transacional<\/a><\/noindex>, recomenda-se seguir a seguinte ordem de deploy, para que, em caso de erro inesperado, possa ser executado um <code>ROLLBACK<\/code>:<\/p>\n<p><\/p>\n<ol>\n<li>Iniciar transa\u00e7\u00e3o<\/li>\n<li>Executar todas as migra\u00e7\u00f5es na transa\u00e7\u00e3o<\/li>\n<li>Na mesma transa\u00e7\u00e3o, executar <code>deployDump<\/code><\/li>\n<li>. Sem encerrar a transa\u00e7\u00e3o, executar <code>verifyDump<\/code>. Se n\u00e3o houver erros, executar <code>COMMIT<\/code>. Se houver erros, executar <code>ROLLBACK<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Esses passos se integram facilmente nas abordagens existentes de deploy de aplica\u00e7\u00f5es, incluindo zero-downtime.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Conclus\u00e3o<\/h1>\n<p><\/p>\n<p>Gra\u00e7as aos m\u00e9todos descritos acima, \u00e9 poss\u00edvel extrair o m\u00e1ximo de desempenho de projetos \"PHP + PostgreSQL\", sacrificando uma quantidade relativamente pequena de conforto de desenvolvimento em compara\u00e7\u00e3o com a implementa\u00e7\u00e3o de toda a l\u00f3gica de neg\u00f3cios no c\u00f3digo principal da aplica\u00e7\u00e3o. Al\u00e9m disso, o processamento de dados em <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex> geralmente parece mais transparente e requer menos c\u00f3digo do que a mesma funcionalidade escrita em PHP.<\/p>\n<p>Fonte: <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.3 - 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\/pt\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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\udd47L\u00f3gica de neg\u00f3cios no banco de dados com o SchemaKeeper | ProHoster","description":"O objetivo deste artigo \u00e9, usando a biblioteca schema-keeper como exemplo, mostrar as ferramentas que permitem uma melhoria substancial.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/31385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=31385"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/31385\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=31385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=31385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=31385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}