PHP 库用于执行 SQL 文件。仅限 Adianti 项目使用。

1.0.7 2020-12-09 21:07 UTC

This package is auto-updated.

Last update: 2024-10-02 01:41:36 UTC


README

关于组件

TQuery 类被开发出来,为 Adianti 框架引入了一种不同的查询构建和执行方法。

使用它,可以执行.sql文件,从而将SQL指令与PHP代码分离。

因此,我们可以更好地阅读SQL代码。

安装

由于这是一个composer包,只需使用以下命令:

 composer require 'jheferson-br/tquery'

使用示例

为了更好地理解类的工作方式,请看以下简单示例。

假设我们需要在数据库中执行以下指令以清理系统表

TRUNCATE TABLE cliente;
TRUNCATE TABLE produto;
TRUNCATE TABLE fornecedor;

该文件位于项目根目录的 app/querys/ 文件夹中,名为 LimpaTabelas.sql

使用TQuery类,代码如下:

TTransaction::open('ERP');

// instanciando o objeto TQuery.
$sql = new TQuery("LimpaTabelas.sql");
//Definindo o local onde os arquivos '.sql' serão encontrados.
$sql->setBasePathQuerys("app/querys/");
//Definindo um separador de querys para a execução de varios comandos dentro do mesmo arquivo .sql
$sql->setMultiQuerySeparator(";");
//Executando as querys.
$afected_rows = $sql->execute();
//Imprimindo na tela a quantidade de linhas que sofreram alterações com a execução da query.
print_r($afected_rows);

请注意,TQuery类需要在 TTransaction 中打开事务才能执行,这与Adianti框架的标准一致。

此外,所有使用 execute() 方法执行的操作都将记录在Adianti的日志系统中。

TQuery还能够执行查询,如复杂的连接。在框架中,通常建议使用视图,但有时这会变得难以维护。

因此,开发了 load() 方法,该方法可以接收框架自带的 TCriteria 作为参数,从而保持与框架的兼容性。

想象一下需要执行以下复杂的连接

    SELECT 
    `mes`.`men_mesano` AS `men_mesano`,
    `mes`.`men_insc_muni` AS `men_insc_muni`,
    `mes`.`men_conta` AS `men_conta`,
    `pla`.`pla_bacen`,
    `mes`.`cod_trib_desif` AS `cod_trib_desif`,
    SUM(if(COALESCE(`mes`.`men_mes_santer`,0) < 0, 0, COALESCE(`mes`.`men_mes_santer`,0))) AS `sald_inic`,
    SUM(COALESCE(`mes`.`men_cred_mes`,0)) AS `men_cred_mes`,
    SUM(COALESCE(`mes`.`men_deb_mes`,0)) AS `men_deb_mes`,
    SUM(COALESCE(`mes`.`men_tributavel`,0)) AS `men_tributavel`,
    SUM(COALESCE(`mes`.`men_deducao`,0)) AS `men_deducao`,
    SUM(COALESCE(`mes`.`men_tributavel`,0)) - SUM(`mes`.`men_deducao`) AS `base_calc`,
    (
      SUM(COALESCE(`mes`.`men_tributavel`,0)) - SUM(COALESCE(`mes`.`men_deducao`,0))
    ) * COALESCE(`mes`.`men_aliquota`,0) / 100 AS `valr_issqn_retd`,
    `mes`.`men_desc_dedu` AS `men_desc_dedu`,
    `mes`.`men_aliquota` AS `men_aliquota`,
    `mes`.`men_incentivo` AS `men_incentivo`,
    `mes`.`men_desc_incen` AS `men_desc_incen`,
    `mes`.`men_motivo_nao_exig` AS `men_motivo_nao_exig`,
    `mes`.`men_processo_nao_exig` AS `men_processo_nao_exig`,
    `mes`.`men_mes_compensacao` AS `men_mes_compensacao`,
    `mes`.`men_vlr_compensacao` AS `men_vlr_compensacao`,
    `pac`.`cnpj` AS `cnpj` 
  FROM
    (
      des_plano AS pla 
      LEFT JOIN `des_mensal` AS `mes` 
        ON (pla.pla_conta = mes.men_conta) 
        
      LEFT JOIN `des_pacs` AS `pac` 
        ON (
          `mes`.`men_insc_muni` = `pac`.`insc_muni`
        )
    ) 
      {{WHERE}} 

    GROUP BY `mes`.`men_mesano`,
  `pac`.`insc_muni`,
    `mes`.`men_conta`,
    `mes`.`men_aliquota`

请注意,查询条件中存在一个名为 {{WHERE}} 的占位符。这个占位符是TQuery的标准占位符,其目的是定义WHERE条件的插入位置。

以下是PHP代码示例

TTransaction::open('ERP');

//Definindo os critérios de busca
$criteria = new TCriteria();
$criteria->add(new TFilter('men_mesano', 'LIKE', "%" . date('Y')));

// instanciando o objeto TQuery.
$sql = new TQuery("QryRelatorio.sql");
//Definindo o local onde os arquivos '.sql' serão encontrados.
$sql->setBasePathQuerys("app/querys/");
//Executando a query e carregando os objetos
$rows = $sql->load($criteria);
//Imprimindo na tela os resultados da consulta.
print_r($rows);

请注意,TQuery的行为与TRepository相似

还可以通过自定义占位符传递查询参数。这在我们需要向TQuery发送SQL代码片段时非常有用。

请看以下示例

SELECT
    '12/{{mes_ano}}' AS men_mesano,
    '{{men_insc_muni}}' AS men_insc_muni,
    pla_conta AS men_conta,
    pla.pla_bacen AS pla_bacen,
    pla.cod_trib_desif AS cod_trib_desif,
    0 AS sald_inic,
    0 AS men_cred_mes,
    0 AS men_deb_mes,
    0 AS men_tributavel,
    0 AS men_deducao,
    0 AS base_calc,
    0 AS valr_issqn_retd,
    0 AS men_desc_dedu,
    aliq.`alq_taxa` AS men_aliquota,
    0 AS men_incentivo,
    0 AS men_desc_incen,
    0 AS men_motivo_nao_exig,
    0 AS men_processo_nao_exig,
    0 AS men_mes_compensacao,
    0 AS men_vlr_compensacao,
    '{{cnpj}}' AS cnpj
  FROM
    des_plano AS pla
    LEFT JOIN des_aliquota AS aliq ON aliq.`cid_cod` = (SELECT cid_cod FROM des_coop WHERE coo_cnpj = '{{cnpj}}') AND aliq.`cod_desif` = pla.`cod_trib_desif`
  WHERE pla_conta IN
    (SELECT
      men_conta
    FROM
      des_mensal as mct
    WHERE (
      CAST(CONCAT(SUBSTR(mct.men_mesano, 4,4),SUBSTR(mct.men_mesano, 1,2))AS UNSIGNED INTEGER) 
      between 
      CAST(CONCAT(SUBSTR('01/{{mes_ano}}', 4,4),SUBSTR('01/{{mes_ano}}', 1,2))AS UNSIGNED INTEGER)
      and CAST(CONCAT(SUBSTR('12/{{mes_ano}}', 4,4),SUBSTR('12/{{mes_ano}}', 1,2))AS UNSIGNED INTEGER)
      )  and mct.poa_cod = '{{poa_cod}}')
    AND pla_conta LIKE '7%'
    and pla.pla_grau = 6
    and pla.pla_arquivo = 1

    GROUP BY `men_mesano`,
    men_insc_muni,
    `men_conta`,
    `men_aliquota` 

请注意,此查询包含多个自定义占位符,如 {{poa_cod}}{{cnpj}}。要向TQuery发送数据,以便将其用于自定义占位符,只需在对象构造函数的第二个参数中发送一个关联数组,其中键名与占位符名称相同。

以下是对先前查询的执行示例

TTransaction::open('ERP');

//Definindo os critérios de busca
$criteria = new TCriteria();
$criteria->add(new TFilter('men_mesano', 'LIKE', "%" . date('Y')));

//Defininto vetor com mnemônicos customizados
$params = [
   "mes_ano"=> $mes_ano,
   "cnpj"=> $PA->cnpj,
   "poa_cod"=> $PA->poa_cod,
   "men_insc_muni"=> $PA->insc_muni,
];

// instanciando o objeto TQuery informando os parâmtros q serão utilizados.
$sql = new TQuery("QryRelatorio.sql", $params);
//Definindo o local onde os arquivos '.sql' serão encontrados.
$sql->setBasePathQuerys("app/querys/");
//Executando a query e carregando os objetos
$rows = $sql->load($criteria);
//Imprimindo na tela os resultados da consulta.
print_r($rows);

还可以通过 setParams 方法设置占位符的值,该方法接收一个包含值的数组作为参数。以下是代码示例

$sql->setParams($params);

注意

请勿在包含用户输入的屏幕中使用TQuery,用于数据列表,因为该类没有SQL注入保护,因为存在将代码片段发送到SQL指令中的可能性。

SQL注入保护仅在 load 方法中起作用,该方法接收一个TCriteria,它已经具有这种保护。

因此,在实现TQuery时请谨慎,以避免在系统中引入安全漏洞。

TQuery更适合内部流程,不受用户干扰。