Ir para conteúdo
Fórum Script Brasil

Frank K Hosaka

Membros
  • Total de itens

    1.678
  • Registro em

  • Última visita

Tudo que Frank K Hosaka postou

  1. Desde 1990 é que eu sonho em fazer um programa de orçamento no computador. Já se passaram vários anos, e até hoje eu não consegui. Hoje, o copilot.microsoft.com me ensinou um pouco de matemática e a função do PHP ceil (pegar o inteiro mais alto a partir de um valor em estudo), a equação dele é fantástica! No Basil, temos moeda de R$ 0,10, R$ 0,25, R$ 0,50 e R$ 1,00, não sei como o Haddad consegue passar essas moedas para o povo, uma vez que as agências presenciais são cada vez mais raras, e as que existem se recusam a oferecer trocados para os clientes. Para calcular o preço de venda, eu pensei em usar a função php round($preço,1), onde preço é igual a $custo * 1,1. O valor final da venda se ajusta às moedas disponíveis no Brasil. Por exemplo, limão kg custo 7,99, preço de venda 8,80. O problema é quando o cliente quer apenas 10 gramas do limão, isso dá 0,01 x 8,80 = 0,088 - onde arranjar o troco analógico para isso? Muito mais simples se a lei obrigasse a todos usarem o cartão de débito ou crédito. Pedi para o Copilot ajustar o preço de venda de acordo com a quantidade de tal maneira que o valor final da venda fosse múltiplo de R$ 0,10. Olha só que código bacana: <?php $pdo=new PDO("mysql:host=localhost;dbname=teste","root",""); $prod=$pdo->query("select * from tbprod where prod like '%limao%'") ->fetchAll(PDO::FETCH_OBJ)[0]; // 1 kg limão R$ 7,99 $preço = $prod->custo * 1.1; // 8.789 $preço = round($preço,1); // 8.80 $qt = 0.01; $preçoAjustado=ceil($preço*$qt/0.1)*0.1/$qt; // preçoAjustado = 10.00 echo "<br>$qt x $preçoAjustado = ". $qt * $preçoAjustado; // 0.10 // $qt = 1; $preçoAjustado=ceil($preço*$qt/0.1)*0.1/$qt; // preçoAjustado = 8.80 echo "<br>$qt x $preçoAjustado = ". $qt * $preçoAjustado; // 8.80 // $qt = 0.1; $preçoAjustado=ceil($preço*$qt/0.1)*0.1/$qt; // preçoAjustado = 9.00 echo "<br>$qt x $preçoAjustado = ". $qt * $preçoAjustado; // 0.90 // a função PHP ceil pega o inteiro mais alto do valor em estudo O problema é o Código de Defesa do Consumidor que me obriga a colocar o preço do quilo do limão na frente do balcão. O cliente pode tirar a foto do balcão e mostrar para o delegado o cupom que cobra o preço diferente e mandar eu para a cadeia. Agora eu entendo porque ninguém vende limão no Brasil, e tem um monte de gente querendo ser vereador, prefeito, deputado, senador e até presidente do Brasil.
  2. Eu criei uma session( ) com a chave vetor, mas depois da escolha do usuário, essa chave simplesmente desapareceu. Esse foi um erro bem difícil de achar. O código original era esse: if (count($aux) > 1) { session(['vetor'=> [$codforn, $dia, $qt, $codp, $total, $atual, $lcto]]); foreach ($aux as $x) { echo "<a href=estoqueIncluir?codprod=$x->codprod>$x->codprod $x->prod</a><br>"; } echo "existe mais de um produto com codforn $codforn, escolha um."; exit; } Na hora que o código foi direcionado para a função incluir, a chave vetor simplesmente desapareceu da session( ). Eu fiz uma bateria de teste, e o erro estava na última instrução. Usei o comando exit; Eu nunca tive problema com esse comando, só hoje é que deu esse bode. Para corrigir, eu fiz assim: return "existe mais de um produto com codforn $codforn, escolha um."; O return faz a mesma coisa que o exit, mas hoje eu aprendi que ele não detona o session( ) do Laravel.
  3. A melhor forma de evitar erro de digitação no <input> é usando o <input type=number>, mas eu queria usar o <input> para fazer cálculo, tipo 2,15+0,17, principalmente no Laravel. Com a ajuda do Copilot, cheguei no código a seguir. Note que sempre uso o arquivo index.php, isso é para agilizar o teste. No código a seguir o nome do arquivo é importante porque uso o nome do arquivo para voltar nele mesmo. arquivo index.php <?php if(isset($_GET['numero'])) { echo "resultado= ".$_GET['numero']."<p>"; echo "<input type=submit value='Novo Teste' onclick=location.replace('index.php')>"; exit; } ?> <script> function modificar() { event.preventDefault() numero.value=numero.value.replace(/,/g,'.') if(/^[0-9+\-*/().\s]+$/.test(numero.value)) { numero.value=eval(numero.value) myForm.submit() } else { numero.value="Erro de digitação!" } } </script> <form id=myForm onsubmit=modificar(numero.value)> <input id=numero name=numero autofocus> <p> <input type=submit> </form>
  4. Fazer orçamento na tela é mais ou menos difícil, botar no papel é bem mais complicado. O Eloquent é engenhoso, ele consegue ajuntar as tabelas através de relações definidos no Model. Para pegar essas informações, aí eu tive que improvisar: arquivo app > Models > tbpedido.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Carbon\Carbon; class tbpedido extends Model { use HasFactory; public $timestamps=false; protected $table="tbpedido"; protected $fillable=['ped','dia','vendido']; protected $primaryKey="ped"; function hist() { return $this->hasMany(tbhistped::class, 'ped'); } } arquivo app > Models > tbhistped.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class tbhistped extends Model { use HasFactory; protected $table="tbhistped"; protected $fillable=['ped','codprod','unitario','subtotal','qt']; const UPDATED_AT=null; const CREATED_AT=null; function produtos() { return $this->belongsTo(tbprod::class, 'codprod'); } } arquivo app > Models > tbprod.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class tbprod extends Model { use HasFactory; protected $table="tbprod"; const UPDATED_AT=null; const CREATED_AT=null; protected $fillable=['prod','custo','codforn','marg','loc','emb','un','cf','codbar','venda']; protected $primaryKey="codprod"; } arquivo app > Http > Controllers > Controlid.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\tbpedido; class Controlid { function pedido(Request $request) { $itens=tbpedido::with('hist.produtos')->where('ped',$request->pedido)->get(); $num_rows=count($itens); if($num_rows==0) { return " <script> if(confirm('Não há nada para imprimir')) { location.replace('?Orcamento.inicio.<?=$ped?>') } </script>"; } return view('controlidView',['itens'=>$itens,'ped'=>$request->pedido]); } } arquivo controlidView.blade.php @include('menuView') <table> <tr class=fw-semibold><td colspan=7>Quitanda do Frank <tr class=fw-semibold><td colspan=7>Pedido <?=$ped?> de <?=dbr($itens[0]->dia)?> @foreach($itens as $item) <div style=width:200:word-break:normal> <tr><td colspan=7><?=$item->hist[0]->produtos->prod?></div> <tr><td class=text-end><?=$item->hist[0]->qt?> <td class=text-end><?=$item->hist[0]->produtos->un?> <td>x<td class=text-end><?=dec($item->hist[0]->unitario)?> <td>=<td class=text-end><?=dec($item->hist[0]->subtotal)?> @endforeach <tr class=fw-semibold><td>Total<td><td><td><td><td class=text-end><?=dec($itens[0]->total)?> <tr class=h-2><td>--- </table> <script> cabecalho.style.display='none' window.print() window.onafterprint=function() { location.replace("orcamentoInicio?ped=<?=$ped?>") } </script>
  5. Hoje eu perdi um tempo danado para testar o código, esqueci de ativar o Tailwinds no terminal do VS Code: npx tailwindcss -i input.css -o output.css --watch Outro problema bem sério é que o Copilot às vezes usa o CSS puro e outras vezes o CSS da Tailwinds. Mesmo assim, eu consegui fazer um modal baseado num arquivo fora do arquivo principal. Mas estou contente com o Copilot, ele me ensinou como mandar uma variável para o modal funcionar. Tive que mudar a classe e outros dois arquivos: arquivo balancete.php <?php class Balancete { function apuracaoSelecionada() { $_SESSION['dia']=$_POST['ano']."-".$_POST['mes']."-01"; return header('location:?Balancete.inicio'); } function inicio($paginaAtual=null) { $maiorAno=(new Conn)->select("max(year(dia)) as maior from tbdiario")[0]->maior; $menorAno=(new Conn)->select("min(year(dia)) as menor from tbdiario")[0]->menor; $anos=[]; for($i=$maiorAno;$i>=$menorAno;$i--) { $anos[]=$i; } $dia = isset($_SESSION['dia']) ? $_SESSION['dia'] : date('Y-m-d'); $vetor=apuracao($dia); $primeiroDia=$vetor->primeiroDia; $ultimoDia=$vetor->ultimoDia; $mesExtenso=$vetor->mesExtenso; $matriz=[]; $registros=(new Conn)->select("count(*) as total from tbconta")[0]->total; $registrosPorPagina=15; $paginaAtual = ($paginaAtual) ? $paginaAtual : 1; $indicador = ($paginaAtual - 1) * $registrosPorPagina; $contas=(new Conn)->select("* from tbconta limit $indicador, $registrosPorPagina"); foreach($contas as $conta) { $debitos=(new Conn)->select("sum(valor) as soma from tbdiario where contad=$conta->conta and dia < '$primeiroDia'")[0]->soma; $creditos=(new Conn)->select("sum(valor) as soma from tbdiario where contac=$conta->conta and dia < '$primeiroDia'")[0]->soma; $inicio=round($debitos-$creditos,2); $debito=(new Conn)->select("sum(valor) as soma from tbdiario where contad=$conta->conta and dia between '$primeiroDia' and '$ultimoDia'")[0]->soma; $credito=(new Conn)->select("sum(valor) as soma from tbdiario where contac=$conta->conta and dia between '$primeiroDia' and '$ultimoDia'")[0]->soma; $saldo=$inicio+$debito-$credito; $matriz[]=['conta'=>$conta->conta,'descricao'=>$conta->descricao, 'inicio'=>$inicio,'debito'=>$debito,'credito'=>$credito, 'saldo'=>$saldo]; } $jMatriz=json_decode(json_encode($matriz)); return view('balanceteView',['jMatriz'=>$jMatriz,'paginaAtual'=>$paginaAtual, 'mesExtenso'=>$mesExtenso,'anos'=>$anos]); } } arquivo balanceteApuracao.php <?php if(isset($_GET['anos'])){$anos=json_decode($_GET['anos']);} ?> <div class="fixed w-full max-w-[500px] mx-auto sm:w-[500px] text-center mb-4"> <div>Escolha o ano</div> <form method="post" action="?Balancete.apuracaoSelecionada"> <div> <select name="ano" class="bg-blue-600 shadow appearance-none border rounded py-2 px-3 text-white leading-tight focus:outline-none focus:shadow-outline"> <?php foreach($anos as $ano): ?> <option><?=$ano?></option> <?php endforeach; ?> </select> </div> <div class=mt-4>Escolha o mês</div> <div class="grid grid-cols-6 gap-1 max-w-md mx-auto mt-4"> <?php for($i = 1; $i <= 12; $i++): $j = sprintf("%02d", $i); ?> <input type="submit" name="mes" value="<?=$j?>" class="bg-blue-500 text-white py-2 px-4 rounded"> <?php endfor; ?> </div> </form> </div> arquivo balanceteView.php <?php include('menuView.php'); ?> <style> .grid-container { display: grid; grid-template-columns: 260px 150px 150px 150px 125px; /* Colunas com largura fixa */ width: 835px; /* Ajustando explicitamente o tamanho do grid */ margin: 0 auto; /* Centralizando */ } @media (max-width: 768px) { .grid-container { grid-template-columns: 200px 125px; /* Ajuste para 2 colunas */ width: 100%; /* Largura cheia para mobile */ } .grid-container > :nth-child(2), .grid-container > :nth-child(3), .grid-container > :nth-child(4) { display: none; } .truncate { max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } </style> <script> function abrirModal() { modal.classList.toggle('hidden'); var anos=<?=json_encode($anos)?>; var xhr = new XMLHttpRequest(); var queryString = "?anos=" + encodeURIComponent(JSON.stringify(anos)); xhr.open('GET', 'balanceteApuracao.php' + queryString, true); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { document.getElementById('modal').innerHTML = xhr.responseText; } }; xhr.send(); } </script> <div id="modal" class="hidden absolute mt-[40px] left-[510px] bg-white bg-opacity-100 w-[500px] h-60 border"> </div> <div class="w-full max-w-[500px] mx-auto sm:w-[500px] text-center mb-4"> <button class="text-blue-500 hover:text-blue-700" onclick=abrirModal()> Balancete de <?=$mesExtenso?></button></div> <div class="bg-gray-100 flex flex-col items-center justify-center w-full mx-auto"> <div class="container mx-auto"> <div class="grid-container bg-gray-800 text-white"> <div class="py-0 text-center truncate">Conta</div> <div class="py-0 text-center">Início</div> <div class="py-0 text-center">Débito</div> <div class="py-0 text-center">Crédito</div> <div class="py-0 text-center">Saldo</div> </div> <?php foreach($jMatriz as $conta): ?> <div class="grid-container bg-white"> <div class="border px-4 py-0 text-left truncate"><?=$conta->conta?> <?=$conta->descricao?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->inicio)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->debito)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->credito)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->saldo)?></div> </div> <?php endforeach; $paginaAnterior=$paginaAtual-1; $paginaAtual++; ?> <div class="flex justify-between w-full max-w-[835px] mt-4 mx-auto"> <a href="?Balancete.inicio.<?=$paginaAnterior?>" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Anterior</a> <a href="?Balancete.inicio.<?=$paginaAtual?>" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Próximo</a> </div> </div> </div>
  6. Ontem, o Copilot mostrou para mim que é possível exibir todas as opções do <select></select> através da propriedade size, mas eu fiquei preocupado com o tamanho da tela do celular, então decidi usar 12 <input>. Eu não tive coragem de copiar todos os 12 <input> do Copilot, eu só copiei um <input> e pedi para o PHP criar os outros <input>. Mas ainda sobrou um <select> e pedi para o Copilot azular para mim, mas ele não azulou, ele criou uma caixa de texto azulada como título e a seguir desenhou o <select>. Eu copiei o CSS Tailwinds da caixa de texto e apliquei no <select>. Veja como ficou: arquivo balanceteApuracao.php <?php include('menuView.php'); ?> <div class="w-full max-w-[500px] mx-auto sm:w-[500px] text-center mb-4"> <div>Escolha o ano</div> <form method="post" action="?Balancete.apuracaoSelecionada"> <div> <select name="ano" class="bg-blue-600 shadow appearance-none border rounded py-2 px-3 text-white leading-tight focus:outline-none focus:shadow-outline"> <?php foreach($anos as $ano): ?> <option><?=$ano?></option> <?php endforeach; ?> </select> </div> <div class=mt-4>Escolha o mês</div> <div class="grid grid-cols-6 gap-1 max-w-md mx-auto mt-4"> <?php for($i = 1; $i <= 12; $i++): $j = sprintf("%02d", $i); ?> <input type="submit" name="mes" value="<?=$j?>" class="bg-blue-500 text-white py-2 px-4 rounded"> <?php endfor; ?> </div> </form> </div>
  7. Foi em 1999 é que consegui o meu primeiro computador de bolso, o Palm. O meu sonho era colocar o banco de dados nele, mas o máximo que eu consegui foi colocar uma cópia do banco de dados só para consulta, através do ListToGo e mais tarde o Handbase. Em 2020, eu consegui conectar o Android ao Windows, graças ao WampServe, o PHP, o MySQL e o VS Code. O problema é que a tela do celular é bem pequena se comparado ao notebook, logo não dá para mostrar tudo o que aparece no notebook no celular. O balancete, por exemplo, tem cinco colunas. O celular só tem espaço para uma coluna, e mesmo assim não dá para mostrar tudo. Para resolver isso, só o HTML é que pode resolver, e essa é uma linguagem que eu não sei mexer. Em outubro de 2024, comecei a trabalhar com o Copilot, a Gemini recusou várias vezes de me ajudar, acho que ela não gosta de mim. O código a seguir é praticamente 100% do Copilot, copiei e colei e fiz um pequeno ajuste na posição do rótulo "conta": arquivo balanceteView.php <?php include('menuView.php'); ?> <style> .grid-container { display: grid; grid-template-columns: 260px 150px 150px 150px 125px; /* Colunas com largura fixa */ width: 835px; /* Ajustando explicitamente o tamanho do grid */ margin: 0 auto; /* Centralizando */ } @media (max-width: 768px) { .grid-container { grid-template-columns: 200px 125px; /* Ajuste para 2 colunas */ width: 100%; /* Largura cheia para mobile */ } .grid-container > :nth-child(2), .grid-container > :nth-child(3), .grid-container > :nth-child(4) { display: none; } .truncate { max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } </style> <div class="w-full max-w-[500px] mx-auto sm:w-[500px] text-center bg-gray-400 mb-4">Balancete</div> <div class="bg-gray-100 flex flex-col items-center justify-center w-full mx-auto"> <div class="container mx-auto"> <div class="grid-container bg-gray-800 text-white"> <div class="py-0 text-center truncate">Conta</div> <div class="py-0 text-center">Início</div> <div class="py-0 text-center">Débito</div> <div class="py-0 text-center">Crédito</div> <div class="py-0 text-center">Saldo</div> </div> <?php foreach($jMatriz as $conta): ?> <div class="grid-container bg-white"> <div class="border px-4 py-0 text-left truncate"><?=$conta->conta?> <?=$conta->descricao?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->inicio)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->debito)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->credito)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->saldo)?></div> </div> <?php endforeach; $paginaAnterior=$paginaAtual-1; $paginaAtual++; ?> <div class="flex justify-between w-full max-w-[835px] mt-4 mx-auto"> <a href="?Balancete.inicio.<?=$paginaAnterior?>" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Anterior</a> <a href="?Balancete.inicio.<?=$paginaAtual?>" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Próximo</a> </div> </div> </div>
  8. O código a seguir consegui com o Copilot. Eu não consegui deixar azul o <div> que contém a palavra balancete. O Copilot me aconselhou a limpar o histórico do navegador, consegui definir a cor do fundo mas não consegui centralizar a palavra balancete no <div>. O Copilot acredita que existe um erro estrutural no código. Eu suponho que defini o <div> principal como 550px, mas a soma das outras colunas dá bem mais do que isso, e assim o Tailwinds não consegue executar o serviço como esperado. Mas a verdade é que eu nem sei o que é a estrutura de um CSS. O mais bacana mesmo é como o Copilot define o tamanho de cada <div> usando o recurso do CSS dentro do marcador <style>, pela primeira vez em cinco anos, consigo definir um tamanho para a primeira coluna e um tamanho para outras quatro. *** depois que publiquei essa mensagem é que eu vi um grave erro de digitação, escrevi "continer", quando o correto é "container". Será esse o famoso erro estrutural que o Copilot comentou? *** balanceteView.php <?php include('menuView.php'); ?> <style> .grid-container {display:grid;grid-template-columns:260px repeat(4,140px)}</style> <div class="bg-gray-100 flex items-center justify-center w-[550px] mx-auto"> <div class="continer mx-auto"> <div class="grid-container bg-blue-700 text-center text-white">Balancete</div> <div class="grid-container bg-gray-800 text-white"> <div class="py-0 text-center">Conta</div> <div class="py-0 text-center">Início</div> <div class="py-0 text-center">Débito</div> <div class="py-0 text-center">Crédito</div> <div class="py-0 text-center">Saldo</div> </div> <?php foreach($jMatriz as $conta): ?> <div class="grid-container bg-white"> <div class="border px-4 py-0"><?=$conta->conta?> <?=$conta->descricao?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->inicio)?></div> <div class="border px-4 py-0 text-right"><?=dec($conta->debito)?></div> <div class="border px-4 py-0 text-center">crédito</div> <div class="border px-4 py-0 text-center">saldo</div> </div> <?php endforeach; $paginaAnterior=$paginaAtual-1; $paginaAtual++; ?> </table> <div class=py-2></div> <a href=?Balancete.inicio.<?=$paginaAnterior?> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Anterior</a> <a href=?Balancete.inicio.<?=$paginaAtual?> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Próximo</a> </div> </div> </div>
  9. A Gemini ofereceu vários exemplos que não deram certo. A culpa não é dela. Eu é que não consegui ser objetivo na consulta. Na última tentativa eu escrevi assim:tenho 3 itens no nav, o do meio queria que fosse um dropdown, tudo com o tailwinds E só assim consegui montar o código seguinte: arquivo menuView.php <link rel=stylesheet href=output.css> <nav class="bg-gray-800 w-[500px] mx-auto"> <div class="container mx-auto flex justify-between px-4 py-2 text-white"> <div>Tailwinds</div> <div class="relative" onclick="menuDiv.classList.toggle('hidden')">Menu <div id=menuDiv class="hidden absolute mt-2 bg-white rounded-md shadow-lg"> <a href="?Balancete.inicio" class="block px-4 py-2 text-blue-700 hover:bg-blue-100"> Balancete</a> </div> </div> <div class="relative" onclick="loginDiv.classList.toggle('hidden')"><?=$_SESSION['nome']?> <div id=loginDiv class="hidden absolute mt-2 bg-white rounded-md shadow-lg"> <a href="?Login.sair" class="block px-4 py-2 text-blue-700 hover:bg-blue-100"> Sair</a> </div> </div> </div> </nav>
  10. Eu perdi uma tabela inteira de dados. Eu fiquei indignado. Depois de quatro horas de pesquisa, descobri que o mysqli não é a mesma coisa que PDO! Olha só: <?php // mysql.teste.tbdiario(contad varchar)('410') $mysqli=new mysqli("localhost","root","","teste"); $contad=$mysqli->query("select * from tbdiario where docto=1")->fetch_assoc()['contad']; var_dump($contad); // string '410' $pdo=new PDO("mysql:host=localhost;dbname=teste","root",""); $contad=$pdo->query("select * from tbdiario where docto=1")->fetch(PDO::FETCH_OBJ)->contad; var_dump($contad); // int 410
  11. Eu defini o registro indesejável como todo registro que está na tabela conta corrente que não que tem a conta '130' ou '211' correspondente na tabela diário. Botar isso na sintaxe MySQL é um pesadelo. Mas a sintaxe PHP é bem mais fácil: <?php $pendencia=$mysqli->query("select * from tbcontacorrente join tbdiario on tbdiario.docto = tbcontacorrente.docto where pgto = 0") ->fetch_all(MYSQLI_ASSOC); foreach($pendencia as $p) { $eliminar=($p['contad']!=='130')+($p['contad']!=='211')+($p['contac']!=='130')+($p['contac']!=='211'); if($eliminar==4) { echo "<br>eliminar docto ". $p['docto']; } }
  12. Valeu! Eu ainda estou bem longe do ambiente servidor-cliente, eu uso o famoso método científico da tentativa e erro. Aqui no notebook, eu tenho que usar "localhost/meuprojeto" para rodar o projeto. Para rodar no hostinger, eu escrevo meuendereco.com, e ele aparece. Não tenho a menor ideia de como isso funciona, mas que eu acho isso bacana, isso eu acho.
  13. Isso é coisa que eu ainda não tenho solução, mas por enquanto eu faço assim: return echo("Mensagem Enviada"); ou seja, quando o PHP termina de fazer uma tarefa, eu uso o PHP para notificar o usuário. Bem que eu queria usar o JavaScript, mas comigo nunca funcionou. Mas tem hora que o PHP não funciona, tipo header("location:vaParaLa.php"), e aí eu peço ajuda para o JavaScript echo "<script>location.replace('vaParaLa.php')</script>". Eu simplesmente não entendo.
  14. Hahahahaha... eu estava pensando assim: showAlert($sendSuccessMessage, 'success'); exit;
  15. Eu apanho muito com esse negócio de JavaScript versus PHP. A minha intuição me diz para você experimentar o "exit;" na última instrução.
  16. Fase 2: aqui inclui o saldo inicial de cada conta, e também introduzi o Tailwinds no PHP. Usei o tutorial em https://tailwindcss.com/docs/installation - eles presumem que você vai utilizar um subdiretório chamado /src/, mas coloquei tudo no diretório raiz. Os principais arquivos ficaram assim: input.css @tailwind base; @tailwind components; @tailwind utilities; tailwind.config.js /** @type {import('tailwindcss').Config} */ module.exports = { content: ["*.{php,js}"], theme: { extend: {}, }, plugins: [], } Para ativar o servidor do Tailwinds, usei esse comando: npx tailwindcss -i input.css -o output.css --watch E o meu arquivo principal ficou assim: balancete.php <?php $mysqli=new mysqli("localhost","root","","teste"); function dec($value) { return ($value) ? number_format($value,2,',','.') : null; } class Balancete { function inicio() { $rota=explode("_",key($_GET)); $metodo=$rota[0]; $argumento=$rota[1]; return $this->$metodo($argumento); } function balancete($paginaAtual=null) { global $mysqli; $primeiroDia='2024-10-01'; $ultimoDia='2024-10-31'; $matriz=[]; $registros=$mysqli->query("select count(*) as total from tbconta") ->fetch_assoc()['total']; $registrosPorPagina=20; $paginaAtual = ($paginaAtual) ? $paginaAtual : 1; $indicador = ($paginaAtual - 1) * $registrosPorPagina; $contas=json_decode(json_encode( $mysqli->query("select * from tbconta limit $indicador, $registrosPorPagina") ->fetch_all(MYSQLI_ASSOC))); foreach($contas as $conta) { $debitos=$mysqli->query("select sum(valor) as soma from tbdiario where contad=$conta->conta and dia < '$primeiroDia'")->fetch_assoc()['soma']; $creditos=$mysqli->query("select sum(valor) as soma from tbdiario where contac=$conta->conta and dia < '$primeiroDia'")->fetch_assoc()['soma']; $inicio=round($debitos-$creditos,2); $matriz[]=['conta'=>$conta->conta,'descricao'=>$conta->descricao,'inicio'=>$inicio]; } $jMatriz=json_decode(json_encode($matriz)); ?> <link rel="stylesheet" href="output.css"> <div class='w-[500px] mx-auto'> <div class="bg-blue-500 text-white">Balancete</div> <div class="flex"> <div class="w-1/6 p-0 font-bold">Conta</div> <div class="w-1/2 p-0 font-bold">Descrição</div> <div class="w-1/6 p-0 font-bold text-right">Início</div> </div> <?php foreach($jMatriz as $conta): ?> <div class="flex"> <div class="w-1/6 p-0"><?=$conta->conta?></div> <div class="w-1/2 p-0 whitespace-nowrap"><?=$conta->descricao?></div> <div class="w-1/6 p-0 text-right"><?=dec($conta->inicio)?></div> </div> <?php endforeach; $paginaAnterior=$paginaAtual-1; $paginaAtual++; ?> </table> <div class=py-2></div> <a href=?balancete.<?=$paginaAnterior?> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Anterior</a> <a href=?balancete.<?=$paginaAtual?> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded">Próximo</a> </div> <?php } } (new Balancete)->inicio();
  17. Ainda não dominei a ferramenta Livewire do Laravel, mas eu gostei dele. O Livewire me lembra os primeiros anos que comecei a engatinhar no PHP, quando não sabia como separar o PHP do HTML. Apesar de não saber como usar o Livewire, ele me ensinou que o Eloquent tem uma paginação embutida, ou seja, você não precisa do Livewire para paginar. O Eloquent tem o paginador embutido. Esse não é o caso do mysqli, mas a Gemini provou que ele tem um paginador embutido. Ele está depois do comando limit: ** o roteador que foi improvisado no método inicio só serve para esse exemplo em particular ** index.php <?php header('location:balancete.php?balancete_1'); balancete.php <?php $mysqli=new mysqli("localhost","root","","teste"); class Balancete { function inicio() { $rota=explode("_",key($_GET)); $metodo=$rota[0]; $argumento=$rota[1]; return $this->$metodo($argumento); } function balancete($paginaAtual=null) { global $mysqli; $registros=$mysqli->query("select count(*) as total from tbconta") ->fetch_assoc()['total']; $registrosPorPagina=10; $paginaAtual = ($paginaAtual) ? $paginaAtual : 1; $indicador = ($paginaAtual - 1) * $registrosPorPagina; $contas=json_decode(json_encode( $mysqli->query("select * from tbconta limit $indicador, $registrosPorPagina")->fetch_all(MYSQLI_ASSOC))); ?> <table><th>Conta<th>Descricao <?php foreach($contas as $conta): ?> <tr><td><?=$conta->conta?><td><?=$conta->descricao?> <?php endforeach; $paginaAnterior=$paginaAtual-1; $paginaAtual++; ?> </table> <a href=?balancete.<?=$paginaAnterior?>>Anterior</a> <a href=?balancete.<?=$paginaAtual?>>Próximo</a> <?php } } (new Balancete)->inicio();
  18. Frank K Hosaka

    O apóstrofo

    Sem querer, eu digitei um apóstrofo dentro da caixa de consulta, e isso acabou gerando uma mensagem de erro. A Gemini sugeriu mudar o meu código pdo->query( ) para pdo->prepare( ), mas isso não resolveu o problema. Então a Gemini sugeriu usar a função PHP addslashes. Eu não tive mais nenhuma mensagem de erro, mas também não tive nenhum resposta na consulta. Assim, chegou a minha vez de improvisar, eu pedi para o PHP excluir qualquer apóstrofo que encontrar no critério assim: function historico() { $criterio=str_replace("'",'',(str_replace(' ','%',$_POST['hist']))); $hist=(new Conn)->select("* from tbdiario where hist like '%$criterio%'"); return view('diarioHistorico',['hist'=>$hist]); }
  19. Baseado no código do counter, tentei montar o pagination. Recebi dezenas de mensagens de erro, e acabou prevalecendo a minha improvisação. Não tenho a menor ideia como usar o Livewire. Para piorar, eu não consegui utilizar o CSS Tailwinds e nem o CSS convencional. Isso é muito chato: routes > web.php <?php use Illuminate\Support\Facades\Route; Route::middleware(['auth', 'verified'])->group(function () { Route::view('counter','counter'); Route::view('pagination','pagination'); }); resources > views > pagination.blade.php <x-app-layout> <div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8"> <livewire:pagination /> </div> </x-app-layout> resources > views > livewire > pagination.blade.php <?php namespace App\Http\Livewire; use Livewire\Volt\Component; use Livewire\WithPagination; use App\Models\tbprod; new class extends Component { public $page=1; public $last_page; public $paginas; public $produtos; use WithPagination; function mount() { $this->paginas=tbprod::paginate(10,['*'],'page',$this->page)->toArray(); $this->last_page=$this->paginas['last_page']; $this->produtos=$this->paginas['data']; } function increment() { if($this->page<$this->last_page) { $this->page++; return $this->mount(); } } function decrement() { if($this->page>1) { $this->page--; return $this->mount(); } } } ?> <div> @foreach($produtos as $produto) <div> {{$produto['codprod']}} {{$produto['prod']}} </div> @endforeach <p><h1>Página Atual: {{$page}}</h1></p> <button wire:click="increment"> Próximo </button> <button wire:click="decrement"> Anterior </button> </div> Em tempo, esqueci de executar npm run dev.
  20. Eu tentei estudar a paginação no Livewire com a Gemini, mas não consegui. Decidi usar o velho motor de busca do Google, e acabei entrando nesse tutorial: https://livewire.laravel.com/docs/quickstart Ele tenta explicar o que é LiveWire e mostra um código exemplo para mostrar como ele funciona. Só que ele não funcionou. E assim eu desisti do Laravel milhares de vezes, por não conseguir encontrar nenhum tutorial que funcionasse. Mas, nesse ano as coisas são diferentes. Eu consegui executar o tutorial do Chirp com o LiveWire, ele não é fácil de entender; mesmo assim, tentei usar o princípio científico da tentativa e erro e tentei fazer o counter funcionar. E eu consegui! routes > web.php <?php use Illuminate\Support\Facades\Route; Route::middleware(['auth', 'verified'])->group(function () { Route::view('counter','counter'); }); resources > views > counter.blade.php <x-app-layout> <div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8"> <livewire:counter /> </div> </x-app-layout> resources > views > livewire > counter.blade.php <?php use Livewire\Volt\Component; new class extends Component { public $count=1; function increment(){$this->count++;} function decrement(){$this->count--;} } ?> <div> <h1>{{$count}}</h1> <button wire:click="increment">+</button> <button wire:click="decrement">-</button> </div>
  21. Eu ainda tenho muita dificuldade para trabalhar com o marcador <div> e mais ainda com o CSS Tailwinds, mas com a ajuda da Gemini consegui montar a minha tabela à base de <div>, e aos poucos vou ingressando no mundo "blade" do Laravel: resources > views > diario.blade.php <x-app-layout> <div class='w-[500px] mx-auto'> <div class="flex"> <div class="w-1/4"> <form method=post action=diarioDia> @csrf <input type=date name=dia value='{{ $lctos[0]->dia }}' onchange=submit()> </form> </div> </div> <div class="flex"> <div class="w-1/6 p-0 font-bold">Lcto</div> <div class="w-1/6 p-0 font-bold">CtaD</div> <div class="w-1/6 p-0 font-bold">CtaC</div> <div class="w-1/6 p-0 font-bold">Valor</div> <div class="w-1/4 p-0 font-bold">Hist</div> </div> @foreach($lctos as $lcto) <div class="flex"> <div class="w-1/6 p-0">{{ $lcto->lcto }}</div> <div class="w-1/6 p-0">{{ $lcto->contad }}</div> <div class="w-1/6 p-0">{{ $lcto->contac }}</div> <div class="w-1/6 p-0">{{ $lcto->valor }}</div> <div class="w-1/4 p-0 whitespace-nowrap">{{ $lcto->hist }}</div> </div> @endforeach </div> </x-app-layout>
  22. Não é a primeira vez que eu enfrento o erro do sql_mode, quando executo o comando $codp=tbhistprod::groupBy('codp')->get(); Só que eu não lembrava como eu resolvi, eu só sei que não mexi na configuração do MySQL. Pedi ajuda da Gemini, fiz várias tentativas e erros, e acabei entrando no modo desespero. Respirei um pouco, e decidi entrar no terminal do MySQL e tentei montar a consulta: Select codp from tbhistprod group by codp Foi nesse momento que eu percebi o meu erro no Laravel, lá eu pedi implicitamente para pegar todos os campos mas agrupar apenas um campo, e hoje isso não é mais possível. Para corrigir o erro, eu fiz assim no Laravel: $codp=tbhistprod::select('codp')->groupBy('codp')->get();
  23. Hoje estudei um pouco sobre validação, mas não queria usar o navegador, usei o terminal, ao invés de php artisan serve, usei o php artisan tinker. a função é essa daqui: <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class Diario { function teste(Request $request) { $dataValida = $request->validate(['dob' => [ 'required','date', 'before_or_equal:' . now()->subYears(18)->format('Y-m-d')]]); return $dataValida; } } Depois de ativar o php artisan tinker, digitei o seguinte no terminal (new App\Http\Controllers\Diario)->teste(new Illuminate\Http\Request(['dob'=>'2006-09-28'])); Para chegar nessa sintaxe fiz várias consultas com a Gemini, e também um monte de tentativa e erro, mas eu gostei, bem mais prático do que mexer no web.php e ativar o server.
  24. Eu queria consultar um produto pelo seu código, ou pelo código de barra, ou pelo código do fornecedor, além da famosa descrição. A sugestão da Gemini foi de concatenar os campos. A sugestão não deu certo. Usei o terminal do MySQL e descobri que o produto que eu procurava não tinha código de barra ou o código do fornecedor, e isso acabou anulando a função de concatenar. Para evitar esse contratempo, a Gemini sugeriu usar a função coalesce, assim: app > Http > Controllers > Produto.php <?php // ... function filtra(Request $request) { $criterio=str_replace(' ','%',$request->procura); session(['criterio'=>$criterio]); $produtos=tbprod::whereRaw("concat(prod,'',codprod,'',coalesce(codbar,''),'', coalesce(codforn,'')) like '%$criterio%'")->get(); return view('produtoView',['produtos'=>$produtos]); }
  25. Frank K Hosaka

    Pagina Expirar

    Encontrei isso com a Gemini: <?php session_start(); // Verifica se a sessão já existe if (isset($_SESSION['last_activity'])) { // Calcula o tempo de inatividade em segundos $time_elapsed = time() - $_SESSION['last_activity']; // Define o tempo limite em segundos (5 minutos neste caso) $timeout_duration = 300; // Se o tempo de inatividade exceder o limite, destrói a sessão e redireciona if ($time_elapsed >= $timeout_duration) { session_unset(); session_destroy(); header("Location: login.php"); // Redireciona para a página de login } } // Atualiza o timestamp da última atividade $_SESSION['last_activity'] = time(); // Resto do seu código PHP
×
×
  • Criar Novo...