Ir para conteúdo
Fórum Script Brasil

Frank K Hosaka

Membros
  • Total de itens

    1.533
  • Registro em

  • Última visita

Tudo que Frank K Hosaka postou

  1. 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]); }
  2. 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.
  3. 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>
  4. 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>
  5. 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();
  6. 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.
  7. 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]); }
  8. 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
  9. Em 2022, não existia a Gemini, o Copilot e tantos outros serviços de Inteligência Artificial. Assim, para eu ajuntar duas tabelas no Laravel, tive que usar a classe DB. Aqui em 2024, mostrei o model do tbhistprod para a Gemini: <?php // app > Models > tbhistprod.php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class tbhistprod extends Model { use HasFactory; protected $table="tbhistprod"; const UPDATED_AT=null; const CREATED_AT=null; protected $fillable=['codprod','dia','docto','qt','custototal','codp','lcto','pessoa']; public function produtos() { return $this->belongsTo(tbprod::class,'codprod'); } public function pessoa() { return $this->belongsTo(tbpessoa::class,'codp'); } } Perguntei para ela como ajuntar a tbhistprod com a tbprod pelo Eloquent, e aqui a resposta: <?php // app > Http > Controllers / Estoque.php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\tbdiario; use App\Models\tbentraprod; use App\Models\tbhistprod; use App\Models\tbpessoa; use App\Models\tbprod; class Estoque { function teste() { $entrada=tbdiario::where('contad',123)->sum('valor'); $verificar=tbhistprod::with('produtos') ->whereHas('produtos',function($query) {$query->where('loc','<>','a24');}) ->where('custototal','>',0) ->sum('custototal'); return "entrada $entrada <br> verificar $verificar"; } //... }
  10. Frank K Hosaka

    Problemas com rotas

    Eu usei a pasta a Astudy para testar o seu código, veja se o seu arquivo .htaccess (que fica na raiz do projeto como o index.php) está mais ou menos assim: # Ativação do RewriteEngine que nos permite gerenciar as rotas RewriteEngine On # Definição da rota principal RewriteBase / # Se o diretório ou arquivos digitados na URL não existirem, seguir a RewriteRule RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f # Rewrite Rule, redirecionar todas as requests para o index.php RewriteRule ^(.+)$ /Astudy/index.php [QSA,L] No index.php utilizei um autload que você não listou, e também modifiquei a rotina original <?php spl_autoload_register(function ($class) { $file = __DIR__ . '/app/controllers/' . $class . '.php'; if (file_exists($file)) { require_once $file; } }); require 'rotas.php'; try{ $pos=strrpos($_SERVER['REQUEST_URI'],'/'); $uri=substr($_SERVER['REQUEST_URI'],$pos); $request=$_SERVER['REQUEST_METHOD']; if(!isset($router[$request])) { throw new Exception('A rota não existe0'); } if(!array_key_exists($uri,$router[$request])) { throw new Exception('A rota não existe1'); } $controller=$router[$request][$uri]; $controller(); }catch(Exception $e) { echo "". $e->getMessage() .""; } E aqui rotas.php <?php function load($controller,$action) { try { // se controller existe if (!class_exists($controller)) { throw new Exception("O controller {$controller} não existe"); } $controllerInstance = new $controller(); if (!method_exists($controllerInstance, $action)) { throw new Exception( "O método {$action} não existe no controller {$controller}" ); } $controllerInstance->$action(); } catch (Exception $e) { echo $e->getMessage(); } } $router=[ "GET" => [ "/" => fn () => load("HomeController", "index"), "/info" => fn () => load("InfoController", "info"), ], "POST" => [ //"/info" => fn () => load("InfoController", "info"), ], ]; Espero que tenha ajudado. Eu gostei desse código, ele se aproxima bastante do modelo Laravel. Eu tenho o PHP 8.2, um autoload e um roteador bem safado que dispensa o uso de pastas, coloco tudo no diretório raiz, não uso o arquivo .htaccess e não preciso atualizar o arquivo rotas.php (aliás, eu nem tenho esse arquivo) toda vez que eu criar uma tarefa nova, aqui está ele, para usá-lo, eu uso a sintaxe ?classe.metodo.argumento: arquivo index.php <?php spl_autoload_register(fn ($class) => require str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'); $rota='login_login'; if($_GET) { if(strpos(key($_GET),"_")==0) { exit; } $rota=isset($_GET) ? key($_GET) : $rota; } $segmentos=explode('_',$rota); $nomeControle=$segmentos[0] ?? 'login'; $metodo=$segmentos[1] ?? 'login'; $parametro=$segmentos[2] ?? null; $controle=new $nomeControle(); $controle->$metodo($parametro); arquivo login.php <?php class Login { function login() { ?> olá mundo! <br> <form method=post action=?login.maisExemplo> <input type=submit value="Me clique"> </form> <?php } function maisExemplo() { echo "E aí, você gostou?"; } }
  11. Você esqueceu de colocar o script completo. Aqui um exemplo de como você pode expor o problema: Parse error: syntax error, unexpected token "?" in C:\wamp64\www\Astudy\index.php on line 28 File: index.php 01: <?php 02: class Teste 03: { 04: function comecarDeNovo() 05: { 06: ?> 07: <p> 08: <form method=post action=index.php> 09: <input type=submit value='Começar de novo'> 10: </form> 11: <?php 12: exit; 13: } 14: function inicio() 15: { 16: ?> 17: conteúdo do $_GET : 18: <?=var_dump($_GET)?> 19: conteúdo do $_POST : 20: <?=var_dump($_POST)?> 21: <?php 22: return $this->comecarDeNovo(); 23: } 24: 25: function mensagem($problema) 26: { 27: 28: Rota <?=json_encode($problema)?> inválida! 29: <?php 30: return $this->comecarDeNovo(); 31: } 32: function naoFazerNada() 33: { 34: 35: } 36: 37: } 38: spl_autoload_register(fn ($class) => 39: require str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'); 40: $rota='Teste_naoFazerNada'; 41: if($_GET) 42: { 43: if(strpos(key($_GET),"_")==0) 44: { 45: return (new Teste)->mensagem($_GET); 46: } 47: $rota=isset($_GET) ? key($_GET) : $rota; 48: } 49: $segmentos=explode('_',$rota); 50: $nomeControle=$segmentos[0]; 51: $metodo=$segmentos[1]; 52: $parametro=$segmentos[2] ?? null; 53: $controle=new $nomeControle(); 54: $controle->$metodo($parametro); 55: ?> 56: <form method=post action=?teste.inicio> 57: <input type=submit name=bacalhau value=Teste> 58: <input type=hidden name=sardinha value=nenhum> 59: </form>
  12. Eu comecei a estudar o PHP em 2020. Os meus códigos estavam bastante embaralhados, PHP aqui, HTML ali, e era difícil consertar o código. Hoje eu sei um pouco sobre classe e imaginei se era possível criar um conjunto de funções sem o autoload e sem o roteador no PHP. A resposta é sim, olha só que beleza: arquivo classe.php <?php class Classe { function roteador() { if(count($_GET)) { $metodo=key($_GET); $parametro=$_GET[$metodo]; return $this->$metodo($parametro); } if(count($_POST)) { $metodo=key($_POST); $parametro=$_POST[$metodo]; return $this->$metodo($parametro); } } } (new Classe)->roteador(); Se você não trabalha com a classe (programação orientada a objeto) não há porque instalar um roteador no PHP, mas nada impede de você trabalhar com a classe no meio dos códigos. Nesse caso, é a classe que vai precisar de um roteador para saber qual a função você precisa utilizar. Vamos supor que exista uma função chamada inicio. Para chamá-lo, você pode usar header('location:classe.php?inicio). No caso acima, essa função não existe. A seguir vou deixar uma lista de uma classe que não tem o suporte de um autoload e um roteador no index.php: arquivo diario.php <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"> </script> <style> @media (min-width: 768px) { body {width: 50%; margin: auto} } @media (max-width: 767px) { body {width: 75%; margin: auto} } a {color:blue;text-decoration:none} a:hover {color:black;} form {margin:0} .inv {border:none;background:transparent;font-weight:600} .linha {line-height:0px} summary{list-style:none} td {white-space: nowrap} </style> <?php session_start(); $mysqli=new mysqli("localhost","root","","teste"); date_default_timezone_set('America/Sao_Paulo'); function dbr($date) { return date('d/m/y',strtotime($date)); } function dec($value) { return ($value) ? number_format($value,2,',','.') : null; } function deca($num) { $value=str_replace(".","",$num); return str_replace(",",".",$value); } class Diario { function roteador() { if(count($_GET)) { $metodo=key($_GET); $parametro=$_GET[$metodo]; return $this->$metodo($parametro); } if(count($_POST)) { $metodo=key($_POST); $parametro=$_POST[$metodo]; return $this->$metodo($parametro); } } function inicio() { global $mysqli; $dia=(isset($_SESSION['dia'])) ? $_SESSION['dia'] : date('Y-m-d'); $mensagem=(date('Y-m-d',strtotime($dia))<>date('Y-m-d')) ? " hoje é ".date('d/m/Y') : null; $lctos = json_decode(json_encode($mysqli->query("select * from tbdiario where dia = '$dia' order by lcto, docto")->fetch_all(MYSQLI_ASSOC))); $somaDebito=$mysqli->query("select sum(case when contad>0 then valor else 0 end) as soma from tbdiario where dia = '$dia'")->fetch_assoc()['soma']; $somaCredito=$mysqli->query("select sum(case when contac>0 then valor else 0 end) as soma from tbdiario where dia = '$dia'")->fetch_assoc()['soma']; ?> <table class='table table-striped'> <tr class=fw-semibold> <td colspan=5> <form method=post action=diario.php> <input type='submit'name=lancamento value='Lançamentos' size='8'> do dia <input id=data type=date size=6 name=dia value=<?=$dia?> onchange=submit()><?=$mensagem?> </form> <tr class=fw-semibold><td>Lcto<td>Ctad<td>Ctac<td class=text-end>Valor <td> <form method=post action=diario.php> <input name=historico onchange=submit() autocomplete=off placeholder='Procurar no histórico'> </form> <?php foreach($lctos as $lcto): ?> <tr class=linha> <td><?=$lcto->lcto?> <td><?=$lcto->contad?> <td><?=$lcto->contac?> <td class=text-end><?=dec($lcto->valor)?> <td><?=$lcto->hist?> <?php endforeach; ?> <tr class=fw-semibold><td><td><td><td class=text-end><?=dec($somaDebito)?><td> <?php if($somaCredito!==$somaDebito): ?> <td class='text-end text-danger'><?=dec($somaCredito)?> Total de crédito <?php else: ?> </table></div> <?php endif; } function historico($hist) { global $mysqli; $historico = str_replace(' ','%',$hist); $lctos=json_decode(json_encode($mysqli->query("select * from tbdiario where hist like '%$historico%'")->fetch_all(MYSQLI_ASSOC))); ?> Lançamentos com o histórico <?=$hist?> <table class='table table-striped linha'> <tr><th>Dia<th>Lçto<th>CtaD<th>CtaC<th>Valor<th>Histórico <?php foreach($lctos as $lcto): ?> <tr> <td><?=dbr($lcto->dia)?> <td><?=$lcto->lcto?></a> <td><?=$lcto->contad?> <td><?=$lcto->contac?> <td class=text-end><?=dec($lcto->valor)?> <td><?=$hist?> <?php endforeach; ?> </table> <?php } function registro() { global $mysqli; $dia=$_GET['registro']; $contad = empty($_GET['debito']) ? 'null' : $_GET['debito']; $contac = empty($_GET['credito']) ? 'null' : $_GET['credito']; $lcto=$_GET['lcto']; $valor= empty($_GET['valor']) ? 'null' : deca($_GET['valor']); $hist=$mysqli->real_escape_string($_GET['hist']); $mysqli->query("insert into tbdiario (lcto,dia,contad,contac,valor,hist) values ($lcto,'$dia',$contad,$contac,$valor,'$hist')"); return $this->inicio(); } function lancamento() { global $mysqli; $dia=$_SESSION['dia']; //plano de contas $ativo=json_decode(json_encode($mysqli->query("select * from tbconta where conta < 201")->fetch_all(MYSQLI_ASSOC))); $passivo=json_decode(json_encode($mysqli->query("select * from tbconta where conta >=201")->fetch_all(MYSQLI_ASSOC))); $contaPassivo=count($passivo); $proximoLcto=$mysqli->query("select lcto from tbdiario order by lcto desc") ->fetch_assoc()['lcto']+1; ?> <script> btmenu.innerHTML='Lançamento' document.title='Lançamento' var idControle,Descricao function ir(controle,destino) { idControle=controle Descricao=destino } function voltar(texto) { controle=document.getElementById(idControle) destino=document.getElementById(Descricao) controle.value=texto.substr(0,3) tamanho=texto.strlen destino.innerHTML=texto.substr(4,tamanho) } </script> <div class=modal id=myModal> <div class=modal-dialog> <div class=modal-content> <div class=modal-body> <table class='table table-striped linha'> <?php foreach($ativo as $key=>$row): ?> <tr><td><a href data-bs-dismiss='modal' onclick=voltar(this.innerHTML)><?=$row->conta." ".$row->descricao?></a> <?php if($key<$contaPassivo): ?> <td><a href data-bs-dismiss='modal' onclick=voltar(this.innerHTML)><?=$passivo[$key]->conta." ".$passivo[$key]->descricao?></a> <?php else: ?> <td> <?php endif; ?> <?php endforeach; ?> </table> </div> </div> </div> </div> <form> <div> <table class='table table-sm table-striped'> <tr><td>Lançamento<td><?=$proximoLcto?> <tr><td>Data<td><?=dbr($dia)?> <input type='hidden' name='registro' value='<?=$dia?>'> <input type='hidden' name='lcto' value=<?=$proximoLcto?>> <tr><td>ContaD<td><input id=idebito name=debito onclick="ir(id,'adebito')" data-bs-toggle=modal data-bs-target=#myModal size=2 autocomplete=off> <a id=adebito></a> <tr><td>ContaC<td><input id=icredito name=credito onclick="ir(id,'acredito')" data-bs-toggle=modal data-bs-target=#myModal size=2 autocomplete=off> <a id=acredito></a> <tr><td>Valor<td><input name='valor' id='valor' autocomplete='off' onchange='hist.focus()'> <tr><td>Histórico<td><input name='hist' id='hist' size='30' autocomplete='off' required> <tr><td><td><input type=submit value=Confirmar></table></div> </form> <?php } function dia($dia) { $_SESSION['dia']=$dia; $this->inicio(); } } (new Diario)->roteador(); ?>
  13. O meu projeto Orçamento usa o PHP, a Classe e o Laravel, os três usam o mesmo banco de dados e fazem a mesma coisa. A minha ideia é tentar igualar o código nos três, o máximo que eu puder. Estou muito contente ter aprendido alguma coisa de classe em 2024. Em 2022 eu comecei a estudar o Laravel, mas eu não aprendi nada sobre classe. A seguir estudei o MVC, mas os tutoriais são de amargar. Só em 2024 é que comecei a entender o que é autoload e o que é roteador. A classe é a melhor forma de organizar as funções. O meu desafio é usar a classe no PHP sem o autoload e sem o roteador. Outro desafio é o roteador do Laravel. O roteador que eu tenho na Classe é bem safado, jamais vai chegar aos pés do Laravel. Mas nada me impede de fazer o Laravel usar a mesma sintaxe que eu uso no roteador da Classe. Enfim, são apenas ideias. Outro desafio é entender porque o Tailwinds não se dá bem com a <table>.
  14. Finalmente decidi atualizar o Laravel que uso no Hostinger, primeiro precisei destruir todo o site. Pedi para a Hostinger instalar o Laravel 11, mas ele não instalou coisa alguma. Eu fiz a instalação através do terminal SSH, ele acabou criando uma pasta chamada Laravel. Peguei todo o conteúdo da pasta Laravel e joguei no diretório raiz. Isso não deu certo. Então eu fui no site onde tenho o projeto Chirp, e de lá copiei a pasta Public. Consegui colocar o Laravel no navegador. A seguir instalei o Breeze com Blade. Copiei o meu projeto que tenho no micro bem como alterei vários arquivos tipo .env, composer.json (para carregar o arquivo Helpers.php), web.php, AppServiceProvider.php, Config/app.php (para definir o horário). Agora o Laravel dá suporte para o Tailwinds bem como o Bootstrap. Como eu não sei fazer o Tailwinds trabalhar com o marcador <table>, o melhor jeito é continuar trabalhando com o suporte do CDN Bootstrap (eu uso app.php no diretório raiz da pasta Views), o app.php com o Tailwinds está em outra pasta, e só dá para usá-lo se você usar o marcador blade <x-app-layout>. Todas essas modificações dá para fazer no Hostinger se você pegar o plano VPS.
  15. arquivo resources > views > teste.blade.php <x-app-layout> <table> <tr><td class='ml-4 bg-blue-500 p-4'>Coluna A</td> <td class='ml-4 bg-greeen-500'>Coluna B</td></tr> </table> <br> <div class='flex'> <div class='ml-4 bg-blue-500 p-4'>Coluna A</div> <div class='ml-4 bg-green-500 p-4'>Coluna B</div> </div> </x-app-layout>
  16. Ontem, choveu um pouco em Diadema, mas isso foi o suficiente para eu perder o WiFi que vinha do roteador da Claro. Mesmo assim, eu estava estudando o Laravel Blade. Fui no terminal, e usei o comando "php artisan serve". Em seguida, abri outro terminal e usei o comando "npm run dev". Abri o navegador, e ele me informou que eu não tinha nenhuma conexão. Eu digitei "localhost:8000", e assim consegui testar o meu projeto. Isso é uma boa noticia, o WampServ funciona, mesmo que o roteador da Claro tenha pifado!
  17. Lamentavelmente, isso daí não é nada óbvio. Estou tentanto estudar a linguagem orientada a objetos desde 2020, mas eu só consegui engatinhar em 2024 com a ajuda do autoload para o PHP 8.2 que o iOwys publicou no fórum Script. O autoload explica para o PHP aonde estão as classes. Mas não basta o PHP saber onde estão as classes, ele precisa saber como chegar até a classe, assim ele precisa do roteador. Na internet tem um monte de roteadores prontos para você baixar pelo comando composer, mas ao invés disso eu ofereço um roteador meia-boca para você ver a cara dele, e estudar como ele funciona. Classe é um conceito muito antigo, mas para fazer funcionar, só nesse ano é que eu consegui alguma coisa. arquivo config.php <?php ini_set('display_errors', 1); date_default_timezone_set('America/Sao_Paulo'); spl_autoload_register(fn ($class) => require str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'); function view($arquivo, $array = null) { if (!is_null($array)){ foreach ($array as $var => $value) { ${$var} = $value; } } ob_start(); include $arquivo . ".php"; ob_flush(); } arquivo index.php <?php require 'config.php'; $rota='Provas_inicio'; if($_GET) { if(strpos(key($_GET),"_")==0) { exit; } $rota=isset($_GET) ? key($_GET) : $rota; } $segmentos=explode('_',$rota); $nomeControle=$segmentos[0] ?? 'Provas'; $metodo=$segmentos[1] ?? 'inicio'; $parametro=$segmentos[2] ?? null; $controle=new $nomeControle(); $controle->$metodo($parametro); arquivo provas.php <?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 imprimir() { $vetor=explode(",",$_POST['questoes']); echo "Prova 1<br>"; $numeroQuestao=0; foreach($vetor as $v) { $prova=$this->selecionar($v); $vetores=explode(',',$prova['questao']); $questao=array_shift($vetores); $numeroQuestao++; $this->imprimirQuestao($questao,$numeroQuestao); $indicador=0; foreach($vetores as $alternativa) { $indicador++; echo chr($indicador+64) . ". " . $alternativa . "<br>"; } } echo "<br>--------- picote aqui----<br>"; echo "<br>Prova 2<br>"; shuffle($vetor); $numeroQuestao=0; foreach($vetor as $v) { $prova=$this->selecionar($v); $vetores=explode(',',$prova['questao']); $questao=array_shift($vetores); $numeroQuestao++; $this->imprimirQuestao($questao,$numeroQuestao); shuffle($vetores); $indicador=64; foreach($vetores as $alternativa) { $indicador++; echo chr($indicador) . ". " . $alternativa . "<br>"; } } } function imprimirQuestao($questao,$numeroQuestao) { echo "<br>"; echo $numeroQuestao . ". " . $questao . "<br>"; } function inicio() { view('provasView'); } function selecionar($id) { return $this->Conexao->query("select * from provas where id=$id") ->fetch_assoc(); } } arquivo provasView.php <form method=post action=?Provas.imprimir> Quais são as questões selecionadas? <br> <input name=questoes placeholder="exemplo: digite 4,3"> <br> <input type=submit> </form>
  18. Você não pode usar espaço entre a classe e o método: o correto é <?php use PHPUnit\Framework\TestCase; class ExceptionTest extends TestCase { public function testCreateException() { $throwable = new Exception('Test exception', 123); $exception = new Exception( $throwable->getMessage(), $throwable->getCode(), $throwable ); $this->assertEquals('Test exception', $exception->getMessage()); $this->assertEquals(123, $exception->getCode()); $this->assertSame($throwable, $exception->getPrevious()); } }
  19. Há cinco anos, eu imaginava que precisava de um marcador para executar um comando JavaScript. O meu conhecimento em HTML era e ainda é bem precário, mas improvisei assim: <tr><td><a href data-bs-dismiss='modal' onclick=voltar(this.innerHTML)> {{$row->conta." ".$row->descricao}}</a> Eu também não sabia nada de CSS, assim eu apelei para o Bootstrap. E tudo foi uma maravilha nos últimos cinco anos. Hoje, no entanto, estou estudando o Laravel, o tutorial do Chirper com Blade. O Laravel Blade trabalha com o CSS da Tailwinds. Ao invés de pesquisar como funciona o modal no Tailwinds, eu simplesmente tirei um monte de <div> que o Bootstrap trabalhava bem como as suas classes. E tudo funcionou quase perfeitamente, o problema é que eu selecionava a conta, os dados eram passados no formulário principal, mas tudo era apagado porque o navegador foi atualizado. Depois de muito investigar, percebi que era o <a href> é que atualizava a tela, o Bootstrap é que dava um jeito de neutralizá-lo. Para corrigir o problema, eu só precisei eliminar o marcador <a href>. Quanto ao comando JavaScript, eu coloquei no marcador <td>. No Tailwinds, eu aprendi como diminuir o espaço entre as linhas através da classe 'leading-tight'. Para exibir ou ocultar a <div> onde montei o plano de contas, eu usei o CSS puro: Ah, o Tailwinds tem uma classe bacana que faz a caixa do input ficar redondo e que muda a cor assim que você foca nela, ele é enorme, eu decidi jogar no arquivo .env com o identificador input, e para usar no arquivo blade, eu chamo a classe com o marcador <?=env('input')?> .env input="class='ml-4 px-3 py-1 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'" resources > views > diarioLcto.blade.php <x-app-layout> <script> document.title='<?=$btMenu?>' var idControle,Descricao function ir(controle,destino) { idControle=controle Descricao=destino plano.style.display="block" } function voltar(texto) { controle=document.getElementById(idControle) destino=document.getElementById(Descricao) controle.value=texto.substr(0,3) tamanho=texto.strlen destino.innerHTML=texto.substr(4,tamanho) plano.style.display='none' } </script> <div id=plano style="display:none" class="w-[500px] mx-auto fixed right-60"> <table class="leading-tight"> <?php foreach($ativo as $key=>$row): ?> <tr><td onclick=voltar(this.innerHTML)><?=$row->conta." ".$row->descricao?> <?php if($key<$contaPassivo): ?> <td onclick=voltar(this.innerHTML)><?=$passivo[$key]->conta." ".$passivo[$key]->descricao?></a> <?php else: ?> <td> <?php endif; ?> <?php endforeach; ?> </table> </div> <table class='w-[500px] mx-auto mt-2 leading-tight'> <?php if(count($produtos)): ?> <tr class=fw-semibold><td class=text-right>Cod<td>Produto <td class=text-end>Qt<td>Un<td class=text-right>Total <?php foreach($produtos as $prod): ?> <tr> <td class=text-end><a href="produtoAlterar?id=<?=$prod->id?>"><?=$prod->codprod?></a> <td nowrap><?=$prod->prod?> <td class=text-right><?=virgula($prod->qt)?> <td><a href="produtoExcluir?id=<?=$prod->id?>"><?=$prod->un?></a> <td class=text-right><?=dec($prod->custototal)?> <?php endforeach ?> <tr class='fw-semibold'><td><?=date('d/m/y',strtotime($produtos[0]->dia))?> <td colspan=3> <form method=post action="diarioProduto"> <input type=submit name=produto value='Produto' class=mr-10> <?php if($somaProdutos!==0):?> <a href=diarioPessoa><?=$produtos[0]->pessoa?></a> <td class=text-right><?=dec($somaProdutos)?> </form> <?php else: ?> <tr><td><td><td><td> <?php endif; ?> <?php else: ?> <?php if($btMenu!=="Novo Lançamento"): ?> <tr><td> <form method=post action="diarioProduto"> <input type=submit name=produto value='Produto'> </form> <?php endif; ?> <?php endif; ?> <form action='<?=$comando?>' method=post> <?php if($btMenu=="Edita Lançamento"): ?> <tr><td colspan=5> <a href="diarioAcrescentar&lcto=<?=$consulta->lcto?>"> Acrescentar no lançamento <?=$consulta->lcto?></a> <?php endif;?> <tr><td>Dia<td> <input <?=env('input')?> type=date name=lcto[] size=2 value='<?=$consulta->dia?>' autocomplete=off> <tr><td>Lcto<td colspan=4> <input <?=env('input')?> type=button name=lcto[] size=4 value='<?=$consulta->lcto?>'> <tr><td>ContaD<td colspan=4> <input <?=env('input')?> id='ContaD' name=lcto[] onclick="ir(this.id,'DescD')" size=2 value='<?=$consulta->contad?>' autocomplete=off> <a id=DescD></a> <tr><td>ContaC<td colspan=4> <input <?=env('input')?> id='ContaC' name=lcto[] onclick="ir(this.id,'DescC')" size=2 value='<?=$consulta->contac?>' autocomplete=off> <a id=DescC></a> <tr><td>Valor<td colspan=4> <input <?=env('input')?> name=lcto[] value='<?=dec($consulta->valor)?>' autocomplete=off size=6> <tr><td>Histórico<td colspan=4> <input <?=env('input')?> name=lcto[] value="<?=$consulta->hist?>" autocomplete=off size=49> <input type=hidden name=lcto[] value=<?=$consulta->docto?>> <tr><td><td><input <?=env('input')?> type=submit value=Confirmar><td><td><td> </form> </table> </x-app-layout>
  20. Eu não sei mexer no Linux. Tentei mexer em 1997, mas me perdi bastante. Eu tive que esperar até 2020 até encontrar o WampServ para o Windows.
  21. Eu uso o WampServ, e na bandeja do Windows tem um ícone verde, clicando nele tenho PHP > PHP Extensions > ative pgsql. O código que eu encontrei com o copilot.microsoft.com é assim: <?php // Defina os parâmetros de conexão $host = "localhost"; $port = "5432"; $dbname = "seu_banco_de_dados"; $user = "seu_usuario"; $password = "sua_senha"; // Crie a string de conexão $conn_string = "host=$host port=$port dbname=$dbname user=$user password=$password"; // Tente estabelecer a conexão $dbconn = pg_connect($conn_string); // Verifique se a conexão foi bem-sucedida if ($dbconn) { echo "Conexão bem-sucedida!"; } else { echo "Erro ao conectar ao banco de dados."; } ?> Espero que isso lhe ajude.
  22. O CSS do Bootstrap é assim: <input class='control'> O CSS do Tailwinds é assim: <input class=class='px-3 py-1 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'> Agora, imagina que você tem um formulário com seis inputs! A minha sorte é que o Laravel suporta o PHP, inclusive o marcador <?= ?> (o equivalente no Blade é {{ }}, mas no meu caso não funcionou), e assim consegui contornar o problema: resources > views > diarioEdita.blade.php <x-app-layout> @php $class="class='px-3 py-1 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'"; @endphp <form method=post action='diarioEditado' class='w-[500px] mx-auto'> <table> <tr><td><input name=docto type=hidden value={{ $lcto->docto }}> Lçto<td><input name=lcto value='{{ $lcto->lcto }}' <?=$class?> > <tr><td>Dia<td><input name=dia type=date value={{ $lcto->dia }} <?=$class?>> <tr><td>ContaD<td><input name=contad value={{ $lcto->contad }} <?=$class?>> <tr><td>ContaC<td><input name=contac value={{ $lcto->contac }} <?=$class?>> <tr><td>Valor<td><input name=valor value={{ $lcto->valor }} <?=$class?>> <tr><td>Histórico<td><input name=hist value='{{ $lcto->hist }}' <?=$class?>> </table> </x-app-layout>
  23. Breeze é um acessório que turbina o Laravel com a rotina de login e também instala a engenharia do CSS Tailwinds. Ele aparece no tutorial do Chirper versão Blade, Livewire e Inertia. Através do migrate, o Breeze cria no banco de dados a tabela user. O problema é que eu sou do tempo do Microsoft Access, onde aprendi a dar o nome da tabela assim: tbusuarios, com o nome dos campos diferentes do user do Breeze. Para fazer a minha tbusuarios funcionar no Laravel com Breeze tive que alterar o model assim: app > Models > User.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use HasFactory, Notifiable; protected $table = 'tbusuarios'; protected $fillable = ['nome','email','senha']; protected $hidden = ['senha','remember_token']; protected function casts(): array { return ['email_verified_at' => 'datetime', 'senha' => 'hashed','nome'=>'string']; } function getAuthPassword() { return $this->senha; } function getAuthPasswordName() { return 'senha'; } } A rotina de login do Breeze permite deletar a conta e também alterar os dados da conta, só que eu não consegui alterar o nome do usuário. Seguindo o bom exemplo daquele candidato que deu uma cadeirada no adversário que repetia desaforos a todo momento, eu fiz a mesma coisa: app > Http > Controllers > ProfileController.php <?php namespace App\Http\Controllers; use App\Http\Requests\ProfileUpdateRequest; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Redirect; use Illuminate\View\View; class ProfileController extends Controller { //... function update(ProfileUpdateRequest $request) { $validated['nome']=$request->name; $validated['email']=$request->email; $request->user()->fill($validated); if ($request->user()->isDirty('email')) { $request->user()->email_verified_at = null; } $request->user()->save(); return Redirect::route('profile.edit')->with('status', 'profile-updated'); } }
  24. Hahahahaha... agora, eu entendi. Você não confia nos alunos: <?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 imprimir($vetor) { echo "Prova 1<br>"; $numeroQuestao=0; foreach($vetor as $v) { $prova=$this->selecionar($v); $vetores=explode(',',$prova['questao']); $questao=array_shift($vetores); $numeroQuestao++; $this->imprimirQuestao($questao,$numeroQuestao); $indicador=0; foreach($vetores as $alternativa) { $indicador++; echo chr($indicador+64) . ". " . $alternativa . "<br>"; } } echo "<br>--------- picote aqui----<br>"; echo "<br>Prova 2<br>"; shuffle($vetor); $numeroQuestao=0; foreach($vetor as $v) { $prova=$this->selecionar($v); $vetores=explode(',',$prova['questao']); $questao=array_shift($vetores); $numeroQuestao++; $this->imprimirQuestao($questao,$numeroQuestao); shuffle($vetores); $indicador=64; foreach($vetores as $alternativa) { $indicador++; echo chr($indicador) . ". " . $alternativa . "<br>"; } } } function imprimirQuestao($questao,$numeroQuestao) { echo "<br>"; echo $numeroQuestao . ". " . $questao . "<br>"; } function selecionar($id) { return $this->Conexao->query("select * from provas where id=$id") ->fetch_assoc(); } } (new Provas)->imprimir([4,3]);
  25. Lá em 2020, gastei quase um mês para montar uma consulta no MySQL para obter todos os documentos da tabela diário que envolviam as contas 130 e 211, eles estavam espalhados nos campos ctad e ctac. Aqui em 2024 enfrentei problema no Laravel. Ao invés de consultar a internet, achei melhor montar várias consultas simples, e depois pedi para o PHP fazer o resto do serviço. Ficou bem mais fácil, o MySQL é um poderoso banco de dados, mas ao invés de pedir serviços complicados para ele, melhor jogar nas costas do PHP! <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\tbcontacorrente; use App\Models\tbdiario; use App\Models\tbpessoa; class Pagar { function inicio() { $pendencias=tbcontacorrente::pluck('docto'); $doc1=tbdiario::where('dia','>','2023-12-31')->where('contad',130)->pluck('docto'); $doc2=tbdiario::where('dia','>','2023-12-31')->where('contac',130)->pluck('docto'); $doc3=tbdiario::where('dia','>','2023-12-31')->where('contad',211)->pluck('docto'); $doc4=tbdiario::where('dia','>','2023-12-31')->where('contac',211)->pluck('docto'); $documentos=$doc1->merge($doc2)->merge($doc3)->merge($doc4); $diferenca=$documentos->diff($pendencias); foreach($diferenca as $d) { $lcto=tbdiario::where('docto',$d)->value('lcto'); tbcontacorrente::create(['docto'=>$d,'lcto'=>$lcto,'pgto'=>0]); } $pendencias=[]; $contas=tbcontacorrente::where('pgto',0)->orderBy('vcto')->get(); foreach($contas as $conta) { $doc=tbdiario::where('docto',$conta->docto)->first(); $vcto=$conta->vcto; $docto=$conta->docto; $lcto=$doc->lcto; if($doc->contad==130 || $doc->contad==211) { $debito=$doc->valor; $credito=null; } else { $debito=null; $credito=$doc->valor; } $hist=dbr($doc->dia)." ".$doc->hist; if($conta->codp) { $pessoa=tbpessoa::where('codp',$conta->codp)->value('pessoa'); } else { $pessoa="Selecionar"; } $pendencias[]=['vcto'=>$vcto,'docto'=>$docto,'lcto'=>$lcto,'debito'=>$debito, 'credito'=>$credito,'hist'=>$hist,'pessoa'=>$pessoa]; } $pendencias=json_decode(json_encode($pendencias)); return view('pagarView',['pendencias'=>$pendencias]); } // ... }
×
×
  • Criar Novo...