Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Thiago de Oliveira Cruz

Laravel - Melhores práticas

Recommended Posts

Olá galera,

Faz tempo que não venho aqui perguntar nada rs...

Mas me surgiu uma dúvida cruel em relação a como receber os dados de um model.

Eu tenho uma tabela chamada VendorMaster a qual contém todos os meus vendedores, essa tabela se relacionada com uma tabela chamada division que se relaciona com uma chamada listing e por ai vai...

Ai eu tenho o seguinte código:

$resp = VendorMaster::all();

foreach($resp as $key=>$vendor){
  $vendor->division;
  foreach($vendor->division as $key=>$division) {
    $division->listing;
    foreach($division->listing as $key=>$listing){
      $listing->building;
      $listing->building->region;
      $listing->building->city;
      $listing->building->country;
      $listing->building->style;
    }
  }
}

Bom o que esse código faz?

Ele pega todos os vendedores e faz um loop por seus objetos e coleta dado dos outros models

No caso 1 vendor tem muitas divisions e divisions tem muitos listings

Queria saber se eu fizer dessa forma eu vou tar fazendo um loop exagerado no meu banco (eu acredito que sim...)

Se seria ou não melhor criar uma função no model vendor com joins para fazer exatamente a mesma coisa.

Eu acredito que se eu fizer 1 função única na qual eu faça vendor->getAllDependets ou algo do genero... se vai ser mais rápido e confiável para meu código do que fazer esse loop assim como eu fiz.

Todas as sugestões são bem vindas...

To querendo otimizar as transações para que isso não vire a festa do pau oco nem que leve 3 anos pro banco buscar tudo.

Detalhe eu sei que o aproche atual provavelmente não é o melhor... mas ele funciona rs.

Resultado final desejado é algo assim:

"vendorMasterID": 714,
"vendorMasterName": "asdahsiduasdagd",
"vendorMasterShortName": "asdahsiduasdagd",
"vendorMasterCode": "ASG",
"vendorMasterPosition": 100,
"vendorMasterActive": 1,
"vendorMasterCreated": "2016-12-20 19:38:59",
"vendorMasterAPICode": null,
"division": [{
	"vendorDivisionID": 1230,
	"vendorDivisionName": "lalalla",
	"vendorDivisionVendorID": 714,
	"vendorDivisionTypeID": 1,
	"vendorDivisionSetPrice": 1,
	"vendorDivisionCommission": 0,
	"vendorDivisionSetAvail": 0,
	"vendorDivisionSetMLOS": 0,
	"vendorDivisionSetCustomMLOS": 0,
	"vendorDivisionFRS": 0,
	"vendorDivisionCurrency": "",
	"vendorDivisionNotifyType": "S",
	"vendorDivisionEmail": "",
	"vendorDivisionFax": "",
	"vendorDivisionFaxAlt": "",
	"vendorDivisionRateCopy": 0,
	"vendorDivisionHideExtranet": 0,
	"special_best_daily_rate": 1,
	"special_compound_rates": 0,
	"set_specials": 0,
	"set_charges": 0,
	"vendorDivisionActive": 1,
	"vendorDivisionCreated": "2016-12-20 12:13:30",
	"vendorDivisionSetSimpleRates": "N",
	"vendorDivisionBookingURL": null,
	"vendorDivisionBookingPhone": null,
	"listing": [{
		"vendorListingID": 3,
		"vendorListingBuildingID": 1026,
		"vendorListingUnitTypeID": 1,
		"vendorListingDivisionID": 1230,
		"vendorListingCheckinID": 7,
		"vendorListingGroupID": 0,
		"vendorListingExtra": "sdasda",
		"vendorListingExtra2": "",
		"vendorListingDesc": "dashiduhasio",
		"vendorListingOcc": 2,
		"vendorListingMaxOcc": 4,
		"vendorListingBeds": "King Bed, Queen Bed",
		"vendorListingBath": 2,
		"vendorListingSqft": 100,
		"vendorListingUnit": 0,
		"vendorListingStatus": -1,
		"vendorListingDecre": 0,
		"vendorListingFRS": "",
		"vendorListingUnitNum": "",
		"vendorListingBlockID": 0,
		"vendorListingBlockDays": 0,
		"vendorListingPackage": 0,
		"vendorListingSecretSaver": 0,
		"vendorListingMapListingID": 0,
		"vendorListingPrepaid": 0,
		"vendorListingActive": 1,
		"vendorListingCreated": "2016-12-20 22:38:58",
		"vendorListingHousekeepingStatus": 1,
		"building": {
			"buildingID": 1026,
			"buildingName": "El Salvador",
			"buildingDesc": "",
			"buildingTypeID": 1,
			"buildingAddress": "Test",
			"buildingRegionID": 201,
			"buildingCityID": "91",
			"buildingStateID": "664",
			"buildingCountryID": "38",
			"buildingZipCode": "V5N 2P9",
			"buildingCreated": "2016-12-20 20:04:29",
			"region": {
				"regionID": 201,
				"regionName": "Downtown",
				"regionAbr": "",
				"regionDesc": "",
				"regionCityID": 91,
				"regionCreated": "2016-12-01 00:10:18"
			},
			"city": {
				"cityID": 91,
				"cityStateID": 664,
				"cityName": "Vancouver",
				"cityDesc": "",
				"cityCreatedBy": 0,
				"cityCreated": "2016-12-01 00:17:08"
			},
			"country": {
				"countryID": 38,
				"countryAbr": "CA",
				"countryName": "Canada",
				"countryCurrencyID": 0
			},
			"style": {
				"buildingTypeD": 1,
				"buildingTypeName": "Hotel",
				"buildingTypeActive": 1
			}
		}
	}]
}]

Abraços

Compartilhar este post


Link para o post
Compartilhar em outros sites

Antes de mais nada obrigado pela resposta Williams e feliz natal pra ti ;)

Pois é como eu falei ali em cima.

Eu já utilizo a parte de relacionamento fazendo hasMany e belongs to e assim vai... só dessa maneira eu conseguiria tal loop funcionando rs.

Mas a minha questão é realmente performance... esse é o melhor jeito?

Pq se eu não tivesse utilizando laravel eu teria que fazer um select com joins de todas as tabelas trazendo os dados nulos e checar se os mesmos são nulos ou não para poder fazer tal loop.

Eu tenho pouco contato com o laravel é a primeira vez que utilizo ele num projeto mesmo, antes só utilizei para aprender a mexer nele e tals.

Minha questão realmente é a melhor prática nesse caso.

Se a melhor for relacional já utilizo :D

Obrigado pela opinião ;)

Quem mais tiver opiniões, serão bem vindas!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Igualmente e foi mals ae, não tinha compreendido o primeiro post, ficou meio confuso. No segundo entendi, bom cara se está tudo certo com as FKs, o que vem a otimizar a consulta, é como estás sendo criados os índices no banco, se vai ser desc ou asc nos filtros. Digo que tem gente que cria só as FKs, mas esquece dos índices de otimização.


Pesquise por Tuning + nome do banco que esta sendo usado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por Frank K Hosaka
      Ontem de madrugada encontrei essa dica javascript - How do I get the value of the selected item in a datalist using pure JS? - Stack Overflow e com ele eu consegui terminar o meu código de paginação. O Laravel já tem um código pronto para ser usado, mas ele é funcional para uma tabela com 150 itens, o meu tem mais de 1500 itens, isso iria entupir a apresentação com um monte de guias. O meu só tem duas guias, o próximo e o anterior. E só lista 10 itens de cada vez.
       
      O mais bacana dessa madrugada é que eu aprendi a usar um pouco mais a  função console.log( ) do JavaScript, procurei exaustivamente uma maneira de obter o número do item da option do datalist, mas foi em vão. A dica que eu encontrei na internet é muito engenhosa, o rapaz encontrou no JavaScript uma função que procura um atributo da option que foi selecionada. Como o option não tem a opção de index, ele sugere criar uma.

      No Controller eu havia pedido para o Laravel trabalhar com os produtos em ordem alfabética, ou seja, a própria consulta já é um index. O único problema foi encontrar um jeito de colocar o index da consulta no option do datalist.

      Com quase tudo resolvido, o problema é fazer o loop do JavaScript funcionar. Graças ao fórum iMasters ou Script Brasil eu consegui uma ajuda. Eu recebi a sugestão de garantir que uma das variáveis dentro do loop do JavaScript seja do tipo inteiro. Eu achei a sugestão um absurdo, mas depois eu lembrei que o mundo dos computadores é bem diferente das abstrações que a gente inventou como os números inteiros e os números reais.
       
      Finalmente, aqui está o código. Ele foi escrito em Blade PHP, não é muito diferente do PHP: a diferença é que ele usa @ ao invés do tradicional <?php >. Nesse projeto pretendo trabalhar com o Bootstrap. Já o class="w600" não é Bootstrap, e sim uma gambiarra que eu fiz onde .w600 {width=600px}. Na imagem que eu deixei, dá para ver que eu ajuntei o nome do produto junto com o código dele, a minha ideia é para o usuário procurar o produto tanto pelo nome bem como pelo código. O datalist é muito bacana, pena que não dá para alterar a fonte e nem fazer a busca semelhante, ou seja, se você digitar "limão", ele não lista se foi cadastrado "limao".

       
      @include('menu') <script> var icontrole document.title='Produto';btmenu.innerHTML='Procurar produto por nome' function controle(comando){ if(comando=="proximo"){ if(icontrole<produtos.options.length){icontrole+=10;show(icontrole)}} if(comando=="anterior"){ if(icontrole>9){icontrole-=10;show(icontrole)}}} function lista(input){ option=Array.prototype.find.call(produto.list.options,function(option){ return option.value === input}) show(option.getAttribute("id"))} function show(j){ j=parseInt(j) divshow.innerHTML="" for(i=j;i<=j+9;i++){ divshow.innerHTML+=produtos.options[i].value+"<br>"} produto.value="" icontrole=j} </script> <div class="w600 m-auto"> <input list=produtos autofocus id=produto onchange=lista(value)> <datalist id=produtos> @foreach($prod as $key=> $pr) <option id={{$key}}>{{$pr->prod}} [{{$pr->codprod}}] @endforeach </datalist></div> <div class="w600 m-auto" id=divshow></div> @if(empty($show)) <script>show(0)</script> @php $show="já começou" @endphp @endif <div class="w600 m-auto"> <input type=submit value=Anterior onclick="controle('anterior')"> <input type=submit value=Próximo onclick="controle('proximo')"> </div>  

    • Por ckcesar
      Pesoal  eu instalei o Laravel em meu pc, mais ao rodar estou enfrentando um erro de permissão. 
      Eu segui os passas da documentação => https://laravel.com/docs/9.x#getting-started-on-windows
       
      Ao entrar no localhost ele retorna esse erro. A lembrando que no docker ele inicial certinho o mysql roda ok, é somente essa pasta storege. Estou tentando resolver mais tudo que eu faço não funfa, estou dando permissão nas pastas, já mudei o arquivo .env e nada.
       
      The stream or file "/var/www/html/storage/logs/laravel.log" could not be opened in append mode: Failed to open stream: Permission denied The exception occurred while attempting to log: The stream or file "/var/www/html/storage/logs/laravel.log" 
       

    • Por joeythai
      Boa tarde pessoal,
       
      Eu tenho um foreach que está me trazendo apenas um resultado a partir de uma consulta, mas na verdade tem que me retornar 10 itens:
      <code>
      public function getBillsUnpaid($date)
      {
      $results = [];
      $numberBills = $this->lotModel->select(DB::RAW("
      Lotes.ID AS Lote_ID,
      Compradores.ID as Comprador_ID,
      Compradores.CompradorWeb_ID,
      Compradores.NM as NM_Comprador,
      Lotes.Leilao_ID as Leilao_ID,
      Lotes.NU as NU_Lote,
      FORMAT(lotes.DT_VenctoBoleto, 'yyyy-MM-dd') as DT_VenctoBoleto,
      REPLACE(
      (CASE
      WHEN
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_DDDCel,'')))) > 0 AND
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_Celular,'')))) > 0
      THEN CONCAT(
      LTRIM(RTRIM(Compradores.NM_DDDCel)),'',
      LTRIM(RTRIM(Compradores.NM_Celular))
      )
      WHEN
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_DDDTel,'')))) > 0 AND
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_Telefone,'')))) > 0
      THEN CONCAT(
      LTRIM(RTRIM(Compradores.NM_DDDTel)),'',
      LTRIM(RTRIM(Compradores.NM_Telefone))
      )
      ELSE ''
      END)
      ,'-', '') AS NM_Celular,
      Lotes.VL_Venda,
      ISNULL(Lotes.VL_Cobranca, 0) as VL_Cobranca,
      ISNULL((
      SELECT SUM(VL_Cobertura)
      FROM LotesXPagamentos
      WHERE Lote_ID = lotes.ID
      AND Pagamento_ID IS NOT NULL
      ), 0) as VL_Pago,
      CONCAT(Lotes.NM_Descricao, '', Lotes.MM_ExtDescricao) as NM_Descricao
      "))
      ->join('Leiloes', 'Leiloes.ID', '=', 'Lotes.Leilao_ID')
      ->join('Compradores', 'Compradores.ID', '=', 'Lotes.Comprador_ID')
      ->where('Lotes.ST_Lote', 3)
      ->where('Lotes.DT_VenctoBoleto', '>', '2021-03-01')
      ->whereRaw("
      ISNULL((
      SELECT SUM(VL_Cobertura)
      FROM LotesXPagamentos
      WHERE Lote_ID = Lotes.ID
      AND Pagamento_ID IS NOT NULL
      ), 0) = 0")
      ->orderBy('Lotes.NU')
      ->take(10)
      ->get();
      if(count($numberBills) > 0){
      foreach($numberBills as $bills){
      $results['CompradorWeb_ID'] = $bills->CompradorWeb_ID;
      $results['DT_VenctoBoleto'] = $bills->DT_VenctoBoleto;
      $results['VL_Cobranca'] = $bills->VL_Cobranca;
      $results['Lote_ID'] = $bills->Lote_ID;
      $results['Comprador_ID'] = $bills->Comprador_ID;
      $results['NM_Comprador'] = $bills->NM_Comprador;
      $results['NM_Descricao'] = $bills->NM_Descricao;
      $results['VL_Pago'] = $bills->VL_Pago;
      $results['NU_Lote'] = $bills->NU_Lote;
      $results['Leilao_ID'] = $bills->Leilao_ID;
      $phones = $this->getPhoneUsers($bills->CompradorWeb_ID);
      $results['NM_Celular'] = (!is_null(@$phones->fone_celular)) ? $phones->fone_celular : $bills->NM_Celular;
      return $results;
      }
      }
      }
      </code>
       
      Se eu retorno somente a variavel $numberBills, ele me traz o resultado certinho, porém, eu não posso retornar essa variavel pq preciso pegar o resultado dela e chamar a minha outra função que faz conexão com outra base de dados e por isso eu criei esse array result, percebam que o numero do telefone vai vir da minha tabela A(função que pega o telefone) e caso não tenha o telefone nela, eu pego o numero da tabela B(resultado dessa query) porem qdo do return $results, so me retorna o primeiro registro, o que estou fazendo de errado ?
    • Por joeythai
      Boa tarde pessoal,
       
      Eu tenho um foreach que está me trazendo apenas um resultado a partir de uma consulta, mas na verdade tem que me retornar 10 itens:
      <code>
      public function getBillsUnpaid($date)
      {
      $results = [];
      $numberBills = $this->lotModel->select(DB::RAW("
      Lotes.ID AS Lote_ID,
      Compradores.ID as Comprador_ID,
      Compradores.CompradorWeb_ID,
      Compradores.NM as NM_Comprador,
      Lotes.Leilao_ID as Leilao_ID,
      Lotes.NU as NU_Lote,
      FORMAT(lotes.DT_VenctoBoleto, 'yyyy-MM-dd') as DT_VenctoBoleto,
      REPLACE(
      (CASE
      WHEN
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_DDDCel,'')))) > 0 AND
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_Celular,'')))) > 0
      THEN CONCAT(
      LTRIM(RTRIM(Compradores.NM_DDDCel)),'',
      LTRIM(RTRIM(Compradores.NM_Celular))
      )
      WHEN
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_DDDTel,'')))) > 0 AND
      LEN(LTRIM(RTRIM(ISNULL(Compradores.NM_Telefone,'')))) > 0
      THEN CONCAT(
      LTRIM(RTRIM(Compradores.NM_DDDTel)),'',
      LTRIM(RTRIM(Compradores.NM_Telefone))
      )
      ELSE ''
      END)
      ,'-', '') AS NM_Celular,
      Lotes.VL_Venda,
      ISNULL(Lotes.VL_Cobranca, 0) as VL_Cobranca,
      ISNULL((
      SELECT SUM(VL_Cobertura)
      FROM LotesXPagamentos
      WHERE Lote_ID = lotes.ID
      AND Pagamento_ID IS NOT NULL
      ), 0) as VL_Pago,
      CONCAT(Lotes.NM_Descricao, '', Lotes.MM_ExtDescricao) as NM_Descricao
      "))
      ->join('Leiloes', 'Leiloes.ID', '=', 'Lotes.Leilao_ID')
      ->join('Compradores', 'Compradores.ID', '=', 'Lotes.Comprador_ID')
      ->where('Lotes.ST_Lote', 3)
      ->where('Lotes.DT_VenctoBoleto', '>', '2021-03-01')
      ->whereRaw("
      ISNULL((
      SELECT SUM(VL_Cobertura)
      FROM LotesXPagamentos
      WHERE Lote_ID = Lotes.ID
      AND Pagamento_ID IS NOT NULL
      ), 0) = 0")
      ->orderBy('Lotes.NU')
      ->take(10)
      ->get();
      if(count($numberBills) > 0){
      foreach($numberBills as $bills){
      $results['CompradorWeb_ID'] = $bills->CompradorWeb_ID;
      $results['DT_VenctoBoleto'] = $bills->DT_VenctoBoleto;
      $results['VL_Cobranca'] = $bills->VL_Cobranca;
      $results['Lote_ID'] = $bills->Lote_ID;
      $results['Comprador_ID'] = $bills->Comprador_ID;
      $results['NM_Comprador'] = $bills->NM_Comprador;
      $results['NM_Descricao'] = $bills->NM_Descricao;
      $results['VL_Pago'] = $bills->VL_Pago;
      $results['NU_Lote'] = $bills->NU_Lote;
      $results['Leilao_ID'] = $bills->Leilao_ID;
      $phones = $this->getPhoneUsers($bills->CompradorWeb_ID);
      $results['NM_Celular'] = (!is_null(@$phones->fone_celular)) ? $phones->fone_celular : $bills->NM_Celular;
      return $results;
      }
      }
      }
      </code>
       
      Se eu retorno somente a variavel $numberBills, ele me traz o resultado certinho, porém, eu não posso retornar essa variavel pq preciso pegar o resultado dela e chamar a minha outra função que faz conexão com outra base de dados e por isso eu criei esse array result, percebam que o numero do telefone vai vir da minha tabela A(função que pega o telefone) e caso não tenha o telefone nela, eu pego o numero da tabela B(resultado dessa query) porem qdo do return $results, so me retorna o primeiro registro, o que estou fazendo de errado ?
       
    • Por zanoth
      Salve galera,
       
      sou novo no fórum, saudacoes a todos.
       
      Tenho um formulario em blade:
       
      <form action="{{url('request-action')}}" method="post"> Uma rota:
       
      Route::post('request-action', [Controllers\MainController::class, 'validator']);  
      E um Controller, com a funcao:
      public function validator(Request $request) { $data = $request->validate([ 'name' => 'required|max:255', 'email' => 'sometimes|email', 'phone' => 'required|max:255', 'units' => 'required', 'done' => 'required', ]); tap(new Clients($data))->save(); $id = DB::table('clients')->where('email', '=', $request->email); var_dump($id); //DEBUG for($i = 0; $i < $request->units; $i++) { $banch = file(storage_path('tickets.txt')); $len_banch = count($banch); $rand = rand(0, $len_banch-1); $got = $banch[$rand]; unset($banch[$rand]); $file = fopen(storage_path('tickets.txt'), "w"); ftruncate($file, sizeof($banch)); file_put_contents(storage_path('tickets.txt'), $banch); fclose($file); $tickets->token = $got; $tickets->id = $id; $tickets->save(); } fclose($file);*/ return redirect('success'); }  
      Quero que o formulario seja validado e os dados sejam salvos no bd. Nessa funcao instancio dois modelos, um deles levando o valor de um indice automatico do outro. (em $tickets->id = $id;). Em uma pesquisa rapida descobri a classe DB (Illuminate\Support\Facades\DB), mas sem resultado, considerando que esse valor é gerado no ato da interacao com o Postgres (no meu caso).
      Qual seria a melhor de maneira para traze-lo?
       
      Com relacao aos logs, a principio uma inconsistencia relacionada a variavel $id foi retornada pelo debugger, porem agora nem sequer o debugger é chamado, em decorrencia de um loop infinito aparentemente (pagina sendo carregada… etc etc). A que se deve tal comportamento?
       
      Seguindo os exemplos dos corteses, crio esse post. Ja se isso for mentira, obra do diabo ou de alguma sociedade secreta que o serve, que alguem fale agora ou cale-se para sempre, por favor. Estes sxerao castigados, vencida a ilusao da vida.
       
      Uma outra duvida seria em relacao ao real funcionamento da funcao (helper) 'tap', nao encontro documentacoes ou manuais tecnicos em essencia,
       
       
      mas informacoes textuais ou artigos, que facilitam a abstracao.
       
      Valeu desde já.
       
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.