
Frank K Hosaka
Membros-
Total de itens
1.533 -
Registro em
-
Última visita
Tudo que Frank K Hosaka postou
-
<?php // mysql.teste.provas(id,questao) // (1,'Quem descobriu o Brasil?,Pedro,João,Maria,Nenhuma das anteriores'), // (2,'O Brasil tem futuro?,Sim,Não,Talvez') // (3, 'Quanto é 1+1?,1,2,3,4,5') // (4, 'Quanto é o logaritimo de 10 na base 10?,1,2,3,4,5') class Provas { private $Conexao; function __construct() { $this->Conexao=new mysqli("localhost","root","","teste"); } function selecionar($id) { return $this->Conexao->query("select * from provas where id=$id") ->fetch_assoc(); } function imprimir($vetor) { $q=0; foreach($vetor as $v) { $prova=$this->selecionar($v); $vetores=explode(',',$prova['questao']); foreach($vetores as $chave => $vetor) { if($chave==0) { echo "<br>"; $q++; echo $q . ". " . $vetor . "<br>"; } else { echo chr($chave+64) . ". " . $vetor . "<br>"; } } } } } (new Provas)->imprimir([4,3]);
-
6 segundos é o tempo que o PHP gasta para montar um balancete. Eu acho isso bem rápido. O problema é que eu tenho a mesma rotina no Laravel, mas ele gastou 18 segundos. Isso é um absurdo! Fiquei imaginando se o Eloquent é bem mais lento que o msqli ou o PDO. Para fazer auditoria, eu coloquei os seguinte comandos na function balancete( ) <?php function balancete() { $tempo1=microtime(true); // ... $tempo2=microtime(true); var_dump($tempo2-$tempo1);exit; (no Laravel: dd($tempo2-tempo1); ) } Os dois levaram 3 segundos, ou seja, o Eloquent é tão bom quanto o mysqli ou o PDO. Ou seja, o problema estava na renderização, e assim eu encontrei o probema no Laravel: <?php function inicio (Request $request) { $balancete=$this->balancete()->balancete; $apuracao=$this->balancete()->apuracao; $anterior=$this->balancete()->anterior; $receita=$this->balancete()->receita; $despesa=$this->balancete()->despesa; $resultado=$this->balancete()->resultado; $nota=$this->balancete()->nota; return view('balanceteView',['balancete'=>$balancete, 'apuracao'=>$apuracao,'anterior'=>$anterior,'despesa'=>$despesa, 'receita'=>$receita,'resultado'=>$resultado,'nota'=>$nota]); } Esse é um erro bem besta. Aqui eu pedi para o Laravel executar a função balancete( ) sete vezes, quando o correto é apenas uma vez assim: <?php function inicio (Request $request) { $previa=$this->balancete(); $balancete=$previa->balancete; $apuracao=$previa->apuracao; $anterior=$previa->anterior; $receita=$previa->receita; $despesa=$previa->despesa; $resultado=$previa->resultado; $nota=$previa->nota; return view('balanceteView',['balancete'=>$balancete, 'apuracao'=>$apuracao,'anterior'=>$anterior,'despesa'=>$despesa, 'receita'=>$receita,'resultado'=>$resultado,'nota'=>$nota]); } Moral da história: se um programa está lento demais, provavelmente o problema é aquela pecinha que fica na frente do monitor.
-
<?php // mysql.teste.provas(id,questao) // (1,'Quem descobriu o Brasil?,Pedro,João,Maria,Nenhuma das anteriores'), // (2,'O Brasil tem futuro?,Sim,Não,Talvez') class Provas { function listar($id) { $conexao=new mysqli("localhost","root","","teste"); return $conexao->query("select * from provas where id=$id")->fetch_assoc(); } } for($q=1;$q<=2;$q++) { $prova=(new Provas)->listar($q); $vetores=explode(',',$prova['questao']); foreach($vetores as $chave => $vetor) { if($chave==0) { echo "<br>"; echo $q . ". " . $vetor . "<br>"; } else { echo chr($chave+64) . ". " . $vetor . "<br>"; } } }
-
No meu projeto original eu criei duas tabelas, uma resumia a venda por mês e outra por dia. Quando o usuário selecionava uma data, a tabela exibia as vendas por hora daquele dia. O problema é que o usuário precisava rolar a página para ver os detalhes por hora. Ontem eu decidi tirar os detalhes das horas de dentro da tabela por dia, e colocar numa <div> por cima das outras duas tabelas (o blade usa a sintaxe {{ }} e @função, mas eu usei <?php ?>, para compartilhar os mesmos códigos entre o Laravel e o PHP): app > Http > Controllers > Venda.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use App\Models\tbpedido; class Venda { function inicio(Request $request) { $detalhes=[]; if($request->detalhe) { $detalhes=tbpedido::wheredate('horavenda',$request->detalhe) ->orderBy('horavenda','desc')->get(); } if(!session()->has('apuracao')) { session(['apuracao'=>date('Y-m-01')]); } $primeiroDia=apuracao(session('apuracao'))->primeiroDia; $ultimoDia=apuracao(session('apuracao'))->ultimoDia; $grupos=DB::table('tbpedido') ->selectRaw('DATE(horavenda) as ddia, SUM(total) as ttotal') ->whereBetween(DB::raw('DATE(horavenda)'), [$primeiroDia, $ultimoDia]) ->whereNotNull('horavenda') ->groupBy('ddia') ->orderBy('ddia', 'desc') ->get(); $vendaMensal=DB::table('tbpedido') ->selectRaw('DATE_FORMAT(horavenda, "%Y-%m") as mes, SUM(total) as total') ->whereNotNull('horavenda') ->groupBy('mes') ->orderBy('mes', 'desc') ->get(); return view('vendaView',['grupos'=>$grupos, 'vendaMensal'=>$vendaMensal,'detalhes'=>$detalhes,'detalhe'=>$request->detalhe]); } function apuracao(Request $request) { $detalhe=$request->apuracao."-01"; session(['apuracao'=>$detalhe]); return $this->inicio(new Request(['detalhe'=>null])); } } resources > views > vendaView.blade.php @include('menuView') <script> document.title="Relatório Venda" btmenu.innerHTML="Relatório Venda" </script> <?php if(count($detalhes)): ?> <div class="position-absolute top-10 start-50 translate-middle-x bg-dark text-white" onclick="this.style.display='none'"> <table class="table table-striped linha border"> Detalhe por hora <tr class=fw-semibold><td><?=dbr($detalhes[0]->dia)?><td>Pedido<td>Bling<td>Total<td>dinheiro<td>troco<td>cartão<td>pix <?php foreach($detalhes as $grupo): ?> <tr> <td class=text-end><?=date('H:i',strtotime($grupo->horavenda))?> <td class=text-end><?=$grupo->ped?> <td class=text-end><?=$grupo->bling?> <td class=text-end><?=dec($grupo->total)?> <td class=text-end> <?php if(abs($grupo->dinheiro)>0): ?> <?=dec($grupo->dinheiro)?> <?php endif; ?> <td class=text-end> <?php if(abs($grupo->troco)>0): ?> <?=dec($grupo->troco)?> <?php endif; ?> <td class=text-center> <?php if($grupo->cartao==1): ?> x <?php endif; ?> <td class=text-center> <?php if($grupo->pix==1): ?> x <?php endif; ?> <?php endforeach; ?> </table> </div> </div> <?php endif; ?> <table class='table table-striped linha w-25' style=float:left> <tr><td colspan=2>Detalhe por mês <?php foreach($vendaMensal as $venda): ?> <tr><td><a href="vendaApuracao?apuracao=<?=$venda->mes?>"><?=$venda->mes?></a> => R$ <td class='text-danger text-end'> <?=dec($venda->total)?> <?php endforeach; ?> </table> <table class='table table-striped linha w-25' style=float:right> <tr><td colspan=2>Detalhe por dia <tr class=fw-semibold><td>Dia<td class=text-end>Total <?php foreach($grupos as $grupo): ?> <tr> <td><a href="vendaInicio?detalhe=<?=$grupo->ddia?>"> <?=date('d/m/y',strtotime($grupo->ddia))?></a> <td class=text-end><?=dec($grupo->ttotal)?> <?php endforeach;?> </table>
-
Programação PHP SELECT COUNT(*) as total FROM ?
pergunta respondeu ao Super Oferta TOP de Frank K Hosaka em PHP
O print do banco de dados não aparece na sua mensagem, assim improvisei uma nova tabela. Espero que isso ajude: <?php $pdo=new PDO("mysql:host=localhost;dbname=teste","root",""); // mysql.teste.tabela(id,telefone,pagou)(301,"99",0)(302,"99",0)(303,"99",0)(304,"99",0) // (305,"99",1) $stmt=$pdo->query("select * from tabela where pagou"); $pagadores=$stmt->fetchAll(PDO::FETCH_OBJ); ?> Lista dos pagadores: <table><th>id<th>telefone <?php foreach($pagadores as $pagador): ?> <tr><td><?=$pagador->id?><td><?=$pagador->telefone?> <?php endforeach; ?> </table> -
Eu tenho uma rotina no projeto que se chama pendência, que eu consegui montar em PHP em 2020. Aqui em 2024, tentei melhorar o código, mas havia tanta rotina repetida que achei melhor usar a tecnologia da classe. Geralmente, a gente separa o código da classe do código HTML, mas hoje tentei colocar HTML dentro da classe. Ele ainda está em fase de desenvolvimento, mas ele parece funcionar: <?php class pendencia { private $mysqli; function __construct() { $this->mysqli=new mysqli("localhost","root","","teste"); } function dec($value) { return ($value) ? number_format($value,2,',','.') : null; } function incluir($controles,$dados) { foreach($dados as $dado) if(!in_array($dado['docto'],$controles)) { $docto=$dado['docto']; $lcto=$dado['lcto']; $this->mysqli->query("insert into tbcontacorrente (docto,lcto) values ($docto,$lcto)"); } } function inicio() { $recebiveis=$this->mysqli->query("select * from tbdiario where contad=130 and dia>'2023-12-31'") ->fetch_all(MYSQLI_ASSOC); $recebidos=$this->mysqli->query("select * from tbdiario where contac=130 and dia>'2023-12-31'") ->fetch_all(MYSQLI_ASSOC); $pagaveis=$this->mysqli->query("select * from tbdiario where contac=211 and dia>'2023-12-31'") ->fetch_all(MYSQLI_ASSOC); $pagos=$this->mysqli->query("select * from tbdiario where contad=211 and dia>'2023-12-31'") ->fetch_all(MYSQLI_ASSOC); $controles=array_column($this->mysqli->query("select docto from tbcontacorrente") ->fetch_all(MYSQLI_NUM),0); $this->incluir($controles,$recebiveis); $this->incluir($controles,$recebidos); $this->incluir($controles,$pagaveis); $this->incluir($controles,$pagos); $controles=$this->mysqli->query("select * from tbcontacorrente left join tbpessoa on tbpessoa.codp = tbcontacorrente.codp join tbdiario on tbdiario.docto = tbcontacorrente.docto where pgto=0 order by vcto") ->fetch_all(MYSQLI_ASSOC); $totalReceber=0; ?> <style>td {white-space: nowrap} </style> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <table class='table table-striped table-sm m-auto' style=width:500px> <tr class=fw-semibold><td>Vencimento<td>Docto<td>Lcto <td class=text-end>Valor<td>Cliente<td>Histórico <?php foreach($controles as $c): $hist=date('d/m/y',strtotime($c['dia']))." ".$c['hist']; $totalReceber+=$c['valor']; ?> <tr><td><input type=date value='<?=$c['vcto']?>'> <td><?=$c['docto']?><td><?=$c['lcto']?> <td class=text-end><?=$this->dec($c['valor'])?> <td><?=$c['pessoa']?><td><?=$hist?> <?php endforeach; ?> <tr class=fw-semibold><td colspan=3>Total a receber<td colspan=3><?=$this->dec($totalReceber)?> </table> <?php } } (new pendencia)->inicio(); /* mysql CREATE TABLE `tbdiario` ( `docto` mediumint NOT NULL AUTO_INCREMENT, `dia` date DEFAULT NULL, `hist` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `lcto` mediumint DEFAULT NULL, `contad` mediumint DEFAULT NULL, `contac` mediumint DEFAULT NULL, `valor` decimal(13,2) DEFAULT NULL, PRIMARY KEY (`docto`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; insert into tbdiario (dia,hist,lcto,contad,contac,valor) values ('2024-09-23','Magazine Luiza',1,130,304,12.00), ('2024-09-24','Mappin',2,130,304,500.00) CREATE TABLE `tbcontacorrente` ( `docto` mediumint NOT NULL, `vcto` date DEFAULT NULL, `pgto` int DEFAULT '0', `codp` mediumint DEFAULT NULL, `lcto` mediumint DEFAULT NULL, PRIMARY KEY (`docto`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci CREATE TABLE `tbpessoa` ( `codp` int NOT NULL AUTO_INCREMENT, `pessoa` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `cnpj` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `end` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `tel` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `nota` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `updated_at` datetime NOT NULL, `vinculo` tinyint NOT NULL, PRIMARY KEY (`codp`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci */
-
No Hostinger, eu configurei o arquivo .env assim: DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=Diario DB_USERNAME=Root DB_PASSWORD=1234 No meu Notebook à base de Windows, eu configurei assim: DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=diario DB_USERNAME=root DB_PASSWORD= São dois arquivos que têm informações diferentes mas compartilham o mesmo nome. Depois de várias tentativas, acredito que consegui consertar o problema. O arquivo de cima permaneceu com o mesmo nome .env, e o de baixo recebeu o nome de .env.local, e agora a listagem do código laravel é exatamente igual no Hostinger como no notebook. Os dois tem os arquivos .env e .env.local. Para otimizar o código, usei o comando composer dump-autoload. Ambos estão programados para abrir o arquivo .env, mas o do notebook executa também o arquivo .env.local - essa é uma bela mágica que estava procurando desde 2022. Ele funciona!
-
PHP For loop com IDs diferentes
pergunta respondeu ao CarlosWebSB de Frank K Hosaka em Tutoriais & Dicas - PHP
<?php // index.php // mysql.teste.dados_socios (id,usuario)(1,"Frank")(3,"João")(4,"Maria") $conn = new mysqli("localhost","root","","teste"); $usuarios=$conn->query("select * from dados_socios")->fetch_all(MYSQLI_ASSOC); ?> <div style="width:500px;margin:0 auto"> <select> <?php foreach($usuarios as $usuario): ?> <option>ID <?=$usuario['id'] . " " . $usuario['usuario']?> <?php endforeach; ?> </select> </div> sugestões: alterar o nome da tabela de dados_socios para socios, alterar o nome do campo usuario para nomeSocio. -
Usei o endereço do eSocial, usei um certificado digital pj, e acabei recebendo um xml. Pesquisei o Google, e ele respondeu assim: Para enviar um arquivo XML de eventos, é possível seguir os seguintes passos: Acessar o eSocial Ir ao Painel Acessar a aba do evento Clicar em Utilitários Selecionar Exportar XML Escolher se deseja exportar apenas o evento selecionado ou todos do filtro aplicado
-
Eu encontrei auth()->user() no tutorial do Chirp versão Livewire, e isso disparou a mensagem de erro no VS Code. Instalei as extensões PHP Extension Pack bem como o Laravel Extension Pack com a ajuda do CTRL+SHIFT+X no VS Code, bem como tirei todas as credenciais do VS Code no Gerenciador de Credenciais do Windows, mas isso não removeu a mensagem de erro. Para você testar isso, pegue qualquer função index de qualquer controlador, e escreve dd(auth()->user()), o Laravel vai mostrar todos os dados do usuário logado, mesmo que o VS Code afirme que o auth() não tem o método user(), ====================================== Acredito que uma das medidas que eu tomei resolveu o problema, eu só não sei qual. Agora não aparece mais a mensagem de erro no VS Code.
-
A Bling fornece o cadastro de produtos através de arquivos .csv. Eu pego os arquivos, monto uma tabela de produtos da Bling, comparo com a minha tabela no MySQL, em seguida uso o marca texto na última célula (não consegui marcar toda linha) para lembrar o que eu já consertei no cadastro de produtos hospedado na Bling: <?php // bling.php class Bling { function diferenca() { return view('blingDiferenca'); } function diferenca2() { (new Conn)->exec("truncate table tbprodbling"); $arquivos=$_FILES['arquivos']; foreach($arquivos['tmp_name'] as $arquivo) { $dados=file($arquivo); foreach($dados as $linha) { $campos=explode(';',$linha); if(aspas($campos[1])!=="Código") { $codprod=intval(trim(aspas($campos[1]))); $un=aspas($campos[3]); $prod=aspas($campos[2]); $custo=deca(aspas($campos[11])); $codbar=trim(aspas($campos[19])); $cf=deca(aspas($campos[4])); $venda=deca(aspas($campos[6])); (new Conn)->insert("tbprodbling (codprod,un,prod,custo,codbar,cf,venda) values ($codprod,'$un','$prod',$custo,'$codbar','$cf',$venda)"); } } } $produto=(new Conn)->select("* from tbprod where loc <> 'a24'"); $contaProduto=count($produto); $prodBling=(new Conn)->select("* from tbprodbling"); $contaProdBling=count($prodBling); $dif=[]; foreach($produto as $key=>$pr) { $codprod=$pr->codprod; $previa=(new Conn)->select("* from tbprodbling where codprod=$codprod"); if(count($previa)==0) { $dif[$key][]=['Codigo'=>$codprod]; $dif[$key][]=['Incluir'=>$codprod,'Incluir2'=>'Incluir']; } else { $a=json_decode(json_encode($previa))[0]; $un=($pr->un==$a->un) ? 1 : 0; $prod=($pr->prod==$a->prod) ? 1 : 0; $custo=($pr->custo==$a->custo) ? 1 : 0; $codbar=($pr->codbar==$a->codbar) ? 1 : 0; $cf=($pr->cf==$a->cf) ? 1 : 0; $venda=($pr->venda==$a->venda) ? 1 : 0; if($un.$prod.$custo.$codbar.$cf.$venda !== '111111') { $dif[$key][]=['Codigo'=>$pr->codprod,'Codigo2'=>$a->codprod]; if($pr->prod!==$a->prod) { $dif[$key][]=['Descricao'=>$pr->prod,'Descricao2'=>$a->prod]; } if($pr->custo!==$a->custo) { $dif[$key][]=['Custo'=>$pr->custo,'Custo2'=>$a->custo]; } if($pr->codbar!=$a->codbar) { $dif[$key][]=['Codigo de Barra'=>$pr->codbar,'Codigo de Barra2'=>$a->codbar]; } if($pr->cf!==$a->cf) { $dif[$key][]=['NCM'=>$pr->cf,'NCM2'=>$a->cf]; } if($pr->venda!==$a->venda) { $dif[$key][]=['Venda'=>$pr->venda,'Venda2'=>$a->venda]; } if($pr->un!==$a->un) { $dif[$key][]=['Un'=>$pr->un,'Un2'=>$a->un]; } } } } return view('blingDiferenca2',['dif'=>$dif,'contaProduto'=>$contaProduto, 'contaProdBling'=>$contaProdBling]); } } <?php require 'menuView.php'; ?><!-- blingDiferenca.php --> <script>btmenu.innerHTML='Diferença Bling';document.title='Diferença Bling'</script> <form method=post class="w-50 m-auto" enctype="multipart/form-data" action=?Bling.diferenca2> <label for=arquivo>Escolha o arquivo XML</label> <input type=file name=arquivos[] multiple required> <input type=submit> </form> <?php require 'menuView.php'; ?><!-- blingDiferenca2.php --> <script>btmenu.innerHTML='Diferença Bling';document.title='Diferença Bling'</script> <table class='table table-sm'> <tr class=fw-semibold><td>Código<td>Campo<td>MySQL<td>Bling <tr><td><td>Produtos<td><?=$contaProduto?><td><?=$contaProdBling?> <?php foreach($dif as $d): foreach($d as $v):?> <?php if(array_keys($v)[0]=="Codigo"): $codigo=array_values($v)[0]; else: ?> <tr> <td><?=$codigo?> <td><?=array_keys($v)[0]?> <td><?=array_values($v)[0]?> <td onclick="this.style.backgroundColor='lightgray'"><?=array_values($v)[1]?> <?php endif; endforeach; endforeach; ?> </table>
-
O meu php é versão 8.2, ele não suporta o motor mysql, então usei o motor mysqli: <?php // index.php php 8.2 // mysql.terminais.videos(id,link)(1,'video1.mp4'); // aqui coloquei o video1.mp4 no diretório raiz do projeto, // se fosse colocado numa pasta chamada vídeos // a tabela vídeos teria que ser cadastrado assim (1,'videos/video1.mp4') $mysqli=new mysqli("localhost","root","","terminais"); $resultado=$mysqli->query("select * from videos"); while($linha=$resultado->fetch_assoc()) { $exlink = $linha['link']; ?> <iframe width="590" height="335" src="<?=$exlink?>" frameborder="0" allowfullscreen> </iframe> <?php }
-
Já faz algum tempo que eu escrevi que é possível usar o <input> como se fosse uma calculadora, tipo 15+15. Isso não é verdade. Ele só funciona somente se o servidor trabalhar com o mysqli ou com o PDO. Ele não funciona com o Eloquent do Laravel. arquivo index.php <?php // mysql schema terminais orcamento(id,qt)(1,0) if(isset($_POST['qt'])) { $qt=$_POST['qt']; $mysqli=new mysqli("localhost","root","","terminais"); $mysqli->query("update orcamento set qt = $qt where id=1"); $pdo=new PDO("mysql:host=localhost;dbname=terminais","root",""); $stmt=$pdo->prepare("update orcamento set qt = :qt where id=1"); $stmt->bindParam(':qt',$qt); $stmt->execute(); } ?> <form method=post> <input value="15+15" name=qt> <input type=submit> </form> --------------------------- ambiente Laravel: arquivo routes.web.php <?php use App\Http\Controllers\Teste; use Illuminate\Support\Facades\Route; Route::view('/','teste'); Route::post('teste',[Teste::class,'inicio']); arquivo resources.views.teste.blade.php <form method=post action=teste> @csrf <input value="15+15" name=qt> <input type=submit> </form> arquivo app.Models.Orcamento.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Orcamento extends Model { use HasFactory; protected $table='orcamento'; public $timestamps = false; } arquivo app.Http.Controllers.Teste.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Orcamento; class Teste { function inicio(Request $request) { $qt=$request->qt; Orcamento::where('id',1)->update(['qt'=>$qt]); // resultado: SQLSTATE[01000]: Warning: 1265 Data truncated // for column 'qt' at row 1 (Connection: mysql, SQL: update `orcamento` // set `qt` = 15+15 where `id` = 1) } }
-
Com a ajuda da Gemini, consegui o seguinte: resources.views.layouts.navigation.blade.php <style> .nav-link.active {color:#333;font-weight:bold} </style> <ul class="nav nav-tabs mt-2"> <li class='nav-item'> <x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')" class='nav-link active' style=margin-left:120px> Dashboard </x-nav-link> <li class='nav-item'> <x-nav-link :href="route('chirps.index')" :active="request()->routeIs('chirps.index')" class='nav-link' style=margin-left:120px> Chirps </x-nav-link> <li class='nav-item' style=margin-left:120px> <div class=dropdown> <button class="btn btn-sm btn-outline-secondary d-inline-flex align-items-center dropdown-toggle" data-bs-toggle=dropdown> {{ Auth::user()->name }} </button> <div class=dropdown-menu> <x-dropdown-link :href="route('profile.edit')"> Profile </x-dropdown-link> <form method="POST" action="{{ route('logout') }}"> @csrf <x-dropdown-link :href="route('logout')" onclick="event.preventDefault();this.closest('form').submit();"> Log Out </x-dropdown-link> </form> </div> </div> </ul> <script> document.addEventListener('DOMContentLoaded', function() { const navLinks = document.querySelectorAll('.nav-link'); const selectedOption = localStorage.getItem('selectedOption'); // Aplica a classe 'active' ao elemento selecionado anteriormente navLinks.forEach(link => { if (link.textContent === selectedOption) { link.classList.add('active'); } else {link.classList.remove('active')} }); navLinks.forEach(link => { link.addEventListener('click', function() { navLinks.forEach(link => link.classList.remove('active')); this.classList.add('active'); localStorage.setItem('selectedOption', this.textContent); }); }); }); </script>
-
Estou estudando o projeto Chirp do Laravel, mas eu desativei o Tailwinds e ativei o Bootstrap. O resultado é um completo desastre. As imagens do tutorial são bem diferentes do que eu consegui com a minha improvisação. Mas o meu maior problema é o arquivo <svg>, ele fica enorme, tornando o programa inoperante. Hoje a Gemini me ensinou a controlar o tamanho do <svg> assim <svg width=100 height=100>. Agora pedir para ela traduzir o Tailwinds em Bootstrap é pura perda de tempo, mas em compensação a brutal diferença visual entre os dois CSS é motivo suficiente para tirar o chapéu para o Tailwinds. O Tailwinds é capaz de mudar a cor da fonte de um texto, mais escuro para a opção que você escolher na barra de navegação, e menos escuro para as outras opções, e ele ainda é capaz de desenhar uma linha abaixo da opção selecionada. Isso é muito bacana, não sei se vou conseguir imitar o mesmo comportamento com o Bootstrap, por enquanto eu me contento com a posição dos elementos, é o máximo que eu consigo fazer. resources.views.chirps.index.blade.php <x-app-layout> <div class="container mt-2 bg-light"> <form method="POST" action="{{ route('chirps.index') }}"> @csrf <div class=row> <div class=col-md-12> <textarea name="message" placeholder="What's on your mind?" cols=50 class="mt-4">{{ old('message') }}</textarea> <x-input-error :messages="$errors->get('message')" class="" /> </div> <div class=col-md-auto> <x-primary-button class="btn btn-primary">Chirp</x-primary-button> </div> </div> </form> <div class=""> @foreach ($chirps as $chirp) <svg width=30 height=30 xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /> </svg> <span class="">{{ $chirp->user->name }}</span> <small class="">{{ $chirp->created_at->format('j M Y, g:i a') }}</small> <p class="">{{ $chirp->message }}</p> @endforeach </div> </div> </x-app-layout>
-
Consegui fazer um upload de um arquivo com mais de 2 mb no PHP
uma questão postou Frank K Hosaka PHP
Eu usei esse código: <?php if(isset($_FILES)) { var_dump($_FILES); } ?> <form method=post enctype="multipart/form-data"> <label for="arquivo">Selecione um arquivo:</label> <input type="file" id="arquivo" name="meuArquivo"> <input type=submit> </form> resultado: C:\wamp64\www\Astudy\index.php:4: array (size=1) 'meuArquivo' => array (size=6) 'name' => string 'xml_nfce_1725380458.zip' (length=23) 'full_path' => string 'xml_nfce_1725380458.zip' (length=23) 'type' => string 'application/x-zip-compressed' (length=28) 'tmp_name' => string 'C:\wamp64\tmp\php5066.tmp' (length=25) 'error' => int 0 'size' => int 2559750 Faz muito tempo que o meu zipArchive não funciona, sempre recebi a mensagem de que o arquivo zipado tinha 'error' => int 1, mas isso me deixou grilado: por que o PHP não consegue abrir o arquivo zipado, mas o Windows consegue? Consultando a Gemini, ela informou que existem vários motivos. O primeiro da lista é a configuração do PHP, ela pediu para ver o arquivo php.ini e verificar upload_max_filesize. Ao invés de procurar o arquivo, eu fui no ícone do WampServe, e lá encontrei a mesma informação em PHP > PHP Settings, e o meu estava configurado para 2M. Alterei para 4M. Agora sim eu vou poder trabalhar com o ZipArchive. -
O mês de agosto terminou e eu pedi para a Bling todas as notas que o meu irmão emitiu. A Bling disse que foram emitidas 635 arquivos. Depois de descompactar o arquivo da Bling, o Windows disse que ele encontrou 637 arquivos. E finalmente o scandir do PHP disse que encontrou 639 arquivos. Esse desencontro de informações é um problema sério e vem desde o tempo de Moisés, onde o Arquiteto diz isso e a criatura entende aquilo. Isso não podia ser diferente com a Bling, o Windows e o PHP, todos eles são imagem e semelhança de nossos desencontros. Para começar a apuração, eu pedi para o PHP listar todas as notas que ele encontrar na pasta. Tem duas notas que ele não conseguiu listar. Esses arquivos terminam com a extensão can.xml ao invés de nfe.xml, e assim eu aprendi que cancelar uma nota significa CRIAR um novo arquivo e não simplesmente ACABAR com o arquivo original. Não dá para ver uma nota cancelada pelo Windows, mas dá para ver com o PHP: <?php // index.php $path="C:/Users/Frank/Downloads/xml_nfce_1725380458"; $arquivos=scandir($path); foreach($arquivos as $arquivo): echo "<table>"; if($arquivo!=="." && $arquivo!==".."): $xml=simplexml_load_file($path."/".$arquivo); if($xml->NFe->infNFe): echo "<tr><td>".$xml->NFe->infNFe->ide->nNF."</tr>"; else: var_dump($xml); endif; endif; endforeach;
-
Consegui alinhar um controle na extrema-direita da tela
pergunta respondeu ao Frank K Hosaka de Frank K Hosaka em PHP
Tentei intercalar o dropdown do Bootstrap no meio dos marcadores do Blade, e nada deu certo. A minha saída foi me livrar dos marcadores do Blade: resources.views.layouts.navigation.blade.php <nav x-data="{ open: false }" class="bg-white border-bottom border-gray-300"> <table> <td> <x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')" style=margin-left:120px> Dashboard </x-nav-link> <td> <x-nav-link :href="route('chirps.index')" :active="request()->routeIs('chirps.index')" style=margin-left:120px> Chirps </x-nav-link> <td class="text-end" style=width:1000px> <div class=dropdown> <button class="btn btn-sm btn-outline-secondary d-inline-flex align-items-center dropdown-toggle" data-bs-toggle=dropdown> {{ Auth::user()->name }} </button> <div class=dropdown-menu> <x-dropdown-link :href="route('profile.edit')"> Profile </x-dropdown-link> <form method="POST" action="{{ route('logout') }}"> @csrf <x-dropdown-link :href="route('logout')" onclick="event.preventDefault();this.closest('form').submit();"> Log Out </x-dropdown-link> </form> </div> </div> </table> -
O meu conhecimento em HTML é bastante precário, ainda não sei mexer no CSS e no elemento <div>. Hoje estudei um pouco o Chirp do Laravel, desativei o vite e no lugar coloquei o CDN do Bootstrap. Tentei encontrar o equivalente do Tailwinds no Bootstrap com a Gemini, mas isso não deu certo. Então resolvi apagar todas as <div> que havia no código blade, e no lugar eu coloquei um <table> e três <td>. Cada célula ficou com o elemento <x>, o novo marcador do Blade. Com a ajuda da Gemini, descobri que o marcador <x> do Blade suporta o CSS do Bootstrap ou um particular como style=margin-left:120px. Isso deu certo no marcador <x-nav-link>, mas não deu certo no marcador <x-dropdown>. A minha saída foi mexer no marcador <td>. Pedi para aumentar a célula para 1000px e alinhar tudo na direita assim <td class="text-end" style=width:1000px>. Certamente, trata-se de uma gambiarra. O código que segue resolve o problema do alinhamento dos elementos na barra de navegação, ainda falta resolver o problema do dropdown, preciso ver como o Bootstrap consegue exibir e ocultar as opções de um menu: arquivo resources.views.layouts.navigation.blade.php <nav x-data="{ open: false }" class="bg-white border-bottom border-gray-300"> <table> <td> <x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')" style=margin-left:120px> Dashboard </x-nav-link> <td> <x-nav-link :href="route('chirps.index')" :active="request()->routeIs('chirps.index')" style=margin-left:120px> Chirps </x-nav-link> <td class="text-end" style=width:1000px> <x-dropdown> <x-slot name="trigger"> <button class="btn btn-sm btn-outline-secondary d-inline-flex align-items-center"> {{ Auth::user()->name }} </button> </x-slot> <x-slot name="content"> <x-dropdown-link :href="route('profile.edit')"> Profile </x-dropdown-link> <form method="POST" action="{{ route('logout') }}"> @csrf <x-dropdown-link :href="route('logout')" onclick="event.preventDefault();this.closest('form').submit();"> Log Out </x-dropdown-link> </form> </x-slot> </x-dropdown> </table>
-
Preciso de ajuda para "session_start()"...
pergunta respondeu ao Carloscba de Frank K Hosaka em Tutoriais & Dicas - PHP
Testei os dois códigos, e não encontrei nenhum erro. O problema é que fiz uma adaptação para fazer os códigos funcionarem, seria necessário todos os códigos para ver exatamente o que acontece. O mais importante é incluir as mensagens de erro, coisa que você não fez. Mas se você suspeita que a função session_start( ) está bloqueando o acesso ao banco de dados, tente isso: <?php // index.php session_start(); $conn=new mysqli("localhost","root","","terminais"); $teste=$conn->query("select * from users"); var_dump($teste); As adaptações que eu fiz para fazer o seu código funcionar estão aqui: <?php // index.php // include('db.php'); mysql users(id,username,password); mysql tasks(id,user_id) session_start(); $conn=new mysqli("localhost","root","","terminais"); // $hashed=password_hash('1234',PASSWORD_BCRYPT); // $conn->query("insert into users (username,password) values ('frank','$hashed')"); $username = 'frank'; // $_POST['username']; $password = '1234'; // $_POST['password']; // Check credentials $sql = "SELECT * FROM users WHERE username = '$username'"; $result = mysqli_query($conn, $sql); $user = mysqli_fetch_assoc($result); if (password_verify($password, $user['password'])) { $_SESSION['user_id'] = $user['id']; // header('Location: tasks.php'); } else { echo "Invalid credentials!"; } $user_id = $_SESSION['user_id']; $sql = "SELECT * FROM tasks WHERE user_id = '$user_id'"; $result = mysqli_query($conn, $sql); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="styles.css"> <title>Task List</title> </head> <body> <h1>Task List</h1> <div class="task-container"> <?php while($task = mysqli_fetch_assoc($result)): ?> <div class="task"> <h2><?php echo $task['title']; ?></h2> <p><?php echo $task['description']; ?></p> <p>Start: <?php echo $task['start_date']; ?> | End: <?php echo $task['end_date']; ?></p> <p>Author: <?php echo $task['author']; ?></p> <a href="edit_task.php?id=<?php echo $task['id']; ?>">Edit</a> <a href="delete_task.php?id=<?php echo $task['id']; ?>">Delete</a> </div> <?php endwhile; ?> </div> <a href="new_task.php">Create New Task</a> </body> </html> -
Além da Gemini, eu também comecei a utilizar o Copilot, tudo na esperança de melhorar o meu código PHP. Nessa semana eu encontrei o Iterables em https://www.w3schools.com/php/php_iterables.asp - tentei testar o código, mas o VS Code reclamou que o método MyIterator::current( ) não é compatível com o método Iterator::current( ). Pedi ajuda para a Gemini e o Copilot, e ambos forneceram o mesmo código, e pediram desculpas por não ajudar mais. A minha tese é de que o PHP foi abandonado, ninguém mais quer saber dessa linguagem. Logo, eu não vou mais perder tempo procurando ajuda onde não existe. Eu tenho conta no iMasters, mas eu preciso passar pela rotina da verificação em duas etapas. Já pedi ajuda várias vezes para o Imasters, e eles falam que o código de ativação pelo Authenticator já foi encaminhado no meu email, só que ele nunca veio. Acredito que o fórum de debate do PHP também vai ser abandonado. E como eu não sei mexer na biblioteca do PHP, tudo o que me resta é seguir o mesmo caminho: esquecer o PHP, o MySQL, o HTML, o JavaScript, o Laravel, e tantos outros recursos que estão disponíveis na internet de graça, só que sem ninguém para explicar como fazer tudo isso funcionar. É uma pena. A outra alternativa é eu tentar continuar com o espírito da tentativa e erro. Quem sabe se eu consigo criar um código que consiga eliminar os mosquitos que teimam em hospedar nos vasos das plantas e flores. Pelo menos, o Copilot e a Gemini ainda não conseguem fazer esse tipo de serviço.
-
Desde 2020 é que estudo o PHP e em 2022 comecei a brincar com o Laravel. O melhor brinquedo que eu encontrei nesse tempo todo foi o var_dump, ele é mais poderoso que o echo, pois ele consegue exibir na tela muito mais que uma string, como é o caso do registro de um banco de dados. object(stdClass) é um nome inventado pelo PHP para guardar informações do tipo registro do banco de dados. Ele tem várias camadas, assim object(stdClass)[0], object(stdClass)[1]... mas na hora de usar o var_dump, ele só mostra o quinto "atributo"; Muito mais bacana que o var_dump( ) é o dd( ) do Laravel, ele é fantástico. O dd( ) mostra uma montanha de informações a respeito de uma variável, além de parar a execução do programa. O único problema é que ele só funciona no Laravel. Nessa nova pesquisa, eu acabei encontrando um método do PDO chamado fetchObject( ), e ele tem a mesma funcionalidade do fetch_assoc( ) do mysqli, ele só mostra o primeiro registro que encontrar pelo caminho, e não mais que isso. Para testar isso, usei o seguinte código: <body style="width:500px;margin:0 auto;margin-top:50px"> <?php class Conn { private static $instancia; private $pdo; private function __construct() { $this->pdo=new PDO("mysql:host=localhost;dbname=diario","root",""); } static function instancia() { if(!self::$instancia) { self::$instancia=new self(); } return self::$instancia; } function select($sql,$params=[]) { $stmt=$this->pdo->prepare("select $sql"); for($i=0;$i<count($params);$i++) { $stmt->bindParam($i+1,$params[$i]); } $stmt->execute(); return $stmt->fetchObject(); // alterar para fetchAll(PDO::FETCH_OBJ) } } $codprod=2; $produto=Conn::instancia()->select("* from tbprod where codprod > ? limit 2",[$codprod]); var_dump($produto); ?> </body> resultado: C:\wamp64\www\Astudy\index.php:36: object(stdClass)[4] public 'codprod' => int 3 public 'un' => string 'pc' (length=2) public 'prod' => string 'Chave Fenda Teste Rayco' (length=23) public 'custo' => string '2.50' (length=4) public 'marg' => float 30 public 'codbar' => string '7898338092162' (length=13) public 'loc' => string '4B6b' (length=4) public 'emb' => float 12 public 'cf' => string '82054000' (length=8) public 'codforn' => string 'e380482' (length=7) public 'estoque' => float 12 public 'origem' => int 0 public 'vazio' => null public 'venda' => string '3.50' (length=4) Os quatro últimos campos desse registro violam o principio básico do banco de dados, ninguém calcula o estoque dentro da tabela de produtos ou coloca o preço de venda lá ou cria um campo para não ter nenhuma informação como o 'vazio'. No meu caso, precisei fazer essa gambiarra para poder comparar o meu banco de dados com o banco de dados da Bling que montei a partir das planilhas que eles fornecem.
-
Eu ainda não consegui entender a função estática, ele é um conceito muito abstrato. Pelo que vi nos tutoriais, a função estática permite usar a classe ao invés de usar um objeto (uma espécie de cópia da classe com atributos particulares). Com a ajuda da Gemini consegui montar o código, entender que é o problema, eu ainda não sei o que é "injeção de SQL" e não sei como o PDO pode evitá-lo. <?php class Conn { private static $instancia; private $pdo; private function __construct() { $this->pdo=new PDO("mysql:host=localhost;dbname=diario","root",""); } static function instancia() { if(!self::$instancia) { self::$instancia=new self(); } return self::$instancia; } function select($sql,$params=[]) { $stmt=$this->pdo->prepare("select $sql"); for($i=0;$i<count($params);$i++) { $stmt->bindParam($i+1,$params[$i]); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } } $codprod=1; $produto=Conn::instancia()->select("* from tbprod where codprod = ?",[$codprod]); var_dump($produto);
-
Hoje estudei o <input list> e achei muito bacana. Para procurar um produto, basta digitar algumas letras, não importa se ele está no começo, no meio ou no fim da descrição: <?php $prod=[['Maçã Tamanho Grande'=>10],['Maçã amanho Médio'=>5], ['Maçã Tamanho Pequeno'=>2]]; ?> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> form {display:flex; justify-content:center; align-items:center; height: 10vh} </style> <form> <input list=lsproduto name=produto placeholder=produto onchange=submit() autofocus autocomplete=off> <datalist id=lsproduto> <?php foreach($prod as $key => $vetor): foreach($vetor as $fruta => $preço) : ?> <option value='<?=$fruta?> :<?=$preço?>'> <?php endforeach; endforeach;?> </form>
-
Encontrei um recurso bacana no VS Code que permite localizar um texto em vários arquivos. Por exemplo, na classe Pessoa eu tinha uma função chamada lista, decidi mudar para inicio. Pedi para o VS Code localizar todos os Pessoa.lista nos arquivos e mudar para Pessoa.inicio. Estou começando a padronizar. Aonde estava public function, decidi mudar tudo para function. Na classe Produto eu tinha a função procurar e a função consultar, mudei para filtra e consulta, ou seja, ao invés de usar o infinitivo vou tentar usar o indicativo da 3a. pessoa do singular. Agora, para pular de um formulário 1 para formulário 2, e de lá ir para o formulário 3 e depois voltar para o formulário 1 não vi outra solução senão apelando para o $_SESSION['end'], assim: arquivo orcamento.php (listagem parcial) <?php class Orcamento { function pessoa($pedido) { $_SESSION['end']="?Orcamento.pessoaSelecionada.$pedido"; return header("location:?Pessoa.inicio"); } function pessoaSelecionada($pedido) { $codp=$_SESSION['codp']; (new Conn)->update("tbpedido set codp = $codp where ped=$pedido"); return $this->inicio($pedido); } } É óbvio que usar variável global é perigoso, principalmente quando ele é utilizado como uma rota (tipo if(isset($_SESSION['end']){ } else { }), eu já vi muitos resultados inesperados aqui, assim sempre dou um jeito de reinicializar a variável global (unset($_SESSION['end'])) quando achar oportuno. Certamente é um péssimo exemplo de programação. Mas é para isso que serve o fórum, alguém pode sugerir coisa melhor.