<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Guia do Desenvolvedor - Documentação</title>
	<atom:link href="https://manual.cbrconsultoria.com.br/manuais-categoria/guia-do-desenvolvedor/feed/" rel="self" type="application/rss+xml" />
	<link>https://manual.cbrconsultoria.com.br</link>
	<description>SuiteCRM em Português.</description>
	<lastBuildDate>Fri, 08 Jul 2022 19:54:26 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.3</generator>

<image>
	<url>https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/favicon-150x150.png</url>
	<title>Guia do Desenvolvedor - Documentação</title>
	<link>https://manual.cbrconsultoria.com.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Recursos Adicionais</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/recursos-adicionais/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=recursos-adicionais</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/recursos-adicionais/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 19:53:12 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2824</guid>

					<description><![CDATA[<p>Embora este livro tenha como objetivo ser um recurso completo, SuiteCRM é grande e rica em recursos. Portanto, não é possível incluir todas as informações de que você pode precisar. Aqui estão alguns recursos extras para desenvolver com SuiteCRM. &#160; Site da SuiteCRM O site suitecrm.com do SuiteCRM tem muitos recursos excelentes, incluindo: &#8211; Fóruns [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/recursos-adicionais/">Recursos Adicionais</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Embora este livro tenha como objetivo ser um recurso completo, SuiteCRM é grande e rica em recursos. Portanto, não é possível incluir todas as informações de que você pode precisar. Aqui estão alguns recursos extras para desenvolver com SuiteCRM.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Site da SuiteCRM</strong></span><br />
O site suitecrm.com do SuiteCRM tem muitos recursos excelentes, incluindo:<br />
&#8211; Fóruns da comunidade SuiteCRM &#8211; Venha e diga oi!<br />
&#8211; SuiteCRM Blog</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Recursos externos do SuiteCRM</strong></span><br />
SuiteCRM GitHub &#8211; O código-fonte SuiteCRM está hospedado no GitHub. Aqui você pode obter alterações de código de ponta e até contribuir com código.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Recursos SugarCRM</strong></span><br />
SuiteCRM tem se esforçado para permanecer compatível com a edição da comunidade SugarCRM e grande parte da documentação ainda é válida. A versão apropriada para informações do SuiteCRM é 6.5. Versões de documentação superiores a esta (ou seja, 7) provavelmente não serão relevantes.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://support.sugarcrm.com/Documentation/Unsupported_Versions/Sugar_6.5/" target="_blank" rel="noopener">Docs do desenvolvedor do SugarCRM versão 6.5</a></span><br />
<span style="color: #750303;"><a style="color: #750303;" href="https://sugarclub.sugarcrm.com/dev-club/">SugarCRM Developer Blog</a></span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Links Técnicos</strong></span><br />
<span style="color: #750303;"><a style="color: #750303;" href="https://www.php.net/" target="_blank" rel="noopener">PHP</a> </span>&#8211; a principal linguagem usada pelo SuiteCRM.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://www.smarty.net/" target="_blank" rel="noopener">Smarty</a> </span>&#8211; A linguagem de templates usada em todo o SuiteCRM.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://xdebug.org/" target="_blank" rel="noopener">XDebug</a> </span>&#8211; extensão de depuração / criação de perfil para PHP.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://git-scm.com/" target="_blank" rel="noopener">Git</a> </span>&#8211; Sistema de controle de versão distribuído.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://clarle.github.io/yui3/" target="_blank" rel="noopener">YUI</a> </span>&#8211; Biblioteca Javascript legada usada no SuiteCRM.<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://jquery.com/" target="_blank" rel="noopener">JQuery</a> </span>&#8211; biblioteca Javascript usada no SuiteCRM &#8211; preferível ao YUI.<br />
Biblioteca de e-mail do <span style="color: #750303;"><a style="color: #750303;" href="https://github.com/PHPMailer/PHPMailer" target="_blank" rel="noopener">PHPMailer</a></span> usada no SuiteCRM.<br />
<span style="color: #750303;"><a style="color: #750303;" href="http://php.net/manual/en/book.apc.php" target="_blank" rel="noopener">APC</a> </span>&#8211; Cache Alternativo de PHP. Cache de Opcode PHP compatível com SuiteCRM<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://www.php.net/manual/en/book.wincache.php" target="_blank" rel="noopener">WinCache</a> </span>&#8211; cache de PHP do Windows. Cache de Opcode PHP compatível com SuiteCRM<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://www.jetbrains.com/phpstorm/" target="_blank" rel="noopener">PHPStorm</a> </span>&#8211; PHP IDE (pago).<br />
<span style="color: #750303;"><a style="color: #750303;" href="https://www.eclipse.org/pdt/" target="_blank" rel="noopener">Eclipse PHP Development Tools</a></span> &#8211; PHP IDE (gratuito e de código aberto).</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Outros Links</strong></span><br />
<span style="color: #750303;"><a style="color: #750303;" href="https://salesagility.com/" target="_blank" rel="noopener">SalesAgility</a></span> – A empresa por trás do SuiteCRM.<br />
<span style="color: #750303;"><a style="color: #750303;" href="http://www.jsmackin.co.uk/" target="_blank" rel="noopener">Jim Mackin</a></span> – Site pessoal do autor original deste Guia do Desenvolvedor.</p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/recursos-adicionais/">Recursos Adicionais</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/recursos-adicionais/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Esquema de banco de dados</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/esquema-de-banco-de-dados/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=esquema-de-banco-de-dados</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/esquema-de-banco-de-dados/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 19:44:58 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2819</guid>

					<description><![CDATA[<p>Tabelas e diagramas SchemaSpy Para saber mais sobre nossa estrutura de banco de dados, com suas tabelas e relacionamentos, visite o SuiteCRM Database Schema, gerado com SchemaSpy. &#160; &#160; Princípios gerais e exemplos de consultas SQL Identificadores únicos SuiteCRM usa UUIDs para seus identificadores únicos. Eles têm a seguinte aparência: 46c35607-bcad-c7f1-1745-558d6b858b27. Eles podem ser gerados [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/esquema-de-banco-de-dados/">Esquema de banco de dados</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 14pt;"><strong>Tabelas e diagramas SchemaSpy</strong></span><br />
Para saber mais sobre nossa estrutura de banco de dados, com suas tabelas e relacionamentos, visite o SuiteCRM Database Schema, gerado com SchemaSpy.</p>
<p><img decoding="async" fetchpriority="high" class="alignnone size-full wp-image-2820" src="http://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schemaspy1.png" alt="" width="706" height="257" srcset="https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schemaspy1.png 706w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schemaspy1-300x109.png 300w" sizes="(max-width: 706px) 100vw, 706px" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt;"><strong>Princípios gerais e exemplos de consultas SQL</strong></span></p>
<p><span style="font-size: 14pt;"><strong>Identificadores únicos</strong></span><br />
SuiteCRM usa UUIDs para seus identificadores únicos. Eles têm a seguinte aparência: 46c35607-bcad-c7f1-1745-558d6b858b27. Eles podem ser gerados em SQL e inseridos em outras consultas como uma sub-seleção:<br />
UPDATE some_table SET id=(SELECT uuid());</p>
<p>Historicamente, desde os dias do SugarCRM, esses ids seguiram este formato, mas na prática qualquer formato era permitido, numérico, string, etc., desde que fosse único. Isso às vezes facilita muito as importações, permitindo que os esquemas de numeração anteriores sejam mantidos.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Os campos personalizados </strong></span><br />
Os campos personalizados são salvos em tabelas com o mesmo nome do módulo em que são definidos, mas com um sufixo _cstm anexado. Cada campo personalizado terá o nome que você inseriu no Studio, com um sufixo _c. Aqui está um exemplo de consulta para unir a tabela de um módulo com alguns campos personalizados (neste caso, um campo chamado idade quando criado no Studio):<br />
<span style="color: #750303;">SELECT first_name, last_name, contacts_cstm.age_c</span><br />
<span style="color: #750303;">FROM contacts</span><br />
<span style="color: #750303;">LEFT JOIN contacts_cstm</span><br />
<span style="color: #750303;">ON contacts.id = contacts_cstm.id_c</span></p>
<p>Liste registros órfãos de contacts_cstm, onde o registro base não está presente, mas uma linha para ele ainda existe na tabela personalizada:<br />
<span style="color: #750303;">SELECT * — DELETE ChildTable</span><br />
<span style="color: #750303;">FROM contacts_cstm ChildTable</span><br />
<span style="color: #750303;">LEFT JOIN contacts ParentTable</span><br />
<span style="color: #750303;">ON ChildTable.id_c = ParentTable.id</span><br />
<span style="color: #750303;">WHERE ParentTable.id IS NULL</span></p>
<p>Essa consulta é um SELECT, mas se você alterar a primeira linha para o que está depois do comentário (-), ele excluirá essas linhas. Leia o aviso acima e decida com responsabilidade.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Relacionamentos </strong></span><br />
O SuiteCRM não depende do mecanismo de banco de dados para impor relacionamentos (restrições de chave estrangeira, etc.). Todas essas coisas são tratadas no nível do aplicativo em nosso próprio código PHP. Em geral, SuiteCRM também não faz nenhuma atualização ou exclusão em cascata, há apenas algumas exceções para alguns casos específicos. Isso significa que você pode precisar de alguma limpeza periódica do banco de dados.<br />
Há um trabalho agendado &#8220;Prune banco de dados no primeiro dia do mês&#8221; que lida com algumas dessas tarefas, mas você precisa avaliar seu próprio caso para decidir sobre as tarefas de limpeza adequadas. Não existe uma solução &#8220;tamanho único&#8221; para isso, portanto, cada implementação deve seguir as etapas necessárias para seu próprio caso.<br />
Existe uma tabela chamada relacionamentos que contém informações de metadados recuperadas dos vardefs.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Maneiras típicas de JOIN tabelas </strong></span><br />
Alguns exemplos de consultas devem ser suficientes para dar uma ideia de como as tabelas SuiteCRM normalmente se referem umas às outras:</p>
<p>1. A consulta para obter dados de um campo personalizado fornecido acima; Atravessar um campo Flex Relate onde vários tipos de registros conectados são permitidos.<br />
2. O campo parent_type contém o nome do módulo relacionado, enquanto o parent_id é uma chave estrangeira para a tabela desse módulo<br />
<span style="color: #750303;">SELECT accounts.name, calls.name, calls.status</span><br />
<span style="color: #750303;">FROM accounts</span><br />
<span style="color: #750303;">INNER JOIN calls ON</span><br />
<span style="color: #750303;">calls.parent_type = ‘Accounts’ AND</span><br />
<span style="color: #750303;">calls.parent_id = accounts.id AND</span><br />
<span style="color: #750303;">calls.deleted = 0</span><br />
<span style="color: #750303;">WHERE accounts.deleted = 0</span></p>
<p>3. Uma consulta para percorrer um relacionamento muitos para muitos usando uma tabela intermediária. Neste exemplo, uma lista de nomes de contas e contatos vinculados:</p>
<p><img decoding="async" class="alignnone size-full wp-image-2821" src="http://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schema1.png" alt="" width="527" height="565" srcset="https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schema1.png 527w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/schema1-280x300.png 280w" sizes="(max-width: 527px) 100vw, 527px" /></p>
<p><span style="color: #750303;">SELECT accounts.name, contacts.first_name, contacts.last_name</span><br />
<span style="color: #750303;">FROM accounts</span><br />
<span style="color: #750303;">INNER JOIN accounts_contacts</span><br />
<span style="color: #750303;">ON (accounts.id = accounts_contacts.account_id AND accounts_contacts.deleted = 0)</span><br />
<span style="color: #750303;">INNER JOIN contacts</span><br />
<span style="color: #750303;">ON (contacts.id = accounts_contacts.contact_id AND contacts.deleted = 0)</span><br />
<span style="color: #750303;">WHERE accounts.deleted = 0</span><br />
<span style="color: #750303;">ORDER BY accounts.name</span></p>
<p>Atravessar o relacionamento email_addresses para obter os endereços de e-mail dos usuários (facilmente adaptável para outros módulos, como Contatos, Leads, etc).<br />
<span style="color: #750303;">SELECT users.user_name,</span><br />
<span style="color: #750303;">email_address</span><br />
<span style="color: #750303;">FROM users</span><br />
<span style="color: #750303;">LEFT JOIN email_addr_bean_rel</span><br />
<span style="color: #750303;">ON email_addr_bean_rel.bean_id=users.id</span><br />
<span style="color: #750303;">AND email_addr_bean_rel.bean_module = ‘Users’</span><br />
<span style="color: #750303;">AND email_addr_bean_rel.primary_address = 1</span><br />
<span style="color: #750303;">AND email_addr_bean_rel.deleted = 0</span><br />
<span style="color: #750303;">LEFT JOIN email_addresses</span><br />
<span style="color: #750303;">ON email_addresses.id = email_addr_bean_rel.email_address_id</span><br />
<span style="color: #750303;">AND email_addresses.deleted = 0</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Limpando relacionamentos com registros excluídos</strong></span><br />
Quando você apaga um registro de um módulo, em muitos casos o SuiteCRM não apaga todos os registros associados, porque é impossível decidir quais devem ou não ser removidos sem conhecer as especificidades de cada negócio. Não excluir é genericamente a abordagem sensata e conservadora. Mas se você decidir no seu caso que precisa remover algumas sobras de registros existentes anteriormente, o seguinte deve ajudá-lo.</p>
<p>Aqui está um exemplo de consulta para procurar registros órfãos, neste caso entradas de grupos de segurança que se referem a registros ausentes:<br />
<span style="color: #750303;">SELECT record_id, module, s.deleted, c.last_name, c.deleted</span><br />
<span style="color: #750303;">FROM securitygroups_records s</span><br />
<span style="color: #750303;">LEFT JOIN contacts c</span><br />
<span style="color: #750303;">ON s.record_id = c.id</span><br />
<span style="color: #750303;">WHERE c.id IS NULL AND</span><br />
<span style="color: #750303;">s.module=’Contacts’</span></p>
<p>&nbsp;</p>
<p>Esta consulta pode ser facilmente transformada em um DELETE para remover esses registros.</p>
<p>Você também pode fazer uma exclusão mais simples de linhas onde excluído = &#8216;1&#8217;, onde o próprio relacionamento foi excluído, mesmo se o record_id ainda existir:<br />
<span style="color: #750303;">SELECT record_id, module, deleted</span><br />
<span style="color: #750303;">FROM securitygroups_records</span><br />
<span style="color: #750303;">WHERE module=&#8217;Contacts&#8217; AND deleted=&#8217;1&#8242;</span></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/esquema-de-banco-de-dados/">Esquema de banco de dados</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/esquema-de-banco-de-dados/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Traduzindo Strings</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/traduzindo-strings/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=traduzindo-strings</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/traduzindo-strings/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 19:18:32 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2816</guid>

					<description><![CDATA[<p>Classe auxiliar para traduzir strings. &#160; Uso / example string definition (only for understanding the next examples): $app_strings[&#8216;LBL_EXAMPLE_APP_STR&#8217;] = &#8216;Example Application String&#8217;; $mod_strings[&#8216;LBL_EXAMPLE_MOD_STR&#8217;] = &#8216;Example string for a specified module&#8217;; $mod_strings[&#8216;LBL_EXAMPLE_VARIABLE&#8217;] = &#8216;Example string to use value of {foo}&#8217;; // Using translation for any strings $text = new LangText(&#8216;LBL_EXAMPLE_APP_STR&#8217;); echo $text; // Using translation for [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/traduzindo-strings/">Traduzindo Strings</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Classe auxiliar para traduzir strings.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Uso</strong></span><br />
<span style="color: #750303;">/ example string definition (only for understanding the next examples):</span><br />
<span style="color: #750303;">$app_strings[&#8216;LBL_EXAMPLE_APP_STR&#8217;] = &#8216;Example Application String&#8217;;</span><br />
<span style="color: #750303;">$mod_strings[&#8216;LBL_EXAMPLE_MOD_STR&#8217;] = &#8216;Example string for a specified module&#8217;;</span><br />
<span style="color: #750303;">$mod_strings[&#8216;LBL_EXAMPLE_VARIABLE&#8217;] = &#8216;Example string to use value of {foo}&#8217;;</span><br />
<span style="color: #750303;">// Using translation for any strings</span><br />
<span style="color: #750303;">$text = new LangText(&#8216;LBL_EXAMPLE_APP_STR&#8217;);</span><br />
<span style="color: #750303;">echo $text;</span><br />
<span style="color: #750303;">// Using translation for any strings with replaced strings values</span><br />
<span style="color: #750303;">$text = new LangText(&#8216;LBL_EXAMPLE_VARIABLE&#8217;, [&#8216;foo&#8217; =&gt; &#8216;bar&#8217;]);</span><br />
<span style="color: #750303;">echo $text; // output: Example string to use value of bar</span><br />
<span style="color: #750303;">// Using translation only for Module Strings</span><br />
<span style="color: #750303;">$text = new LangText(&#8216;LBL_EXAMPLE_MOD_STR&#8217;, null, LangText::USING_MOD_STRINGS);</span><br />
<span style="color: #750303;">echo $text;</span><br />
<span style="color: #750303;">// Using translation only for Application Strings</span><br />
<span style="color: #750303;">$text = new LangText(&#8216;LBL_EXAMPLE_APP_STR&#8217;, null, LangText::USING_APP_STRINGS);</span><br />
<span style="color: #750303;">echo $text;</span></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/traduzindo-strings/">Traduzindo Strings</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/traduzindo-strings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Escrevendo testes</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/escrevendo-testes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=escrevendo-testes</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/escrevendo-testes/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 19:15:52 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2814</guid>

					<description><![CDATA[<p>Os testes PHPUnit estão relacionados a uma unidade que você está testando. O caminho dos testes é idêntico ao caminho da unidade dentro da pasta de testes /…. Cada classe de teste de unidade tem um sufixo… Teste e deve estender a classe SuiteCRM \ Test \ SuitePHPUnitFrameworkTestCase. O prefixo dos métodos de teste é [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/escrevendo-testes/">Escrevendo testes</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Os testes PHPUnit estão relacionados a uma unidade que você está testando. O caminho dos testes é idêntico ao caminho da unidade dentro da pasta de testes /…. Cada classe de teste de unidade tem um sufixo… Teste e deve estender a classe SuiteCRM \ Test \ SuitePHPUnitFrameworkTestCase. O prefixo dos métodos de teste é test….</p>
<p>Por exemplo. se o /path/to/Example.php contém uma classe Example, o teste relacionado deve estar em tests / path / to / ExampleTest.php:</p>
<p>&nbsp;</p>
<p><strong>Exemplo para um teste PHPUnit</strong><br />
conteúdo de testes / caminho / para / ExampleTest.php:<br />
use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;<br />
// note: SuitePHPUnitFrameworkTestCase extends SuiteCRM\TestCaseAbstract, which extends PHPUnit_Framework_TestCase. class ExampleTest extends SuitePHPUnitFrameworkTestCase { public function testDoingSomething() { $example = new Example(); $results = $example-&gt;doSomething(); $this-&gt;assertSame(&#8216;expected value&#8217;, $results); } }</p>
<p>Veja mais sobre os testes PHPUnit em <span style="color: #750303;"><a style="color: #750303;" href="https://phpunit.readthedocs.io/" target="_blank" rel="noopener">https://phpunit.readthedocs.io</a></span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Aulas de teste:</strong></span><br />
&#8211; classe abstrata SuiteCRM \ TestCaseAbstract<br />
Implementação de um caso de teste abstrato, essa classe substitui os métodos setUp () e tearDown () para lidar com a criação e reversão da transação do banco de dados.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Testes de segurança de estado</strong></span><br />
Anteriormente, tínhamos ajudantes StateSaver e StateChecker para tornar mais fácil escrever testes seguros de estado. Isso se provou lento e complexo, então nós o substituímos por um sistema mais padrão envolvendo transações de banco de dados que são revertidas após cada teste de unidade individual.<br />
&#8211; Mantenha o estado do ambiente global do sistema limpo, especialmente em testes.<br />
&#8211; Se um teste deixar alguns dados extras no banco de dados, sistema de arquivos, superglobais, etc., isso pode alterar o comportamento dos outros testes executados posteriormente. Ao escrever um novo teste, certifique-se de que é seguro para o estado, o que significa que os testes não devem deixar nenhum dado &#8220;lixo&#8221; no estado do ambiente de teste.<br />
&#8211; Para garantir que o estado permaneça inalterado quando um teste de unidade é executado, existem algumas coisas que você deve ter em mente:<br />
&#8211; Estado do banco de dados, isso é tratado automaticamente pelo sistema de reversão da transação do banco de dados. No entanto, se você criar explicitamente uma transação de banco de dados em seu teste, precisará certificar-se de que o teste usa a estratégia de limpeza de truncamento em vez da estratégia de transação padrão.<br />
&#8211; Mudanças em arquivos no sistema de arquivos, atualmente não fazemos isso.<br />
&#8211; Nível de erro, se o seu teste depende de um nível de erro específico, você deve salvar o nível de relatório de erro que existe no início do teste, alterar o nível de erro e restaurá-lo no final do teste.<br />
&#8211; Variáveis ​​globais do PHP, elas podem ser manipuladas pelo próprio PHPUnit, embora atualmente não usemos essa funcionalidade.<br />
&#8211; Mudanças no PHP INI, elas precisam ser tratadas manualmente da mesma forma que os níveis de erro</p>
<p>&nbsp;</p>
<p>Um exemplo de restauração do nível de relatório de erro em um teste:</p>
<p><span style="color: #750303;">&lt;?php</span></p>
<p><span style="color: #750303;">use SuiteCRM\Test\SuitePHPUnitFrameworkTestCase;</span></p>
<p><span style="color: #750303;">class somethingTest extends SuitePHPUnitFrameworkTestCase {</span><br />
<span style="color: #750303;">public function testSomething() {</span><br />
<span style="color: #750303;">// Store the current error level and then set the reporting level to 0 for the test.</span><br />
<span style="color: #750303;">$errorLevelStored = error_reporting();</span><br />
<span style="color: #750303;">error_reporting(0);</span></p>
<p>&nbsp;</p>
<pre><span style="color: #750303;">    // Do test stuff

    // Restore error reporting level.
    error_reporting($errorLevelStored);
}</span></pre>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Como: Testar Imap</strong></span><br />
Desenvolvedores capazes de escrever teste IMAP (testes de unidade e de aceitação).</p>
<p>Se o modo de desenvolvedor definido e o nível de logger forem depurados, a classe ImapHandler registra cada chamada de imap, então cada chamada de método de imap registrada com o parâmetro chamado e os valores de retorno para que os desenvolvedores e testadores possam ver exatamente o que está acontecendo em segundo plano. Se imap_test definido, o sistema usa chamadas falsas por parâmetros de método predefinidos e valores de retorno em ImapHandlerFakeCalls.php para que os desenvolvedores possam adicionar mais testes para qualquer funcionalidade de e-mail, mesmo que precise de um recurso imap válido.</p>
<p>&#8211; ImapHandler: classe Wrapper para funções de extensão integrada de PHP IMAP.<br />
&#8211; ImapHandlerFacotry: recupera um ImapHandlerInterface. Pode ser ImapHandler ou ImapHandlerFake. Use $ sugar_config [&#8216;imap_test&#8217;] = true em config_override.php para ativar o modo de teste.<br />
&#8211; ImapHandlerFake: classe Wrapper para funções de extensão integrada de PHP IMAP. (apenas testes)<br />
&#8211; ImapHandlerFakeCalls.php: descreve os valores de retorno de funções imap falsas para cada chamada de função com parâmetros específicos em cada cenário de teste.<br />
&#8211; ImapHandlerFakeData: Apenas para testes, ele lida com valores de retorno falsos para chamadas falsas em um wrapper IMAP.<br />
&#8211; ImapHandlerInterface: Wrappers IMAP precisam implementar para que o sistema possa usá-lo como um manipulador IMAP.<br />
&#8211; ImapTestSettingsEntry.php: para um ponto de entrada para definir o cenário de teste atual em qualquer teste de aceitação pode chamá-lo. (exemplo de ponto de entrada: index.php? entryPoint = setImapTestSettings &amp; imap_test_settings = [índice da matriz em ImapHandlerFakeCalls.php])</p>
<p>&nbsp;</p>
<p><strong>Exemplo de uso em testes de unidade:</strong><br />
primeiro precisa incluir os seguintes arquivos:<br />
<span style="color: #750303;">include_once <strong>DIR</strong> . &#8216;/../../../../../include/Imap/ImapHandlerFakeData.php&#8217;;</span><br />
<span style="color: #750303;">include_once <strong>DIR</strong> . &#8216;/../../../../../include/Imap/ImapHandlerFake.php&#8217;;</span></p>
<p>&nbsp;</p>
<p>Exemplo de teste de unidade para conexão imap (usando dados imap falsos)</p>
<pre><span style="color: #750303;">public function testConnectMailserverUseSsl()
 {

     // using fake imap handler behaviour in test
     $fake = new ImapHandlerFakeData();

     // set up the fake handler behaviour
     $fake-&gt;add('isAvailable', null, [true]);
     $fake-&gt;add('setTimeout', [1, 60], [true]);
     $fake-&gt;add('setTimeout', [2, 60], [true]);
     $fake-&gt;add('setTimeout', [3, 60], [true]);
     $fake-&gt;add('getErrors', null, [false]);
     $fake-&gt;add('getConnection', null, [function () {
         // the current crm code needs a valid resource to an imap server
         // but also will accept a file resource
         return fopen('fakeImapResource', 'w+');
     }]);
     $fake-&gt;add('getMailboxes', ['{:/service=/notls/novalidate-cert/secure}', '*'], [[]]);
     $fake-&gt;add('ping', null, [true]);
     $fake-&gt;add('reopen', ['{:/service=}', 32768, 0], [true]);

     // instantiate a fake imap handler
     $imap = new ImapHandlerFake($fake);

     $_REQUEST['ssl'] = 1;

     // using fake imap in InboundEmail class (only for testing)
     $ie = new InboundEmail($imap);

     // test connection, it should pass
     $ret = $ie-&gt;connectMailserver();
     $this-&gt;assertEquals('true', $ret);
 }</span></pre>
<p>&nbsp;</p>
<p>variáveis ​​de configuração úteis:<br />
<span style="color: #750303;">$sugar_config[&#8216;imap_test&#8217;] = true;</span><br />
<span style="color: #750303;">$sugar_config[&#8216;logger&#8217;][&#8216;level&#8217;] = &#8216;debug&#8217;;</span><br />
<span style="color: #750303;">$sugar_config[&#8216;stack_trace_errors&#8217;] = false; // set to true for more details</span><br />
<span style="color: #750303;">$sugar_config[&#8216;developerMode&#8217;] = true;</span><br />
<span style="color: #750303;">$sugar_config[&#8216;show_log_trace&#8217;] = false; // set to true for more details</span></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/escrevendo-testes/">Escrevendo testes</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/escrevendo-testes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Configurar ambiente de teste</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/configurar-ambiente-de-teste/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=configurar-ambiente-de-teste</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/configurar-ambiente-de-teste/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 18:52:10 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2810</guid>

					<description><![CDATA[<p>Ambiente de Teste SuiteCRM fornece uma tarefa automatizada para auxiliar na configuração do ambiente de teste. &#160; Configure o ambiente de teste (bash): Abra o terminal e execute o Robô: ./vendor/bin/robo configurar: testes &#160; Configure o ambiente de teste (prompt de comando): Abra o prompt de comando e execute o Robô: . \ vendor \ [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/configurar-ambiente-de-teste/">Configurar ambiente de teste</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 14pt;"><strong>Ambiente de Teste</strong></span><br />
SuiteCRM fornece uma tarefa automatizada para auxiliar na configuração do ambiente de teste.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Configure o ambiente de teste (bash):</strong></span><br />
Abra o terminal e execute o Robô:<br />
<span style="color: #750303;">./vendor/bin/robo configurar: testes</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Configure o ambiente de teste (prompt de comando):</strong></span><br />
Abra o prompt de comando e execute o Robô:<br />
<span style="color: #750303;">. \ vendor \ bin \ robo configure: testes</span></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/configurar-ambiente-de-teste/">Configurar ambiente de teste</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/configurar-ambiente-de-teste/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Teste Automatizado</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/teste-automatizado/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=teste-automatizado</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/teste-automatizado/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Fri, 08 Jul 2022 18:49:40 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2804</guid>

					<description><![CDATA[<p>Introdução Os testes automatizados fornecem um meio de garantir que a alta qualidade do SuiteCRM seja mantida. SuiteCRM possui um conjunto de testes automatizado que é alimentado pelas estruturas de teste Codeception e PHPUnit. &#160; Suites de teste SuiteCRM oferece quatro suítes de teste diferentes. Suite Descrição install Teste de aceitação para verificar se o [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/teste-automatizado/">Teste Automatizado</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 14pt;"><strong>Introdução</strong></span><br />
Os testes automatizados fornecem um meio de garantir que a alta qualidade do SuiteCRM seja mantida. SuiteCRM possui um conjunto de testes automatizado que é alimentado pelas estruturas de teste Codeception e PHPUnit.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Suites de teste</strong></span><br />
SuiteCRM oferece quatro suítes de teste diferentes.</p>
<table class="has-subtle-pale-pink-background-color has-background">
<thead>
<tr>
<th>Suite</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td>install</td>
<td>Teste de aceitação para verificar se o assistente de instalação está funcionando corretamente.</td>
</tr>
<tr>
<td>acceptance</td>
<td>Teste automatizado de navegador, também conhecido como ‘testes de recursos’.</td>
</tr>
<tr>
<td>unit</td>
<td>Os testes de unidade verificam se uma única unidade de código, por exemplo, um método está funcionando corretamente.</td>
</tr>
<tr>
<td>api</td>
<td>Testes funcionais que testam as respostas da versão 8 da API.</td>
</tr>
</tbody>
</table>
<p>Estabelecer Este guia assume que você já instalou e configurou uma versão compatível do PHP, MySQL 5.7 e Composer. Você pode configurar o CRM para teste com estas etapas:</p>
<ol>
<li>Em seu emulador de terminal ou prompt de comando: caminho do cd / para / suitecrm / instância.</li>
<li>Instale dependências com o Composer: instalação do composer.</li>
<li>Crie um banco de dados MySQL chamado Automa_tests, junto com um usuário chamado Automa_tests e a senha Automated_tests. Na interface de linha de comando do MySQL:</li>
<li>mysql -e &#8220;CRIAR BANCO DE DADOS automatic_tests CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;&#8221;</li>
<li>mysql -u root -p -e &#8220;CRIAR USUÁRIO &#8216;Automated_tests&#8217; @ &#8216;localhost&#8217; IDENTIFICADO POR &#8216;Automated_tests&#8217;;&#8221;</li>
<li>mysql -u root -p -e &#8220;GRANT ALL PRIVILEGES ON Automated_tests. * TO &#8216;Automated_tests&#8217; @ &#8216;localhost&#8217;;&#8221;</li>
<li>Configure as variáveis ​​de ambiente, consulte a seção de variáveis ​​de ambiente abaixo para obter mais informações.</li>
<li>Configure seu servidor Apache para que o servidor SuiteCRM esteja disponível em http: // localhost (ou qualquer URL de instância que você configurou na etapa anterior).</li>
<li>Instale o ChromeDriver para que você possa usá-lo para automatizar o navegador Chrome (você também precisará do Chrome ou Chromium instalado): ./vendor/bin/robo chromedriver: instalar Você também precisará de uma instância do ChromeDriver em execução em segundo plano para o conjunto de testes usar. Você pode usar ./vendor/bin/robo chromedriver: run para executar uma instância do ChromeDriver. Isso é necessário para os pacotes de instalação e aceitação.</li>
<li>Você pode atualizar sua versão do ChromeDriver, se necessário, com ./vendor/bin/robo chromedriver: install &#8211;reinstall.</li>
<li>Crie dependências de teste com ./vendor/bin/codecept build.</li>
<li>Configure o ambiente de codecepção personalizado para permitir a execução dos testes de instalação e aceitação localmente.</li>
<li>Consulte &#8220;Configurando o ambiente de teste&#8221; abaixo.</li>
<li>Instale o SuiteCRM.</li>
<li>Isso pode ser feito executando o pacote de instalação ou passando pelo processo de instalação em seu navegador. Ele deve estar disponível em http: //localhost/install.php.</li>
<li>Preencha o banco de dados com dados de teste para o conjunto de testes da API. Substitua DATABASE_NAME pelo nome do banco de dados MySQL configurado, provavelmente automatic_tests se você seguiu as instruções acima.</li>
<li>mysql -u root -p -D DATABASE_NAME -v -e &#8220;source tests / _data / api_data.sql&#8221;</li>
<li>mysql -u root -p -D DATABASE_NAME -v -e &#8220;source tests / _data / demo_users.sql&#8221;</li>
</ol>
<p>Com isso, você deve ser capaz de executar as suítes de teste &#8211; observe que os testes de instalação só podem ser executados uma vez atualmente.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Variáveis ​​ambientais</strong></span><br />
Este é o método preferido para armazenar informações confidenciais, pois evita que as informações de segurança sejam enviadas para o repositório git. Você pode automatizar diferentes ambientes de desenvolvimento usando variáveis ​​de ambiente.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt;"><strong>Variáveis ​​de ambiente do conjunto de testes</strong></span></p>
<p><span style="font-size: 14pt;"><strong>Instale o Test Suite:</strong></span></p>
<table class="has-subtle-pale-pink-background-color has-background">
<thead>
<tr>
<th>Variável</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td>DATABASE_DRIVER</td>
<td>MYSQL ou MSSQL.</td>
</tr>
<tr>
<td>DATABASE_HOST</td>
<td>caminho para o servidor do banco de dados.</td>
</tr>
<tr>
<td>DATABASE_NAME</td>
<td>nome dobanco de dados.</td>
</tr>
<tr>
<td>DATABASE_USER</td>
<td>usuário do banco de dados.</td>
</tr>
<tr>
<td>DATABASE_PASSWORD</td>
<td>senha do banco de dados.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Aceitação, API e pacotes de teste de instalação:</p>
<table class="has-subtle-pale-pink-background-color has-background">
<thead>
<tr>
<th>Variável</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td>INSTANCE_URL</td>
<td>URL da instância SuiteCRM que o testador precisa acessar.</td>
</tr>
<tr>
<td>INSTANCE_ADMIN_USER</td>
<td>usuário administrador para fazer login.</td>
</tr>
<tr>
<td>INSTANCE_ADMIN_PASSWORD</td>
<td>senha de administrador para fazer login.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Suítes de teste de API:</p>
<table class="has-subtle-pale-pink-background-color has-background">
<thead>
<tr>
<th>Variável</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td>INSTANCE_CLIENT_ID</td>
<td>ID do cliente</td>
</tr>
<tr>
<td>INSTANCE_CLIENT_SECRET</td>
<td>Segredo do cliente</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Configurar variáveis ​​de ambiente com tarefa Robô<br />
Abra o terminal e execute o Robô:<br />
<span style="color: #750303;">./vendor/bin/robo configurar: testes (Bash)</span></p>
<p><span style="color: #750303;">. \ vendor \ bin \ robo configure: testes (prompt de comando)</span></p>
<p>Isso adicionará interativamente as variáveis ​​de ambiente necessárias ao seu arquivo ~ / .bash_aliases. Você precisa reiniciar seu terminal / prompt de comando para obter as alterações. No macOS / Linux, você pode usar env para ver as variáveis ​​de ambiente atuais.</p>
<p>Observe que essas variáveis ​​se aplicam a todo o dispositivo, portanto, se você tiver mais de um CRM configurado localmente, todos usarão a mesma configuração.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Configurando o ambiente de teste</strong></span><br />
É recomendável que você execute o conjunto de testes com um ambiente personalizado configurado, para garantir que o conjunto de testes saiba onde está a instância de CRM e para permitir que você personalize o ambiente para suportar depuração, se necessário. Copie tests / _envs / custom.dist.yml para tests / _envs / custom.yml e leia os comentários do arquivo para configurar seu ambiente. custom.yml não será rastreado pelo git, então pode ser customizado para funcionar com seu ambiente local sem ser reiniciado ou acidentalmente confirmado.</p>
<p>Você pode executar testes de codecepção em um determinado ambiente, como: ./vendor/bin/codecept executar aceitação &#8211;env custom</p>
<p>Observe que o ambiente personalizado deve ser usado apenas com os conjuntos de teste de aceitação e instalação. Há também o ambiente travis-ci-hub.yml, que serve para executar os testes no Travis CI.</p>
<p>Consulte a documentação do Codeception para obter mais informações sobre a configuração do ambiente.</p>
<p>Executando as suítes de teste<br />
Depois de configurados, você pode executar os conjuntos de testes com os seguintes comandos Robô:</p>
<table class="has-subtle-pale-pink-background-color has-background">
<thead>
<tr>
<th>Variável</th>
<th>Descrição</th>
</tr>
</thead>
<tbody>
<tr>
<td>install</td>
<td>./vendor/bin/robo tests: install</td>
</tr>
<tr>
<td>acceptance</td>
<td>./vendor/bin/robo testes: aceitação</td>
</tr>
<tr>
<td>unit</td>
<td>./vendor/bin/robo testes: unidade</td>
</tr>
<tr>
<td>api</td>
<td>./vendor/bin/robo testes: api</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Algumas coisas a serem observadas:</strong></span><br />
&#8211; Esses comandos usarão automaticamente o ambiente definido em tests / _envs / custom.yml para os conjuntos de teste de instalação e aceitação.<br />
&#8211; Cada um desses comandos leva estes sinalizadores:<br />
&#8211;debug: Imprime mais informações durante as execuções de teste, bom para depuração.<br />
&#8211;fail-fast: interrompe a execução do conjunto de testes após a primeira falha.</p>
<p>&#8211; Cada um deles também pode ser passado para um diretório ou pasta específica se você quiser executar apenas alguns testes específicos, por exemplo, ./vendor/bin/robo tests: unit ./tests/unit/phpunit/modules/.<br />
&#8211; A suíte de teste de instalação só pode ser executada uma vez atualmente, e todas as outras suítes de teste dependem do CRM que está sendo instalado.<br />
&#8211; Os conjuntos de testes de instalação e aceitação usam testes automatizados de navegador com o Chrome e exigem que o usuário execute um processo ChromeDriver separado simultaneamente com o conjunto de testes. Como alternativa, você ativa a extensão ChromeDriver RunProcess fornecida em custom.dist.yml para que o ChromeDriver inicialize automaticamente sempre que os testes precisarem.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt;"><strong>Outras opções de configuração</strong></span></p>
<p><span style="font-size: 14pt;"><strong>Docker</strong></span><br />
Você também pode executar o conjunto de testes usando o Docker, se preferir.</p>
<p><strong>Variáveis ​​de ambiente de configuração (Docker Compose):</strong><br />
Você pode adicionar um arquivo .env à configuração do Docker Compose:<br />
<span style="color: #750303;">DATABASE_DRIVER=MYSQL</span><br />
<span style="color: #750303;">DATABASE_NAME=automated_tests</span><br />
<span style="color: #750303;">DATABASE_HOST=localhost</span><br />
<span style="color: #750303;">DATABASE_USER=automated_tests</span><br />
<span style="color: #750303;">DATABASE_PASSWORD=automated_tests</span><br />
<span style="color: #750303;">INSTANCE_URL=http://path/to/instance</span><br />
<span style="color: #750303;">INSTANCE_ADMIN_USER=admin</span><br />
<span style="color: #750303;">INSTANCE_ADMIN_PASSWORD=admin</span><br />
<span style="color: #750303;">INSTANCE_CLIENT_ID=suitecrm_client</span><br />
<span style="color: #750303;">INSTANCE_CLIENT_SECRET=secret</span></p>
<p>&nbsp;</p>
<p>em seguida, faça referência a ele em seu contêiner php (docker-compose.yml):</p>
<pre><span style="color: #750303;">version: '3'
 services:
   php:
       image: php:7.0-apache
       restart: always
       ports:
         - 9001:80
       environment:
        - DATABASE_DRIVER: $DATABASE_DRIVER
        - DATABASE_NAME: $DATABASE_NAME
        - DATABASE_HOST: $DATABASE_HOST
        - DATABASE_USER: $DATABASE_USER
        - DATABASE_PASSWORD: $DATABASE_PASSWORD
        - INSTANCE_URL: $INSTANCE_URL
        - INSTANCE_ADMIN_USER: $INSTANCE_ADMIN_USER
        - INSTANCE_ADMIN_PASSWORD: $INSTANCE_ADMIN_PASSWORD
        - INSTANCE_CLIENT_ID: $INSTANCE_CLIENT_ID
        - INSTANCE_CLIENT_SECRET: $INSTANCE_CLIENT_SECRET</span></pre>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Usando Docker Compose com o Selenium Hub</strong></span><br />
Em seu ambiente de desenvolvimento de selênio, é recomendável que você empregue docker compose para configurar um hub de selênio com um nó de selênio. Isso garantirá que sua versão do Chrome ou Firefox seja mantida atualizada com a versão mais recente. Além disso, você também pode executar várias versões do PHP na mesma máquina host.</p>
<p>Você pode configurar o selênio usando docker compose. Certifique-se de ter o seguinte em seu arquivo docker-compose.yml.</p>
<pre><span style="color: #750303;">version: '3'
 services:
     selenium-hub:
       image: selenium/hub
       restart: always
       ports:
         - 4444:4444
     selenium-node-chrome:
       image: selenium/node-chrome-debug
       restart: always
       ports:
         - 5900:5900
       links:
         - selenium-hub:hub
       environment:
               - "HUB_PORT_4444_TCP_ADDR=selenium-hub"
               - "HUB_PORT_4444_TCP_PORT=4444"
     selenium-node-firefox:
       image: selenium/node-firefox-debug
       restart: always
       ports:
         - 5901:5900
       links:
         - selenium-hub:hub
       environment:
               - "HUB_PORT_4444_TCP_ADDR=selenium-hub"
               - "HUB_PORT_4444_TCP_PORT=4444"</span></pre>
<p><span style="color: #ff0000;">Nota: você também pode escolher imagens diferentes para os nós, por exemplo, os nós sem suporte de vnc</span></p>
<p>&nbsp;</p>
<p><strong>Outras dicas</strong><br />
Adicione fornecedor / bin ao seu PATH<br />
Isso tornará mais fácil executar o codeception e os outros comandos que residem no diretório vendor / bin /. Você pode adicionar a localização do fornecedor / bin à sua variável de ambiente PATH.</p>
<p><span style="color: #750303;">Adicionando fornecedor / bin ao PATH (Bash):</span><br />
<span style="color: #750303;">exportar PATH = $ PATH: / path / to / instance / vendor / bin</span><br />
<span style="color: #750303;">Adicionando fornecedor / bin ao PATH (Prompt de Comando):</span><br />
<span style="color: #750303;">defina PATH =% PATH%; C: \ path \ to \ instance \ vendor \ bin</span></p>
<p>Isso permite que você chame os comandos codecept e robo sem precisar prefixar o comando com sua localização. Ao executar qualquer um deles, você deve se certificar de que seu diretório de trabalho atual é o mesmo que sua instância SuiteCRM.</p>
<p>cd / caminho / para / suitecrm / instância /</p>
<p>aceitação de execução de codecept ou testes robô: aceitação</p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/teste-automatizado/">Teste Automatizado</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/teste-automatizado/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Criação de um mecanismo de pesquisa personalizado</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/criacao-de-um-mecanismo-de-pesquisa-personalizado/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=criacao-de-um-mecanismo-de-pesquisa-personalizado</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/criacao-de-um-mecanismo-de-pesquisa-personalizado/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Thu, 07 Jul 2022 20:39:21 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2800</guid>

					<description><![CDATA[<p>No núcleo do SearchFramework existe a natureza personalizável da classe SearchEngine. Para criar uma subclasse de SearchEngine que será detectada pelo SearchWrapper, tudo o que você precisa fazer é criar um arquivo na pasta custom / Extension / SearchEngines que estende a classe SearchEngine e implementa o método de pesquisa (SearchQuery $ query). &#160; Exemplo [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/criacao-de-um-mecanismo-de-pesquisa-personalizado/">Criação de um mecanismo de pesquisa personalizado</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>No núcleo do SearchFramework existe a natureza personalizável da classe SearchEngine. Para criar uma subclasse de SearchEngine que será detectada pelo SearchWrapper, tudo o que você precisa fazer é criar um arquivo na pasta custom / Extension / SearchEngines que estende a classe SearchEngine e implementa o método de pesquisa (SearchQuery $ query).</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Exemplo de pesquisa simulada</strong></span><br />
O exemplo abaixo mostra um mecanismo de busca que, independente de sua consulta de pesquisa, retornará o Administrador.<br />
<span style="color: #750303;">use SuiteCRM\Search\SearchEngine;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchQuery;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchResults;</span></p>
<p><span style="color: #750303;">class FakeSearch extends SearchEngine</span><br />
<span style="color: #750303;">{</span><br />
<span style="color: #750303;">public function search(SearchQuery $query)</span><br />
<span style="color: #750303;">{</span><br />
<span style="color: #750303;">return new SearchResults([</span><br />
<span style="color: #750303;">‘Users’ =&gt; [1]</span><br />
<span style="color: #750303;">]);</span><br />
<span style="color: #750303;">}</span><br />
<span style="color: #750303;">}</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Exemplo de pesquisa de cidade</strong></span><br />
O exemplo acima é perfeitamente válido e funcionaria, mas é bastante inútil. Vamos tentar fazer um mecanismo de pesquisa simples que procura contas que têm o endereço em uma determinada cidade.<br />
<span style="color: #750303;">use SuiteCRM\Search\SearchEngine;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchQuery;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchResults;</span><br />
<span style="color: #750303;">class CitySearch extends SearchEngine</span><br />
<span style="color: #750303;">{</span><br />
<span style="color: #750303;">public function search(SearchQuery $query)</span><br />
<span style="color: #750303;">{</span><br />
<span style="color: #750303;">$sql = “SELECT id FROM accounts WHERE billing_address_city = ‘%s’ OR shipping_address_city = ‘%s’ LIMIT %d OFFSET %d”;</span></p>
<pre><span style="color: #750303;"> // Format the query with the values
    $sql = sprintf(
        $sql, // SQL Query above
        $query-&gt;getSearchString(), // First equals
        $query-&gt;getSearchString(), // Second equals
        $query-&gt;getSize(), // LIMIT
        $query-&gt;getFrom() // OFFSET
    );

    // Get an instance of the dabatabase manager
    $db = DBManagerFactory::getInstance();
    // Perform the query
    $rows = $db-&gt;query($sql);
    // Initialize an array with the results
    $results = ['Accounts' =&gt; []];

    <span class="tadv-color">// Fetch the row and push the id in the results array
    while ($row = $db-&gt;fetchRow($rows)) {
        $results['Accounts'][] = $row['id'];
    }</span>

    // Make a new SearchResults object with the results array and return
    return new SearchResults($results);
}</span></pre>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Exemplo de personalização de visualização</strong></span><br />
É possível personalizar como o mecanismo de pesquisa constrói a interface substituindo os métodos displayForm () e displayResults (). Se precisar de um grau mais alto de controle, você pode substituir o método searchAndDisplay () inteiramente.</p>
<p>Por padrão, displayForm () (exibindo a barra de pesquisa) e displayResults () (exibindo resultados e erros) chamam SearchFormController e SearchResultsController respectivamente para criar as visualizações. Essas duas classes devem ser usadas e personalizadas por mecanismos de pesquisa personalizados.</p>
<p>No exemplo abaixo, iremos substituir o método displayResults () para a classe acima e dizer ao mecanismo para carregar um arquivo de modelo diferente. O arquivo de modelo é um arquivo personalizado colocado na mesma pasta do mecanismo e mostrará uma visualização de tabela com três colunas: nome do bean, endereço de entrega e endereço de cobrança. O referido arquivo de modelo smarty pode ser encontrado logo após o código da classe.</p>
<p><span style="color: #750303;">use SuiteCRM\Search\SearchEngine;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchQuery;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\SearchResults;</span><br />
<span style="color: #750303;">use SuiteCRM\Search\UI\SearchResultsController;</span></p>
<p><span style="color: #750303;">class CitySearchWithView extends SearchEngine</span><br />
<span style="color: #750303;">{</span><br />
<span style="color: #750303;">public function search(SearchQuery $query) { // Same as example above. }</span></p>
<pre><span style="color: #750303;">public function displayResults(SearchQuery $query, SearchResults $results)
{
    // Override the displayResults() method to change how the `SearchWrapper` will show the results.

    // I have used an anonymous class just for simplicity in the example.
    // The extended controller can be normally placed in a separate file.
    $controller = new class($query, $results) extends SearchResultsController
    {
        public function __construct(SearchQuery $query, SearchResults $results)
        {
            parent::__construct($query, $results);
            // Let us load a custom template file.
            $this-&gt;view-&gt;setTemplateFile(__DIR__ . '/citysearch.tpl');
        }
    };

    // Finally ask the Controller to render the view.
    $controller-&gt;display();
}</span></pre>
<p>&nbsp;</p>
<p>citysearch.tpl</p>
<p><img decoding="async" class="alignnone size-full wp-image-2801" src="http://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/Capturarhoje1.jpg" alt="" width="814" height="616" srcset="https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/Capturarhoje1.jpg 814w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/Capturarhoje1-300x227.jpg 300w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/Capturarhoje1-768x581.jpg 768w" sizes="(max-width: 814px) 100vw, 814px" /></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Exemplo de personalização de visualização</strong></span><br />
É possível personalizar como o mecanismo de pesquisa constrói a interface substituindo os métodos displayForm () e displayResults (). Se precisar de um grau mais alto de controle, você pode substituir o método searchAndDisplay () inteiramente.</p>
<p>Por padrão, displayForm () (exibindo a barra de pesquisa) e displayResults () (exibindo resultados e erros) chamam SearchFormController e SearchResultsController respectivamente para criar as visualizações. Essas duas classes devem ser usadas e personalizadas por mecanismos de pesquisa personalizados.</p>
<p>No exemplo abaixo, iremos substituir o método displayResults () para a classe acima e dizer ao mecanismo para carregar um arquivo de modelo diferente. O arquivo de modelo é um arquivo personalizado colocado na mesma pasta do mecanismo e mostrará uma visualização de tabela com três colunas: nome do bean, endereço de entrega e endereço de cobrança. O referido arquivo de modelo smarty pode ser encontrado logo após o código da classe.</p>
<p><img decoding="async" class="alignnone size-full wp-image-2802" src="http://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1.png" alt="" width="2068" height="779" srcset="https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1.png 2068w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1-300x113.png 300w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1-1024x386.png 1024w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1-768x289.png 768w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1-1536x579.png 1536w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/ErrorPage1-1-2048x771.png 2048w" sizes="(max-width: 2068px) 100vw, 2068px" /></p>
<p>Se você deseja mostrar diretamente uma mensagem de erro ao usuário, pode lançar uma SearchUserFriendlyException. Lembre-se de usar a estrutura de tradução se quiser que o erro seja localizado e nunca mostre detalhes que sejam (muito) técnicos.</p>
<p>Exemplo de envio de uma mensagem de erro amigável:<br />
<span style="color: #750303;">throw new SearchUserFriendlyException(translate(&#8216;LBL_ERROR_MESSAGE_INVALID_QUERY&#8217;));</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Conclusões</strong></span><br />
Para aprender mais sobre o Search Framework, não tenha medo de olhar o código em lib \ Search. Pretende ser simples, legível e bem documentado.</p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/criacao-de-um-mecanismo-de-pesquisa-personalizado/">Criação de um mecanismo de pesquisa personalizado</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/criacao-de-um-mecanismo-de-pesquisa-personalizado/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Quadro de pesquisa</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/quadro-de-pesquisa/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=quadro-de-pesquisa</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/quadro-de-pesquisa/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Thu, 07 Jul 2022 20:29:10 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2796</guid>

					<description><![CDATA[<p>Visão Geral O Search Framework tem como objetivo facilitar ao máximo a criação de mecanismos de busca para o SuiteCRM, com o mínimo de impacto na experiência do usuário, permitindo a reutilização de elementos da IU. Seus componentes residem no lib \ Search. Uma visão geral da estrutura do arquivo seguirá: lib\Search ├── Exceptions │   [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/quadro-de-pesquisa/">Quadro de pesquisa</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 14pt;"><strong>Visão Geral</strong></span><br />
O Search Framework tem como objetivo facilitar ao máximo a criação de mecanismos de busca para o SuiteCRM, com o mínimo de impacto na experiência do usuário, permitindo a reutilização de elementos da IU.</p>
<p>Seus componentes residem no lib \ Search. Uma visão geral da estrutura do arquivo seguirá:</p>
<pre><span style="color: #750303;">lib\Search
├── Exceptions
│   ├── SearchEngineNotFoundException.php
│   ├── SearchException.php
│   ├── SearchInvalidRequestException.php
│   └── SearchUserFriendlyException.php
├── UI
│   ├── MVC
│   │   ├── Controller.php
│   │   └── View.php
│   ├── templates
│   │   ├── search.form.tpl
│   │   └── search.results.tpl
│   ├── SearchFormController.php
│   ├── SearchFormView.php
│   ├── SearchResultsController.php
│   ├── SearchResultsView.php
│   └── SearchThrowableHandler.php
├── SearchEngine.php
├── SearchQuery.php
├── SearchResults.php
└── SearchWrapper.php</span></pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt;"><strong>Classes Principais</strong></span></p>
<p><span style="font-size: 14pt;"><strong>SearchWrapper</strong></span><br />
A principal classe do Search Framework que permite realizar pesquisas facilmente usando métodos estáticos.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Motor de busca</strong></span><br />
Classe abstrata que contém utilitários para classes que a implementam. Os métodos integrados cuidam de mostrar os resultados e a visualização da pesquisa e podem ser substituídos, se necessário. As subclasses são necessárias apenas para implementar o método search (SearchQuery $ query), embora seja recomendado substituir o método validateQuery (SearchQuery $ query) também.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Consulta de pesquisa</strong></span><br />
O objeto SearchQuery envolve todos os parâmetros usados ​​pelo SearchWrapper e SearchEngine.</p>
<p>Possui um conjunto de métodos de fábrica para preencher os parâmetros de maneira padrão.</p>
<p>Ele contém os seguintes campos (disponíveis por meio de getters):<br />
<em>$query ─ uma string contendo a consulta de pesquisa. Quando vazio, nenhuma pesquisa será realizada.</em></p>
<p><em>$size ─ Um int especificando quantos resultados são solicitados. O padrão é 10.</em></p>
<p><em>$from ─ Um int usado para paginação, efetivamente um deslocamento. O padrão é 0.</em></p>
<p><em>$engine ─ uma string contendo o nome da classe SearchEngine a ser usada. Padrões de acordo com a configuração.</em></p>
<p><em>$options ─ uma matriz contendo opções que podem ser necessárias para SearchEngines personalizados.</em></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Procurar Resultados</strong></span><br />
A classe SearchResults contém os resultados de uma pesquisa, junto com metadados como o tempo da pesquisa, o número total de ocorrências e a pontuação dos resultados.</p>
<p>Ele contém os seguintes campos (disponíveis por meio de getters):<br />
<em>$hits ─ uma matriz contendo os resultados da pesquisa. Os resultados são aninhados por módulo.</em></p>
<p><em>$scores ─ uma matriz com índices correspondentes aos de $ hits, contendo um float especificando os resultados.</em></p>
<p><em>$options ─ uma matriz contendo opções personalizadas para serem usadas pelos mecanismos.</em></p>
<p><em>$searchTime ─ um float com a quantidade de segundos que levou para realizar a pesquisa.</em></p>
<p><em>$total ─ Um int com o número total de ocorrências (sem paginação).</em></p>
<p><em>$groupedByModule ─ Sinalizador que especifica se o array $ hits é agrupado por módulo.</em></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Diagrama de Comunicação</strong></span><br />
O diagrama abaixo ilustra como funciona o processo de pesquisa, quando um usuário realiza uma pesquisa.</p>
<p>A classe Search está localizada em modules / Home / e é efetivamente o controlador que lida com a solicitação do navegador.</p>
<p><img decoding="async" class="alignnone size-full wp-image-2797" src="http://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/SearchFrameworkDiagram1.png" alt="" width="404" height="672" srcset="https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/SearchFrameworkDiagram1.png 404w, https://manual.cbrconsultoria.com.br/wp-content/uploads/2022/07/SearchFrameworkDiagram1-180x300.png 180w" sizes="(max-width: 404px) 100vw, 404px" /></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/quadro-de-pesquisa/">Quadro de pesquisa</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/quadro-de-pesquisa/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ajuste de desempenho</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/ajuste-de-desempenho/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=ajuste-de-desempenho</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/ajuste-de-desempenho/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Thu, 07 Jul 2022 20:16:52 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2793</guid>

					<description><![CDATA[<p>Na maioria dos casos, o desempenho do SuiteCRM não deve ser um problema. No entanto, no caso de grandes conjuntos de dados ou sistemas com muitos usuários, você pode notar alguma degradação de desempenho. Essas mudanças podem ajudar a melhorar o desempenho. &#160; Servidor O servidor no qual o SuiteCRM é executado é, obviamente, muito [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/ajuste-de-desempenho/">Ajuste de desempenho</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Na maioria dos casos, o desempenho do SuiteCRM não deve ser um problema. No entanto, no caso de grandes conjuntos de dados ou sistemas com muitos usuários, você pode notar alguma degradação de desempenho. Essas mudanças podem ajudar a melhorar o desempenho.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Servidor</strong></span><br />
O servidor no qual o SuiteCRM é executado é, obviamente, muito importante quando se trata do tipo de desempenho que você pode esperar. Um guia completo sobre configuração de servidor está fora do escopo deste livro. No entanto, existem algumas coisas que você pode fazer para garantir o melhor desempenho do SuiteCRM.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>PHP</strong></span><br />
A instalação de um cache opcode PHP aumentará o desempenho de todos os arquivos PHP. Eles funcionam armazenando em cache a compilação de arquivos PHP, resultando em menos trabalho em cada solicitação. Além disso, o SuiteCRM usará a API de cache de alguns aceleradores de PHP, o que aumentará ainda mais o desempenho. Se você estiver usando Linux, APC é a escolha usual. Os usuários do Windows devem verificar o WinCache.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>MySQL</strong></span><br />
O MySQL é conhecido por ter pequenas configurações padrão. A otimização total do MySQL está fora do escopo deste livro (entretanto, verifique mysqltuner.pl para um script Perl útil que fornecerá recomendações de configuração &#8211; observe que você deve ter cuidado ao executar arquivos de uma fonte desconhecida). Uma pequena mudança que pode fazer uma grande diferença é aumentar o innodb_buffer_pool_size.</p>
<p>Se você migrou ou importou uma quantidade significativa de dados, é possível que algumas tabelas fiquem fragmentadas. Executar OPTIMIZE TABLE tablename pode aumentar o desempenho.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Índices</strong></span><br />
Adicionar índices nos campos dos módulos pode melhorar o desempenho do banco de dados. Os módulos principais geralmente possuem campos importantes indexados. No entanto, se você criou um novo módulo ou adicionou novos campos frequentemente pesquisados ​​a um módulo, esses campos podem se beneficiar com a indexação. Veja o capítulo Vardef para adicionar índices.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Mudanças de configuração</strong></span><br />
A seguir estão algumas configurações que podem ser usadas para melhorar o desempenho. Observe que, na maioria dos casos, você obterá melhores ganhos de desempenho seguindo primeiro as etapas das seções anteriores. Essas configurações devem ser definidas no arquivo config_override.php. Consulte o capítulo sobre os arquivos de configuração para obter mais informações.</p>
<p><span style="color: #750303;">$sugar_config[‘developerMode’] = false;</span><br />
A menos que você esteja desenvolvendo ativamente em uma instância, o developerMode deve estar desligado. Caso contrário, cada solicitação de página fará com que os arquivos em cache sejam recarregados.</p>
<p><span style="color: #750303;">$sugar_config[‘disable_count_query’] = true;</span><br />
Para sistemas com grandes quantidades de dados, as consultas de contagem nos subpainéis usados ​​para os controles de paginação podem se tornar lentas, fazendo com que a página seja lenta ou completamente lenta para carregar. Desativar essas consultas pode melhorar drasticamente o desempenho em algumas páginas.</p>
<p><span style="color: #750303;">$sugar_config[&#8216;disable_vcr&#8217;] = true;</span><br />
Por padrão, abrir a exibição de detalhes de um registro na exibição de lista também carregará os outros registros na lista para permitir uma movimentação fácil pelos registros. Se você não usar este recurso ou se o carregamento da visualização de detalhes para alguns registros estiver lento, você pode desativar este recurso.</p>
<p><span style="color: #750303;">$sugar_config[‘list_max_entries_per_page’] = ’10’;</span><br />
O número de registros mostrado em cada página da exibição de lista pode ser diminuído. Isso resultará em um ligeiro aumento no desempenho nas páginas de exibição de lista.</p>
<p><span style="color: #750303;">$sugar_config[‘logger’][‘level’] = ‘fatal’;</span><br />
Reduzir o nível de log significa que haverá menos mensagens de log para gravar no disco em cada solicitação. Isso aumentará ligeiramente (muito ligeiramente) o desempenho.</p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/ajuste-de-desempenho/">Ajuste de desempenho</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/ajuste-de-desempenho/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Melhores Práticas</title>
		<link>https://manual.cbrconsultoria.com.br/manuais/melhores-praticas/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=melhores-praticas</link>
					<comments>https://manual.cbrconsultoria.com.br/manuais/melhores-praticas/#respond</comments>
		
		<dc:creator><![CDATA[cbr]]></dc:creator>
		<pubDate>Thu, 07 Jul 2022 20:09:53 +0000</pubDate>
				<guid isPermaLink="false">http://manual.cbrconsultoria.com.br/?post_type=docs&#038;p=2790</guid>

					<description><![CDATA[<p>Instâncias de desenvolvimento Ao fazer alterações, você deve sempre usar uma instância de desenvolvimento ou teste primeiro. Isso permite que você teste todas as alterações de forma completa e segura. &#160; Controle de versão Ao desenvolver personalizações, é prudente usar alguma forma de controle de versão. O controle de versão permite rastrear alterações em sua [&#8230;]</p>
<p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/melhores-praticas/">Melhores Práticas</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 14pt;"><strong>Instâncias de desenvolvimento</strong></span><br />
Ao fazer alterações, você deve sempre usar uma instância de desenvolvimento ou teste primeiro. Isso permite que você teste todas as alterações de forma completa e segura.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Controle de versão</strong></span><br />
Ao desenvolver personalizações, é prudente usar alguma forma de controle de versão. O controle de versão permite rastrear alterações em sua base de código, além de reverter as alterações. Existem muitos sistemas de controle de versão disponíveis. SuiteCRM usa Git, embora eu também goste de Mercurial.</p>
<p>Se você estiver usando uma instância de desenvolvimento (como mencionado acima), o Controle de Versão geralmente permite que você envie alterações para outras versões ou para liberar tags. Isso fornece uma maneira de enviar alterações para instâncias ativas ou de teste com segurança. Crucialmente, também significa que, caso haja problemas graves com uma versão, isso pode ser facilmente revertido.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Cópia de segurança</strong></span><br />
SuiteCRM foi desenvolvido para ser personalizável. No entanto, erros, bugs e outras coisas desagradáveis ​​podem (e graças à lei de Murphy, vão) acontecer. Antes de fazer qualquer alteração, você deve sempre se certificar de que possui um backup de todos os arquivos e do banco de dados.</p>
<p>Para fazer backup dos arquivos, você pode simplesmente criar um arquivo zip do diretório SuiteCRM e copiá-lo para um local seguro. Em sistemas Linux, isso pode ser realizado usando o seguinte:<br />
<span style="color: #750303;">Exemplo 17.1: backup de arquivo</span><br />
<span style="color: #b00909;">tar -czvf suitecrmfilebackup.tar.gz /path/to/suitecrm</span></p>
<p>&nbsp;</p>
<p>O backup do banco de dados SuiteCRM irá variar dependendo de qual banco de dados você está usando. No entanto, os backups do MySQL podem ser executados usando o comando mysqldump no Linux, como visto aqui:<br />
<span style="color: #750303;">Exemplo 17.2: backup do banco de dados MySQL</span><br />
<span style="color: #b00909;">mysqldump suitecrmdatabase -u databaseuser -p | gzip -c | cat&gt; suitecrm.sql.gz</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Seja um upgrade seguro</strong></span><br />
A menos que você esteja fazendo alterações em um módulo personalizado, você deve se esforçar em todos os casos para usar a estrutura personalizada e fazer alterações na pasta personalizada. Isso garante que, caso você cometa um erro, retificá-lo seja tão simples quanto remover a personalização.</p>
<p>No entanto, a principal vantagem de usar o personalizado é que, quando você atualizar o SuiteCRM no futuro, você não terá suas alterações sobrescritas pelos arquivos do SuiteCRM atualizados. Consulte o capítulo Extensões para obter mais informações.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Use níveis de registro apropriados</strong></span><br />
O uso de níveis de registro apropriados (consulte o capítulo sobre Registro) torna mais fácil rastrear problemas. Você não quer que mensagens muito importantes sejam registradas como depuração, pois isso dificultará sua localização. Da mesma forma, você não quer mensagens de registro sem importância bagunçando a saída do registro fatal.</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Ganchos lógicos de longa duração</strong></span><br />
Se uma tarefa de gancho lógico é de longa execução, você deve colocá-la na fila de trabalhos (consulte os capítulos Ganchos Lógicos e Tarefas Agendadas).</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Minimize SQL</strong></span><br />
Sempre que possível, você deve se esforçar para usar os métodos fornecidos pelo SuiteCRM para acessar dados. Isso inclui o uso de beans e da BeanFactory onde possível (consulte o capítulo Trabalhando com beans). Existem algumas razões para isso. A primeira é que o SQL geralmente é codificado ou deve ser construído dinamicamente. No caso em que o SQL está codificado, isso significa que as alterações nos campos não serão refletidas, tornando o código mais frágil.</p>
<p>O SQL dinâmico é melhor porque pode reagir às mudanças de campo e geralmente ser adaptado para se ajustar à situação. No entanto, isso requer a adição de código extra, muitas vezes complexo. Pode ser difícil explicar todas as situações (isso pode ser especialmente problemático ao tentar atravessar relacionamentos dinamicamente).</p>
<p>Outro problema é que, normalmente, o SQL acabará sendo específico do Banco de Dados (consulte o próximo ponto para atenuar isso, no entanto).</p>
<p>Finalmente, qualquer lógica customizada (como Logic Hooks) que normalmente seria disparada para salvar beans ou relacionamentos não será disparada para consultas SQL.</p>
<p>&nbsp;</p>
<p><strong>Uso de SQL</strong><br />
Em alguns casos, o uso de SQL bruto é inevitável. Se for esse o caso, você deve se esforçar para usar o SQL compatível com o padrão. Se recursos específicos do mecanismo de banco de dados precisam ser usados ​​e você deseja direcionar outros mecanismos de banco de dados, pode verificar o tipo de banco de dados. Por exemplo:<br />
<span style="color: #750303;">Exemplo 17.1: Verificando o mecanismo de banco de dados</span></p>
<pre><span style="color: #750303;">function getSomeSQLQuery(){
      global $sugar_config;
      switch($sugar_config['dbconfig']['db_type']){
          case 'mssql':
              $sql = 'MSSQL specific SQL';
              break;
          case 'mysql':
          default:
              $sql = 'MySQL specific SQL';
              break;
      }
      return $sql;
 }
</span></pre>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Verificação de entrada</strong></span><br />
A maioria dos arquivos SuiteCRM começará com alguma variação da seguinte linha:</p>
<p><span style="color: #750303;">Exemplo 17.2: Verificação de entrada</span><br />
<span style="color: #b00909;">if (! defined (&#8216;sugarEntry&#8217;) ||! sugarEntry) die (&#8216;Não é um ponto de entrada válido&#8217;);</span></p>
<p>Isso evita o acesso direto ao arquivo garantindo que o SuiteCRM foi carregado por meio de um ponto de entrada válido (ou seja, foi carregado por meio de index.php, cron.php ou um ponto de entrada personalizado).</p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt;"><strong>Redirecionar após a postagem</strong></span><br />
Às vezes, você pode ter ações de controlador personalizadas (consulte a seção de controladores) ou pontos de entrada personalizados (consulte o capítulo Pontos de entrada). Essas ações e pontos de entrada ou outras páginas geralmente são acessados ​​usando POST. Após uma solicitação POST, é uma prática recomendada da web redirecionar para uma página diferente, especialmente se sua página fizer alterações. Isso evita que o usuário atualize a página e cause uma ação duplicada. No SuiteCRM, é melhor usar o método SugarApplication :: redirect para redirecionar. Isso simplesmente aceita um URL. Do seguinte modo:<br />
<span style="color: #750303;">Exemplo 17.3: Redirecionando dentro do SuiteCRM</span><br />
<span style="color: #b00909;">SugarApplication :: redirect (&#8216;index.php? Module = &#8216;);</span></p><p>The post <a href="https://manual.cbrconsultoria.com.br/manuais/melhores-praticas/">Melhores Práticas</a> first appeared on <a href="https://manual.cbrconsultoria.com.br">Documentação</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://manual.cbrconsultoria.com.br/manuais/melhores-praticas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
