Curso Desenvolvedor Web Completo + 10 de projetos

Curso VIII - Unidade 02 - Aplicando fundamentos de SEO no site

Aula 274 a 275 - Organizando o site / Seis itens de sua página que merecem sua atenção
Algumas ideias sobre como padronizar os arquivos do site de modo a organizar melhor sua estrutura para deploy.
A ideia é colocar todas as páginas auxiliares em diretórios com seu nome e nomear todos os arquivos nos diretórios individuais como index.html. Dessa forma o acesso pela URL se dará apenas pelo 'nome_do_domínio/nome_da_pagina/' sem a necessidade da extensão .html na URL.
Para as pastas de apoio (css, js, images) a sugestão é utilizar um '_'(underscore) no inicio do nome para identificar que esse diretório não é de conteudo.
Itens que devemos ter atenção no desenvolvimento do SEO:
  • URL
  • Title
  • Meta Tag - Description
  • Headers
  • Body Text
  • Images
Para a URL o ideal é criarmos páginas com nomes que sejam amigáveis aos mecanismos de busca, ou seja, nomes dos arquivos '.html' que indiquem o conteudo da melhor forma sem caracteres especiais, utilizando '-' invés de '_' sem espaços e preferencialmente com letras minusculas (ex: como-fazer-camarao-com-catupiry.html).
O title deve indicar a referencia ao conteúdo da página e deve ter a mesma referencia que a tag <h1> da página.
A meta tag - description deve conter a descrição de cada página específica, passando informações sobre o conteúdo daquela parte do site.
Não esquecer de preencher as propriedades alt das imagens.
Aula 276 a 278 - Fazer uma boa navegação / Construindo links dentro do site / Informação sobre localização
Pensar sempre na estrutura do site, e em como o usuário vai navegar pelo conteudo. Manter os site de forma organizada com uma navegação fluida.
Além de definir os links de navegação do site, podemos utilizar links de conteudo. Para links no site, evite utilizar links com texto Clique Aqui ou sememlhantes. Os mecanismos de busca costumam evitar esse tipo de sinalização. Utilizar links com textos que façam referencia ao conteudo.
Podemos ddefinir a localização de um endereço vinculado a um site utilizando meta tags. Para isso podemos utilizar as seguintes tags:
<meta name='geo.region' content='FR-75' />
<meta name='geo.placename' content='Paris' />
<meta name='geo.position' content='48.844426;2.348085' />
<meta name='ICBM' content='48.844426, 2.348085' />

Para gerarmos as meta-tags de localização podemos utilizar o site Geo-Tag que gera os valores automaticamente.

Curso VIII - Unidade 03 - Contruindo o site map

Aula 279 a 281 - Como criar uma arquivo robots.txt / Construindo XML Sitemaps / Submeter sitemap para Google
O arquivo robots.txt permite selecionar algumas pastas ou outros arquivos para não serem indexadas pelos mecanismos de buscas. Os principais parametros do arquivo robots.txt são:
User-agent que define quais bots vão acessar a página (Googlebot / Bingbot), por padrão setamos com 'User-agent: *' Allow define permissões e Disallow remove permissão. O Disallow geralmente é aplicado para pastas de conteudos que não devem ou não precisam ser indexados (arquivos de estilo, arquivos de js, arquivos restritos, etc). Podemos definir os robots diretamente em uma meta tag:
<meta name:'ROBOTS' content='noindex,nofollow'>
Cuidado para não incluir no robots.txt uma propriedade Disallow: / pois isso remove todas páginas do indexador.
Existem dois tipos de sitemap, um feito para o usuário, para que este se localize no site e outro para o buscador, para facilitar sua indexação.
Podemos incluir o caminho para o sitemap no arquivo robots.txt. Para gerar um arquivo de sitemap podemos utilizar a ferramenta XML-Sitemaps.
Feito isso devemos informar ao Google Search o caminho para nosso arquivo sitemap.xml.

Curso VIII - Unidade 04 - Links

Aula 282 - Importancia de links externos para seu site
O apontamento externo para o link de seu site através de grandes plataformas, outros sites e foruns ajuda a melhorar o ranking de busca no Google. Apontamentos por redes sociais por sua vez não pontuam muito pois geralmente são realizados com uma propriedade rel='nofollow'. Existem extensões no Chrome para aplicações que verificam se um link está setado para nofollow. Fazer troca de apontamentos é detectável e pode rebaixar a posição do site. Para verificar os apontamentos para sua URL podemos utilizar a ferramenta link:nome_do_site no próprio Google ou um site de verificação como o Majestic que permite uma verificação gratuita de seu site.
Para fazer um bom link nas páginas é ideal seguir as seguintes orientações:
  • Link em texto
  • Link com boas palavras chaves (keywords)
  • Link com atributo TITLE
  • Em uma página indexada
  • Em um site relevante
  • Em um site confiável
  • Pontos extras em site .edu ou .gov
  • Em uma página com alto PageRank
  • Em uma página estática, não dinamica
  • Dentro de um parágrafo

Curso IX - Unidade 02 - Instalação do PHP no Windows

Aula 287 - Ativar os serviços essenciais do XAMPP
Iniciando o XAMPP e criando um pequeno arquivo PHP.
O live-server não executa arquivos PHP diretamente, portanto esse arquivo só irá rodar pelo XAMPP

Curso IX - Unidade 07 - Criando variáveis

Aula 298 a 299 - O que são variáveis / Commo criar suas primeiras variáveis
Variáveis em PHP são criadas precedidas por '$' e na prática podem ser declaradas pelo nome diretamente ou precedidas por '_', não podem utilizar caracteres especiais e são case sensitive.
Podemos incluir os códigos PHP dentro do <body> ou mesmo antes da declaração do <!DOCTYPE>.
O código PHP é sempre incluido dentro da seguinte estrutura:
<?php
// instruções
?>
Aula 300 - Variáveis de Strings
Em PHP o sinal para concatenação é o '.' entre os valores a se concatenar.
Aula 301 - Funções de Strings
Algumas funções para manipulação de Strings:
strlen - Retorna a quantidaded de letras
stripos - Retorna a primeira ocorrencia
strripos - Retorna a ultima ocorrencia
strtolower - Converte para letras minusculas
strtoupper - Converte para letras maiusculas
SUBSTR_COUNT substr_count- Conta quantas letras ocorreram em um texto ou string.
Aula 302 - Funções numéricas
Operadores matemáticos:
+ , - , * , / Operadores matemáticos básicos.
pow(y, x): Exponenciação
sqrt(): Raiz quadrada
rand(): Número radomico
rand(x, y): Número randomico no intervalo x , y.
abs(): Valor absoluto.
Aula 303 a 305 - Numeros inteiros e racionais / Testar o tipo de números das variáveis / Arredondar variáveis
Números inteiros ocupam menos espaço na memória que números do tipo float. Dados numéricos como telefone, cep ou cpf geralmente são utilizados como string pois não são necessárias operações matemáticas com eles.
is_numeric(): Testa se o valor é numérico. Retorna '1' se verdadeiro e não retorna nada se false.
is_int(): Testa se o valor é inteiro. Retorna '1' se verdadeiro e não retorna nada se false.
is_float(): Testa se o valor é float. Retorna '1' se verdadeiro e não retorna nada se false.
Não devemos utilizar ' para as declarações em PHP mas sim " pois nos dois casos ele gera um texto porém no primeiro ele não considera as declarações de variáveis e outras operações de programação.
round(): Arredonda pela média.
ceil(): Arredonda para cima.
floor(): Arredonda para baixo.
Aula 306 a 308 - Boolean / NULL / ISSET
Em PHP o case dos booleanos true e false não importa, podendo ser escritos de qualquer forma.
O retorno para true é '1' e para false é ''.
is_bool(): Testa se o valor é booleano.
O valor null é diferente de "", ou seja é diferente de vazio.
is_null(): Verifica se o valor é null.
isset(): Verifica se uma variável está setada. Caso o valor seja null também retornará 'vazio'.

Curso IX - Unidade 08 - Criando Array no PHP

Aula 309 - Introdução ao Array
Declaramos arrays utilizando a função array(). Podemos incluir itens no array declarando o nome do array seguido de [i] onde i é o índice onde desejamos incluir o item. Se utilizarmos apenas [], o valor é incluido no fim do array. Do mesmo modo que no JS o array pode ter vários tipos de dados, mesmo outro array.
Aula 310 - Criando um array na prática
Quando criamos um array não conseguimos imprir seu valor inteiro com o echo, apenas os valores pelos indices. Para imprimir o array inteiro na tela devemos utilizar a função print_r(). Nesse caso a saida é um array em linha. Para vermos o array formatado podemos utilizar a tag <pre> antes da tag de código PHP (<?php ?>)
Aula 311 a 312 - Funções para Array / Pesquisa dentro de um array
sort(): Organiza os dados do array em ordem crescente. Esta função é destrutiva, ou seja, altera em definitivo o indice dos elementos.
max(): Retorna o maior valor de um array.
min(): Retorna o menor valor em um array.
Para ver mais funções de array consultar a documentação em Documentação PHP.
in_array(valor, array): Verifica se existe o valor no array. Esta função é case sensitive. Esta função retorna '1' ou ''.
array_search(valor, array): Verifiva se existe o valor no array e caso positivo retorna a posição do elemento.

Curso IX - Unidade 09 - Ações condicionais

Aula 313 a 314 - Ação condicional / Como funciona o IF e ELSE
Uso do if
if (condição) {
//retorno
}
A estrutura segue o padrão if{ }else if{ }else{ }.
Aula 315 a 316 - Como funciona o SWICTH-CASE / Switch Case
Uso do switch / case
switch (condição) {
case 'verificador1':
//expressão1;
break;
case 'verificador2':
//expressão2;
break;
default:
//expressão;
}
Aula 317 a 318 - Como funciona o operador ternário / Operador ternário na prática
Uso do operador ternário:
variável = (expressão_lógica) ? 'retorno_true' : 'retorno_false';
Aula 319 a 322 - Quais são os operadores lógicos / Operadores lógicos - exercício 1 / Operadores lógicos - exercício 2 / Operadores lógicos - exercício 3
= : atribuição;
== : comparação de igualdade;
=== : comparação de identico;
!= : comparação de não igualdade;
!== : comparação de não identico;
<, <=, > >= : menor / maior;
&& : E lógico;
|| : OU lógico

Curso IX - Unidade 10 - Estruturas de repetição

Aula 324 a 325 - While / Do While
Loops While e Do...While.
Aula 328 - Foreach - Exemplo 1
O loop foreach() percorre arrays verificando cada posição do array independente de tamanho e sem necessidade de contadores, bastando atribuir uma variável(temporária) para o retorno de cada valor.
foreach(nome_array as variável_temporária){
//instruções
}
Podemos utilizar o foreach em arrays associativos (arrays que tem a mesma forma de objetos).
O array associativo tem a seguinte estrutura:
array ( "nome1" => "valor1",
"nome2" => "valor2",
...
"nomeN" => "valorN" );
Nesse caso o foreach vai ser:
foreach($nome_array as $variavel_nome => $variavel_valor){
//instruções
}
Aula 330 - Projeto da Unidade
Foi feito um projeto para sortear 6 números de 1 a 60 com a condição de não repetir nenhum número.
Os números foram incluidos em um array vazio. Utilizamos um loop while() para repetir a lógica por 6 vezes. Para o sorteio utilizou-se a função rand(1, 60). Para o teste lógico que verifica se o número já foi sorteado utilizamos a função in_array(). Essa função verifica se existe determinado elemento no array analisado.

Curso IX - Unidade 11 - Funções

Aula 333 a 335 - Criar funções / Usar parametros / Função de converter temperaturas
A criação de funções em PHP segue a mesma estrutura das demais linguagens:
function nomeDaFuncao() {
//instruções
return
}
Outra função abordada nessa aula foi number_format() para formatar casas decimais de numeros:
number_format(valor, numero_casas_decimais)

Para passar parametros para funções os mesmos devem seguir a mesma sintaxe das variáveis, ou seja devem ser declrados precedidos por '$'.

Curso IX - Unidade 12 - Data e Hora

Aula 336 a 339 - GetDate / Mostrar Hora / Mostrar Hora em Portugues / Mostrar dia da semana em portugues.
A função getdate() retorna um array associativo com diversos valores. Para acessarmos os valores basta atribuir essa função a uma variável e utilizar a função print_r para apresentar os valores. Os valores do array resultante são os seguintes (em ordem):
[seconds] => 25, [minutes] => 42, [hours] => 17, [mday] => 23, [wday] => 2, [mon] => 11, [year] => 2021, [yday] => 326, [weekday] => Tuesday, [month] => November, [0] => 1637700145.
Para utilizarmos os valores de data e hora locais devemos setar algumas propriedades:
date_default_timezone_set('Brazil/East'): configura o timezone para recuperar o valor da hora local.
setlocale(LC_TIME, "portuguese"): configura o local para idioma portugues.
strftime(): define diversas outras configurações de exibição de dados de tempo. Veja documentação em PHP Manual strftime. Entre os parametros mais importantes temos :
strftime("%B"): Mes por extenso na lingua local (de acordo com o setlocale()).
strftime("%A"): Dia da semana por extenso.
Aula 340 - DIFF
A função diff() retorna um array com a diferença de tempo entre um dado de tempo inicial e um dado de tempo final. As variáveis para cálculo devem ser passadas no formato yyyy-mm-dd.
Para executar a função utilizamos a sintaxe:
$_variavel = $_data_inicial->diff($_data_final);

Não foi explicado para que serve o sinal '->'.
Na verdade o retorno é um objeto e o sinal de '->' aponta para o atributo ou métodos do objeto
Baseado na informação que eu deduzi acima, explica-se por que as variáveis de data inicial e data final são instanciadas como new DateTime(). Tanto o diff() quanto o format() são métodos da classe DateTime()
O array de retorno contém os seguintes dados:
[y] => 0, [m] => 10, [d] => 23, [h] => 0, [i] => 0, [s] => 0, [f] => 0, [weekday] => 0, [weekday_behavior] => 0, [first_last_day_of] => 0, [invert] => 0, [days] => 327, [special_type] => 0, [special_amount] => 0, [have_weekday_relative] => 0, [have_special_relative] => 0.
Esses dados são a diferença entre os valores final e inicial.
Podemos recuperar os valores individuais com o seguinte comando:
print_r($_variavel->format('%y'))

onde %y retorna a quantidade de anos, %m meses, %d dias, e %a total de dias do intervalo.

Curso IX - Unidade 13 - Links com parametros

Aula 341 a 343- Links com parametros
Neste módulo vamos indexar links de páginas através de outra página PHP, passando os links com parametros na URL.
Uma vez que passamos o código pela URL par o arquivo de destino recebemos esse valor através do método AJAX $_GET. No nosso exemplo os valores recebidos são números de 0 a 2, que coincidem com o índice de um array criado com os links para as imagens a serem exibidas. Desse modo só precisamos passar o valor recuperado pelo $_GET para uma tag <img> para apresentar a imagem na tela.

Curso IX - Unidade 14 - Formulário

Aula 344 - Resgatar informações do formulário
Neste módulo temos um formulário básico onde a propriedade action="" da tag <form> aponta para um arquivo PHP que fará o processamento das informações. Esta tag possui um método GET que envia os dados captados nas tags <input> através do submit na URL do documento.
Mudamos o método de transmissão dos dados para POST para não enviar via URL. Feito isso o arquivo destino.php pode receber os dados informados no arquivo principal. Esses dados são recebidos em um array com as chaves passadas na propriedade name da tag. Esse array pode ser acessado pela variável $_POST, e cada valor acessado por sua chave.
Aula 345 a 346 - Identificação do recebimento / Identificar operador ternário
Aqui utilizamos a função isset() para verificar se os campos estão preenchidos e caso contrário enviar uma mensagem. O problema é que esse método só verifica se o array enviado está vazio, ou seja se o array for enviado com os campos em branco não há verificação. PAra contornar esse problema fiz uma lógica complementar para preencher o campo caso seu valor também seja nulo.
Na sequencia utilizamos o operador ternário para simplificar a lógica do if...else anterior.
Para instalação precisamos do MySQL e do MySQL Workbench. Outro aplicativo sugerido é o Navicat, entretanto essa aplicação é paga. Utilizar o MySQL é mais recomendado que o MariaDB que vem por padrão no XAMPP.
Aula 347 - Form - single page
Nesta aula passamos os dados da página destino para a página do formulário de modo a concentrar a resposta na mesma página que o formulário, e fazendo o teste lógico no botão de submit.

Curso X - Unidade 02 - Introdução a Banco de Dados

Aula 350 a 351 - Estrutura de um banco de dados / Comandos do SQL
SQL é a sigla para Structured Query Language ou Linguagem de Consulta Estruturada. Ela interage com a maioria dos bancos de dados relacionais (MySQL, Oracle e MSSQL).
Bancos de dados são compostos por tabelas. Uma tabela tem estrutura semelhante a uma planilha. As colunas representam os itens do banco de dados e as linhas representam os dados.
Comandos de SQL:
Comandos de Consulta
SELECT: seleciona as colunas que participam da consulta.
FROM: seleciona a(s) tabela(s) que faz(em) parte da consulta.
WHERE: Especifica filtros e condições da consulta.
GOUP BY: Agrupar conjunto de dados.
HAVING: Expressa condição que deve satisfazer cada grupo.
ORDER BY: Ordena os registros por uma sequencia determinada.
DISTINCT: Utilizada para mostrar dados sem repetição.
Operações básicas
INSERT: Insere um novo registro ao banco de dados.
UPDATE: Altera dados.
DELETE: Remove dados.
Operações lógicas
AND: "E" lógico.
OR: "OU" lógico.
NOT: Negação lógica. Retorna o inverso da operação.
Operadores relacionais
< >=: Menor, menor ou igual.
>, >=: Maior, maior ou igual.
=: igual.
<>: diferente.
Funções de agregação
AVG: retorna o cálculo da média dos valores de uma coluna.
COUNT: retorna a soma de itens em uma coluna.
SUM: retorna a soma dos valores de uma coluna.
MAX: retorna o valor máximo de uma coluna.
MIN: retorna o valor mínimo de uma coluna.

Curso X - Unidade 03 - Criando consultas

Aula 362 a 366 - Consulta ao banco de dados / SELECT com multiplas / Como ordenar numero de linhas / Limitar o numero de linhas / Como retornar valores unicos com DISTINCT
Os procedimentos a seguir são executados no MySQL Workbench.
Para ativar um banco de dados no Workbench devemos selecionar o banco desejado com o botão direito do mouse e selecionar a opção Set as Default Schema para definir qual o banco em operação.
Para fazer uma consulta de dados em uma tabela utilizamos o comando:
SELECT nome_da_coluna FROM nome_da_tabela

Podemos fazer seleções de mais de uma coluna com o comando:
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela

Para ordenar a saida de dados basta acrescentar a consulta ORDER BY. Por padrão a ordem é ASC ascendente. Para ordenar de forma inversa utilizamos o DESC (descendente).
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN
FROM nome_da_tabela ORDER BY nome_da_coluna DESC

Podemos aplicar mais de um item para ordenação, sendo que a classificação será sempre na ordem que as colunas forem declaradas.
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela ORDER BY nome_da_coluna DESC, nome_da_coluna ASC

Podemos limitar a quantidade de linhas a serem retornadas com o comando LIMIT
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela ORDER BY nome_da_coluna DESC, nome_da_coluna ASC LIMIT numero

Podemos selecionar apenas os valores únicos na tabela com o comando DISTINCT após o comando SELECT. Assim teremos como retorno apenas os valores únicos na tabela.

Curso X - Unidade 04 - Criar filtros

Aula 367 a 370 - Criando filtros / Criando um filtro entre intervalos / Criando um filtro usando o IN / Criando um filtro com LIKE
Para filtrar o retorno de uma consulta por determinado valor podemos acrescentar à consulta o comando WHERE determinando qual coluna deve ser verificada e o valor esperado.
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela WHERE nome_da_coluna = valor_desejado

Podemos utilizar na seleção os operadores relacionais e operadores lógicos:
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela WHERE nome_da_coluna = valor_desejado AND nome_da_coluna > valor_desejado

Podemos selecionar intervalos com o comando BETWEEN:
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela WHERE nome_da_coluna BETWEEN valor_inicial AND valor_final

Para filtrar diversos valores específicos de modo mais performático que fazer o filtro utilizando vários operadores OR podemos utiliza o comando IN passando os valores desejados entre parenteses.
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela WHERE nome_da_coluna IN (valor_desejado, valor_desejado,...valor_desejado)

Para fazer a seleção inversa basta incluir a palavra NOT.
Para filtros de valores que contenham determinada expressão utilizamos o comando LIKE seguido do valor buscado entre ''. Para essa operação podemos utilizar como coringa o caractere '%':
SELECT nome_da_coluna1, nome_da_coluna2,...nome_da_colunaN FROM nome_da_tabela WHERE nome_da_coluna LIKE '%valor_busca%'

Curso X - Unidade 05 - Funções do MySQL

Aula 371 a 375 - Funções de MIN, MAX e AVG / Função de SUM / Função de COUNT / Uso do GROUP BY / Uso do HAVING
Podemos utilizar algumas funções para retornar valores mínimos, máximos e médio de uma coluna.
MIN seleciona o menor valor de uma coluna:
SELECT MIN(nome_da_coluna) AS nome_de_retorno FROM nome_da_tabela

O valor de nome_de_retorno pode ser qualquer nome que identifique os dados de retorno. Caso não seja passado nenhum valor o nome do campo será FUNCAO(selecao) Para nomes compostos devemos utilizar "" (por exemplo "Preco Minimo").
A mesma sintaxe pode ser utilizada para as funções MAX (valor máximo) e AVG (média calculada entre todos os valores da coluna).
A função SUM soma os valores de determinada coluna. Podemos utilizar esse comando combinado com filtros como no exemplo:
SELECT SUM(nome_da_coluna) AS nome_de_retorno FROM nome_da_tabela WHERE YEAR(data) = 'valor_do_filtro'

Neste exemplo selecionamos o ano em um campo de data para o filtro.
A função COUNT conta o numero de elementos em uma coluna. Para essa seleção podemos utilizar como contador qualquer coluna, bastando selecionar a coluna desejada para o filtro.
SELECT COUNT(nome_da_coluna) AS nome_de_retorno FROM nome_da_tabela WHERE nome_da_coluna = 'valor_do_filtro'

A função GROUP BY determina de que modo os dados devem ser agrupados, ou seja, qual o item em que devemos agrupar o retorno. A seguir um exemplo que eu montei com agrupamento pelos campos de data:
SELECT data_pedido, COUNT(pedidoID) as totalpedidos FROM pedidos WHERE YEAR(data_pedido) = '2007' AND MONTH(data_pedido) BETWEEN 1 AND 5 GROUP BY DAY(data_pedido)

A função HAVING possisbilita a criação de filtros baseados em resultados de funções, diferente do WHERE. Desse modo quando criamos uma função do tipo SUM ou COUNT e queremos que o filtro recupere valores baseados no valor retornado por essa função devemos utilizar o HAVING.
SELECT status_pedido, SUM(valor_pedido) as SOMA FROM pedidos GROUP BY status_pedido HAVING SOMA >= 6000

Entretanto como o HAVING é executado após o ORDER BY a execução é mais lenta do que com o WHERE que é executado antes do ORDER BY e desse modo filtra e reduz os dados diminuido a quantidade de dados a serem processados.

Curso X - Unidade 06 - Relacionamento entre tabelas

Aula 376 a 384 - Relacionamento entre tabelas / Relacionar tabelas com WHERE / Relacionar tabelas com INNER JOIN / Solução do desafio do exercício anterior / Relacionar 3 tabelas / Relacionamento com agrupamento / Relacionamento com LEFT JOIN / Relacionamento por agrupamento e HAVING / Relacionamento entre tabelas avançado
Podemos realcionar diversas tabelas através de elementos em comum que serão IDs ou chaves relacionando umas as outras.
Podemos fazer o relacionamento entre as tabelas selecionando os dados que queremos cruzar, indicando as tabelas a serem consultadas e indicando qual a chave comum entre elas com o comando WHERE.
SELECT coluna_tabelaA, coluna_tabelaB FROM tabelaA, tabelaB WHERE tabelaA.chave_comum = tabelaB.chave_comum

Entretanto a utilização do WHERE não é indicada para fazer essa operação mas sim para filtros. O comando mais indicado para essa operação é o INNER JOIN. Nesse caso a sintaxe é a seguinte:
SELECT coluna_tabelaA, coluna_tabelaB FROM tabelaA INNER JOIN tabelaB ON tabelaA.chave_comum = tabelaB.chave_comum

Podemos facilitar os endereçamentos dos itens criando alias(apelidos) para elas de modo a facilitar a sua indicação. Para isso basta utilizar o comando AS e em seguida o alias.
Em seguida fiz o relacionamento entre tres tabelas com ordenação.
SELECT nomeproduto,nomecategoria,nomefornecedor
FROM produtos AS p
INNER JOIN categorias AS c ON p.categoriaID = c.categoriaID
INNER JOIN fornecedores AS f ON p.fornecedorID = f.fornecedorID
ORDER BY nomecategoria ASC

Quando queremos fazer um agrupamento utilizando uma chave presente em duas tabelas devemos definir apenas uma chave para o agrupamento, desse modo quando chamamos o comando GROUP BY devemos definir uma das tabelas como agrupador determinando seu prefixo (nome da tabela ou alias).
SELECT nomecategoria, COUNT(produtoID) AS total
FROM produtos AS p
INNER JOIN categorias AS c ON p.categoriaID = c.categoriaID
GROUP BY c.categoriaID

A consulta com agrupamento utilizando o INNER JOIN entretanto apenas retorna os dados que tiverem algum valor (calculado pelo COUNT). Para recuperar todas as ocorrencias devemos utilizar o INNER JOIN. Esse comando irá retornar todos os valores da tabela, mesmo o que não tiverem valores de ocorrencia.
SELECT nomecompleto, COUNT(pedidoID) AS total
FROM clientes AS c LEFT JOIN pedidos AS p ON c.clienteID = p.clienteID
GROUP BY c.clienteID
ORDER BY total DESC

Podemos mesclar os comandos de agrupamento com os de soma e filtro:
SELECT nomestatus, SUM(valor_pedido) AS total
FROM pedidos AS p INNER JOIN pedidos_status AS s ON p.status_pedido = s.statusID
GROUP BY p.status_pedido
HAVING total >= 6000

Por fim fizemos um filtro com tres tabelas buscando vários valores de uma tabela.
SELECT DISTINCT nomecompleto,telefone,email
FROM clientes c INNER JOIN pedidos p ON c.clienteID = p.clienteID
INNER JOIN pedidos_item i ON i.pedidoID = p.pedidoID
WHERE i.produtoID = 2

Note que não precisamos utilizar o AS para criar alias, embora eu entenda que fica mais organizado e fácil de visualizar.

Curso X - Unidade 07 - Insert, Update e Delete

Aula 385 - Inserção de um novo registro
Para inserir valores em uma tabela utilizamos o comando INSERT INTO combinado com o comando VALUES.
INSERT INTO estados(nome,sigla) VALUES ('Victor', 'VI')

Para alteração de dados utilizamos o comando UPDATE combinando com o comando SET
UPDATE estados SET nome = 'Matheus', sigla = 'MH'
WHERE estadoID = 32

Para remover registros utilizamos o comando DELETE FROM selecionando o registro com o filtro WHERE
DELETE FROM estados
WHERE estadoID = 32

Atenção para a utilização da palavra chave WHERE nas seleções de UPDATE e DELETE. Caso não seja selecionado o índice através do WHERE "TODO O BANCO DE DADOS SERÁ ALTERADO"

Curso X - Unidade 08 - Criar um novo banco de dados

Aula 388 - Criar um novo banco de dados
Para criar um novo Banco de Dados precisamos primeiramente conhecer os tipos de dados que são NUMERIC, DATE AND TIME e STRING:
NUMERIC podem ser INTEGER e DECIMAL que por sua vez são classificados em:
INTEGER: INTEGER, TINYINT, SMALLINT, MEDIUMINT, INT e BIGINT.
DECIMAL: DECIMAL.
Type Armazenagem(bytes) Valor Mínimo Valor Máximo Capacidade Máxima
TINYINT 1 -128 127 255
SMALLINT 2 -32768 32767 65535
MEDIUMINT 3 -838608 838607 16777215
INT 4 -2147483648 2147483647 4294967295
BIGINT 8 -263 263 264-1
Os numeros do tipo DECIMAL permitem até 65 dígitos. A notação para numeros decimais é (digitos, casas decimais).
DATE AND TIME podem ser:
DATE - "0000-00-00"
TIME - "00:00:00"
DATETIME * - "0000-00-00 00:00:00"
TIMESTAMP * - "0000-00-00 00:00:00"
YEAR - 0000 (valor numérico)
*O DATETIME serve para armazenar datas, já o TIMESTAMP faz um carimbo digital de determinada ação. Uma das diferenças entre eles é a abrangencia de valores. O DATETIME permite armazenar datas de 1000-01-01 a 9999-12-31 e utiliza 4 bytes. Já o TIMESTAMP é baseado no contador Unix Timestamp ou Posix Time, vai de 1970-01-01 a 2038-01-09 e requer 8 bytes.
STRING pode ser do tipo CHAR e VARCHAR.
A diferença entre eles é que enquanto o CHAR ocupa o espaço total definido na quantidade de caracteres o VARCHAR apenas armazena a quantidade de caracteres armazenada mais 1 byte. desse modo se temos definidos os campos CHAR(4) e VARCHAR(4) no primeiro teremos o uso de 4 bytes independente de quantos caracteres tivermos armazenados. Já o segundo vai gastar apenas os dados efetivamente armazenados acrescido de 1 byte.
Aula 389 - Criar uma nova tabela
Podemos criar um novo banco de dados pelo Workbench clicando em Schemas e selecionando a opção Create Schema1 ou através da linha de comando digitando CREATE SCHEMA 'nome_do_BD. Feito isso já temos a estrutura do SQL pronta e podemos inicar a criação de tabelas.
Criamos a seguir uma tabela para o banco de dados agenda. Essa tabela tem o nome de 'contatos' e foi criada no Workbench. Em linha de comando a criação ficaria da seguinte forma:
CREATE TABLE `agenda`.`contatos` (
`contatoID` INT NOT NULL AUTO_INCREMENT,
`nome` VARCHAR(255) NOT NULL,
`telefone` VARCHAR(20) NULL,
`email` VARCHAR(100) NULL,
`data_nascto` DATE NULL,
`salario` DECIMAL(10,2) NULL,
`nota` BLOB(255) NULL,
PRIMARY KEY (`contatoID`));

Note que os campos contatoID e nome são definidos como NOT NULL e que ao final definimos como PRIMARY KEY o campo contatoID.

Curso X - Unidade 09 - Dicas Extras

Aula 393 - Uso do GetTimeOfDay do PHP
Quando queremos definir um tempo de timestamp bastante preciso podemos através do PHP utilizar uma função chamada gettimeofday(). Essa função além do timestamp no padrão Unix Timestamp também retorna um valor que retorna o tempo em milisegundos, tornando o marco de tempo bem mais preciso.

Curso XI - Unidade 03 - API's conexão

Aula 403 - Conhecer API's de conexão
No PHP temos 3 API's para conexão do MySQL com o PHP: MySQL, MySQLi e PDO.
MySQL: API original do MySQL para PHP, iniciou na versão 2.0, programação procedural;
MySQLi: API melhorada (improved), iniciou na versão 5.0, programação procedural;
PDO: PHP Data Object (permite a conexão de outros DBs, não apenas o MySQL), iniciou na versão 5.5, programação não procedural;
Algumas funções pré-definidas da API MySQL: mysqli_connect, mysqli_connect_errno, mysqli_connect_error, mysqli_free_result, mysqli_query, mysqli_fetch_assoc, mysqli_fetch_lengths e mysqli_close.
Aula 404 - Como criar uma conexão com MySQL
Para criar a conexão com o MySQL primeiramente criamos as variáveis para definir os dados de acesso ao BD. Devemos definir o nome de servidor, nome do usuário, senha do usuário e nome do banco.
Em seguida criamos uma variável para a conexão que irá inicia-la. Essa variável utiliza a função mysqli_connect.
$variavel_conexao = mysqli_connect($servidor, $usuario, $senha, $banco);

Devemos a seguir testar a conexão e em caso de erro encerrar a execução do PHP:
if (mysqli_connect_errno()) {
die("Conexão falhou: " . mysqli_connect_errno());
}

No final do arquivo devemos fechar a conexão com o comando:
mysqli_close($variavel_conexao);

Alguns erros forçados apresentaram os seguinte códigos de erro:
2002: erro no nome do servidor;
1049: erro no nome do banco de dados;
1045: erro no nome de usuário ou senha;
Aula 405 a 406 - Criar uma consulta a uma tabela / Fazer listagem de dados
Feita a conexão com o BD podemos criar as querys. Para isso criamos variáveis no formato utilizado pelo SQL:
$consulta_produtos = 'SELECT nomeproduto, precounitario, tempoentrega FROM produtos;';
Note que podemos criar as querrys com concatenação dos valores e aparentemente não é necessário o ';' no final da query:
$consulta_produtos = 'SELECT nomeproduto, precounitario, tempoentrega ';
$consulta_produtos .= ' FROM produtos ';

Em seguida atribuimos a uma variável a consulta através das variáveis de conexão e da query com a função mysqli_query(). Devemos tratar possíveis erros neste caso também:
$produtos = mysqli_query($conecta, $consulta_produtos);

if (!$produtos) {
die("Falha na consulta ao banco de dados");
}
Para mostrar os dados com o PHP utilizamos as funções de FETCH do mysqli. As opções são:
mysqli_fetch_row: Mostra os dados em linha com o [indice do array] => valor.
Array ( [0] => Biscottis [1] => 20.00 [2] => 15 )
mysqli_fetch_array: Mostra os dados na forma de linha com o [indice do array] => valor, [nome do campo] => valor de modo que repete os dados.
Array ( [0] => Biscottis [Produto] => Biscottis [1] => 20.00 [Preco Unitário] => 20.00 [2] => 15 [Tempo de Entrega] => 15 )
mysqli_fetch_assoc: Mostra os dados em linha de modo associativo, associando [nome da coluna] => valor.
Array ( [Produto] => Biscottis [Preco Unitário] => 20.00 [Tempo de Entrega] => 15 )
Temos ainda o:
mysqli_fetch_object: Mostra os dados da mesma forma que o mysqli_fetch_assoc stdClass Object ( [Produto] => Biscottis [Preco Unitário] => 20.00 [Tempo de Entrega] => 15 )
Nos meus testes fiz primeiramente um foreach para separar os dados recuperados com o mysqli_fetch_assoc ou mysqli_fetch_object. Alterei os nomes das colunas na projeção do SELECT utilizando o ALIAS. Por fim fiz a apresentação dos dados em linha com separadores e depois em uma tabela HTML.
Aula 407 a 408 - Mostrar os dados dentro de um elemento / Liberar espaço da consulta lista
Outro modo de fazer a apresentação de dados com o PHP (diferente do que eu fiz onde coloquei todo o HTML sendo criado no PHP) é dividindo as tagas do PHP de acordo com a necessidade de dados a serem processados:
<body>
<ol>
<?php
while ($dados = mysqli_fetch_assoc($produtos)) {
?>
<li><?php echo $dados['nomeproduto'] ?></li>
<?php
}
?>
</ol>
</body>

Após a consulta feita é importante limparmos os dados da memória. Para isso utilizamos a função mysqli_free_result().
Apesar disso fiquei em dúvida com uma coisa. Depois que fazemos o fetch nos dados se verificarmos a variável ela apresenta o mesmo resultado:
mysqli_result Object ( [current_field] => 0 [field_count] => 3 [lengths] => [num_rows] => 22 [type] => 0 )
Entretanto se tentamos percorrer a variável original da pesquisa novamente com o loop while não temos nenhum resultado. Não sei se o fetch é destrutivo em relação ao array mas os valores permanecem na memória mas não ficam acessíveis em uma nova pesquisa.
Aula 409 - Include e Include_once
Podemos importar arquivos com as funções include() e include_once(). A diferença entre elas é que a primeira permite que façamos quantas inclusões quisermos enquanto a segunda só aceita uma inclusão (mesmo que o arquivo tenha sido incluido a primeira vez com o include() caso tentemos incluir novamente com include_once() ele não será reincluido).
Já as funções require() e require_once() fazem basicamente a mesma coisa, entretanto em caso de erro o include() envia uma mensagem de aviso e continua a execução da aplicação ao passo que o require() envia um erro fatal e impede a execução em caso de erro.
Aula 411 - Criar arquivo de conexão
Com as funções include() ou require() podemos separar do arquivo publico os dados de conexão com o banco de dados de modo a proteger as informações mesmo sabendo que essas informações não são acessíveis por meio do HTML simples.

Curso XI - Unidade 04 - Listagem de produtos

Aula 413 a 416 - Realizar uma listagem de produtos / Mostrar a imagem do produto / Aplicando estilo a listagem de produtos / Aplicar o formato da moeda Real
Reconstrução da lista de produtos, agora com alguns estilos.
Os arquivos de topo e rodapé vieram prontos com os recursos da aula, assim como os estilos CSS. Analisei os arquivos e não tem nada de relevante.
Tanto o arquivo de topo quanto o de rodapé foram inseridos utilizando o include(). Precisei fazer ajustes nos caminhos para os arquivos.
Em seguida foi criada uma lista com os dados do banco como já visto anteriormente.
Em seguida inserimos na query o campo de imagens e a adicionamos na lista dentro de uma tag img. O formato do texto no campo da imagem está no padrão do arquivo 'jpg' inclusive com o path. Caso as imagens estivessem em outro padrão precisariamos tratar esses dados de outra forma.
O próximo passo é aplicar as configurações do CSS. No arquivo CSS pré-definido temos um id e uma class pré-definidos que formatam a lista com float: left para as <ul> e para a <img>. Dessa forma temos a distribuição das imagens e dos textos lado a lado e uma divisão em duas colunas (definido pelo width das <ul>).
Para finalizar o projeto inserimos uma função que já havia sido definida para formatar os valores em reais. Essa função utiliza a função do PHP number_format para definir o numero de casas decimais e alterar os simbolos de milhar e decimal. A função é como segue:
function real_format($valor) {
$valor = number_format($valor,2,",",".");
return "R$ " . $valor;
}

Essa função está em um arquivo externo e é inserida com o include.

Curso XI - Unidade 05 - Listagem - Detalhe

Aula 419 a 423 - Criar links com parametro de URL / Testar parametro / Fazer um filtro na página de detalhe / Apresentar os dados na tela / Aplicar estilos e função monetária
Aqui criamos um anchor no item de imagem da lista para acessar a página de detalhes. A página detalhe, em princípio é a mesma que a página listagem o que deve ser alterado é apenas o conteúdo e os estilos.
Para fazer o link entre as páginas apontando para o produto selecionado utilizamos os parametros enviados pela URL com o código recuperado na tabela através da coluna produtoID. Esse código é recuperado ná página detalhe com a variável global $_GET.
Devemos fazer um teste para verificar se a página está com a URL completa, com os parametros. Fazemos isso testando se a variável global $_GET recebeu algum valor utilizando a função isset(). Caso não haja valor definido, no exemplo, retornamos para a página listagem com o comando Header('Location: listagem.php'); Com o valor do produtoID recuperado podemos aplicar na projeção SELECT a seleção com WHERE no item desejado.
Diferente da listagem em que devemos percorrer todos os dados do banco com o while(), nesse caso como precisamos de apenas um registro (selecionado pelo filtro WHERE) podemos fazer o fetch nos dados ainda no início da página, no teste que verifica a conexão.
Neste caso, recuperamos quase todos os dados da tabela e atribuimos eles a variáveis. Isso é indiferente, embora deixe o código mais organizado.
O último passo é aplicar os estilos do mesmo modo que no exemplo anterior.

Curso XI - Unidade 06 - Tela de pesquisa

Aula 425 a 426 - Criar formulario de pesquisa / Reusltado da pesquisa
Fiz a lógica da criação da pesquisa e o campo de pesquisa antes da aula, portanto não apliquei os estilos (serão aplicados depois).
Na minha solução criei um <form> com o método GET para recuperar a chave da pesquisa:
<form action="./listagem.php?">
<input type="text" name="prodName">
<input type="submit"
value="Pesquisar">
</form>
Para a lógica do PHP alterei o filtro de apenas mostrar todos os elementos para um filtro no nome do produto utilizando o LIKE do SQL. A estrutura completa da pesquisa ficou como segue:
if (isset($_GET["prodName"])) {
$prodName = $_GET["prodName"];
} else {
$prodName = '';
}
$produtos = "SELECT produtoID, nomeproduto, tempoentrega, precounitario, imagempequena ";
$produtos .= " FROM produtos ";
$produtos .= " WHERE nomeproduto LIKE CONCAT('%','$prodName','%')";
$resultado = mysqli_query($conecta, $produtos);
if (!$resultado) {
die('Falha na conexão');
}
O <input> insere o parametro prodName na URL. O PHP recebe através do $_GET e processa o valor no filtro com a função SQL CONCAT() e os coringas '%' desse modo filtramos qualquer valor de entrada, mesmo incompletos.
O <input type='image'> faz a mesma função que o <input type='submit'> e envia os dados do <input type='text'> como parametro do formulário.
A resolução da lógica ficou um pouco diferente:
$produtos = "SELECT produtoID, nomeproduto, tempoentrega, precounitario, imagempequena ";
$produtos .= " FROM produtos ";
if (isset($_GET["prodName"])) {
$prodName = $_GET["prodName"];
$produtos .= " WHERE nomeproduto LIKE '%{$prodName}%'";
O código da aula tem ainda uma função PHP setlocale() (ver Aula 336) que não foi referenciada durante esse projeto:
setlocale(LC_ALL, 'pt_BR');
O parametro LC_ALL seta todos os parametros (letras, dinheiro, etc) para o padrão selecionado.

Curso XII - Unidade 07 - Criar um sistema de login

Aula 428 - Como funciona um sistema de login
O sistema de login recebe os dados de login definidos pelo sistema através de um formulário e verifica em um Banco de dados se os dados informados são iguais aos definidos entre os usuários cadastrados. Existindo o usuário o primeiro passo é inicializar a variável global $_SESSION. Essa variável não precisa ser passada por GET ou POST, ela permanece ativa indefinidamente, até que expire (por padrão em 3 horas) ou quando o usuário faz um logout.
A variável $_SESSION vincula o navegador ao Servidor.
Aula 429 - Criar uma variável de sessão
Para iniciar uma sessão no PHP precisamos inicialmente executar a função session_start(). Em seguida iniciamos a variável $_SESSION com os dados do usuário.
Quando iniciamos uma sessão com a função session_start() devemos faze-lo em todas as páginas da aplicação, para que a sessão permaneça ativa durante a navegação.
Uma vez que temos a variável $_SESSION definida ela se torna global e acompanha todas as páginas que seguem a página onde ela foi definida.
Duas coisas importantes aqui são não esquecer de iniciar a sessão ( session_start() ) em todas as páginas que seguem o fluxo da sessão e sempre que precisarmos do dado dos usuários verificarmos se a variável está definida ( isset($_SESSION[]) ).
Para encerrar uma sessão podemos utilizar a função unset($_SESSION[]) para excluir a variável da memória.
Outra opção é utilizar a função session_destroy() que apaga todas as variáveis da aplicação.
Aula 430 a 436 - Criar uma tela de login / Receber as informações enviadas / Realizar o filtro no banco de dados / Criar a variável de sessão / Proteger as páginas internas / Criar uma rotina de saudação / Criar uma página de logout
Criamos a tela de login em um <form> com método POST pois se trata de dados de usuário e senha. Esse formulário irá enviar os dados de usuario e senha através do POST ao clicar em Login. Em seguida iniciamos a captura dos valores de input.
Primeiro fazemos um teste para verificar se exitem dados no método POST através de um isset() em qualquer uma das variáveis do POST. Feito isso incluimos os valores em variáveis.
No Banco de Dados temos, na tabela clientes os campos usuario e senha. Esses serão os campos utilizados para a validação do login.
Toda a validação de login fiz corretamente. A única coisa que fiz diferente foi o tratamento do sucesso/erro. Para verificar o erro foi utilizada a função PHP empty() que verifica se a variável está vazia. Em caso de sucesso foi utilizada a função header("location:página_de_destino.php") que direciona para uma página definida.
        if (isset($_POST['usuario'])) { 
            $usuario = $_POST["usuario"]; 
            $senha = $_POST["senha"]; 
            $login = "SELECT * FROM clientes "; 
            $login .= " WHERE usuario = '{$usuario}' AND senha = '{$senha}'"; 
            $usrLogin = mysqli_query($conecta, $login);
            
            if (!$usrLogin) { 
                die('Falha na conexão'); 
            } 
            $show = mysqli_fetch_assoc($usrLogin);
            
            if (empty($show)) { 
                $message = 'Digite um nome de usuario ou senha validos'; 
            } else { 
                header("location:listagem.php"); 
            } 
        } 
                                    
Para a mensagem de erro inserimos um teste lógico no form para imprimir a mensagem:
            if (isset($message)) { 
                echo " <p>$message</p> "; 
            } 
                                
Feito o login com sucesso precisamos iniciar a sessão. Neste momento as páginas estão acessíveis quando digitamos sua URL completa. Com a sessão podemos proteger as páginas da aplicação.
Para iniciar a sessão primeiramente inserimos a função session_start() no início da rotina PHP. Devemos então criar a variável $_SESSION["nome_da_sessao"] e atribuimos a ela um valor que identifique o usuário de forma única (nesse exemplo pode ser o campo clienteID ou usuario, muito embora o campo usuario não esteja com a propriedade UNIQUE).
Com isso nossa variável de sessão está criada. A partir de agora devemos iniciar a sessão em todas as páginas com session_start().
Com as variáveis de sessão iniciadas precisamos criar uma instrução que faça com que quando a sessão não esteja inicializada a navegação seja redirecionada para a página de login.
Fazemos isso inserindo a seguinte instrução nas páginas que são acessadas após o login:
                if (!isset($_SESSION["user_portal"])) {
                    header("location:login.php");
                    die;
                };
                                    
Essa restrição só ocorrerá quando não houver sessão iniciada no navegador. Nesse momento o sistema não está limpando a variável $_SESSION portanto ela fica na memória do navegador. Essa rotina deve ser incluida em todas as páginas.
PAra evitar que o programa por algum erro prossiga após o teste da session, podemos colocar um die após a ligação para a página de login (na aula o professor utilizou o break porém esse comando resultou em erro na aplicação).
O próximo passo é colocar uma saudação com o nome do usuário no topo da tela. Essa saudação foi incluida no arquivo que define a barra superior do projeto (topo.php).
Como esse arquivo é incluido nos arquivos das páginas não é necessário iniciar a sessão nem incluir o arquivo de conexão com o BD. Nesse arquivo importamos a variável de $_SESSION e criamos uma nova projeção no banco de dados para recuperar o nome de usuário. Tentei transmitir o nome completo como uma variável global a partir da página de login mas não consegui. Desse modo precisamos refazer a projeção mesmo.
            if (isset($_SESSION["user_portal"])) {
                $user = $_SESSION["user_portal"];
    
                $saudacao = "SELECT nomecompleto FROM clientes WHERE clienteID = {$user}";
                $saudacao_login = mysqli_query($conecta, $saudacao);
                if (!$saudacao_login) {
                    die("Falha na conexão");
                }
    
                $saudacao_login = mysqli_fetch_assoc($saudacao_login);
                $nome = $saudacao_login["nomecompleto"];
            };
                                    
Para a apresentação dos dados na tela foram feitas alterações no estilo CSS para que o menu do topo mudasse para position: relative com a saudação em position: absolute.
Para finalizar a sessão incluimos uma página de logout com um link do tipo <a> que direciona para uma rotina de unset() na variável $_SESSION:
                session_start();
                unset($SESSION["user_portal"]);
                header("location: login.php");
                                    

Curso XII - Unidade 08 - Inserindo dados em um B.D.

Aula 438 a 442 - Criar um formulário / Preencher o campo de estados dinamicamente / Conferir a informação enviada via formulário / Inserir no banco de dados / Alterar o encode para inserção no banco
Primeiramente criamos um formulário com os campos da tabela do BD andes transportadoras. Esse formulário utilizará o método POST para transmissão dos dados. O estilo para o formulário já estava pronto também em um arquivo CSS. O estilo basicamente dimensiona o formulário e os inputs de modo que eles fiquem em bloco automaticamente.
Para selecionarmos os estados utilizamos um campo tipo <select> e recuperamos os valores da tabela do BD estados inserindo sua projeção nas tags <option>.
            $consulta_estados = "SELECT * FROM estados";
            $estados = mysqli_query($conecta, $consulta_estados);
            if (!$estados) {
                die('Falha na conexão');
            }
                                    
Em seguida recuperamos os dados inseridos nos campos do formulário com a variável $_POST de cada campo e apresentamos elas na tela com o print_r()
Para inserir os dados no BD atribuimos todos os valores do $_POST em variáveis. Em seguida criamos a variável que irá armazenar a query de INSERT. Por fim criamos a variável de execução da query com mysqli_query(). Fiz um teste lógico para evitar que sejam inseridos campos sem pelo menos um valor no nometransportadora.
            if (isset($_POST['nometransportadora'])) {
                // print_r($_POST);
                $nometransportadora = $_POST['nometransportadora'];
                $endereco = $_POST['endereco'];
                $telefone = $_POST['telefone'];
                $cidade = $_POST['cidade'];
                $estado = $_POST['estados'];
                $cep = $_POST['cep'];
                $cnpj = $_POST['cnpj'];
                if (empty($nometransportadora)) {
                    header("location:inserir_transportadoras.php");
                } else {
                    $insere_transp = "INSERT INTO transportadoras VALUES(null, '$nometransportadora' , '$endereco' , '$telefone' , '$cidade' , $estado , '$cep', '$cnpj')";
                    $insert_data = mysqli_query($conecta, $insere_transp);
                    if (!$insert_data) {
                        die('Falha na conexão');
                    }
                }
            }
                                    
Na aula o BD estava em formato fora do padrão de caracteres UTF-8. Com isso os nomes dos estados eram apresentados no formulário sem acentuação e os dados que eram inseridos na tabela entravam no BD com caracteres truncados. Para solucionar esse problema utilizou-se as funções PHP utf8_encode() e utf8_decode().

Curso XII - Unidade 09 - Página de Alteração

Aula 443 a 444 - Apresentar o projeto da unidade / Criar o formulário de alteração
Para o arquivo incial criei a query que recupera a lista de dados da tabela transportadoras. Na minha query utilizei o INNER JOIN pois tive a impressão que os dados apresentados eram de estados mas na verdade eram de cidade que está na tabela transportes.
No estilo pré definido cada linha da tabela está em uma <ul> e as <li> foram configuradas com display: inline-block. A largura de cada item na linha é definido através da pseudo-classe li:nth-child(n) onde 'n' representa cada elemento da linha. Para o efeito de zebra foi utilizada a pseudo-classe ul:nth-child(odd).
Na lista de valores inserimos nas <li> os valores recuperados da tabela e utilizamos um tag <a> para fazer o link para a página do formulário passando como parametro da URL o valor do campo transportadoraID.
A página de formulário é igual a de inserção de dados. A única diferença é que como vamos preencher os campos com os valores recuperados foi incluido um <label> para cada <input> para susbstituir o placeholder.
Nesse ponto eu montei o resto da aplicação com meus conhecimentos.
Como recebemos o código da transportadora como parametro na URL primeiro recuperamos seu valor com o $_GET.
Com esse valor fazemos o filtro e recuperamos o dado do registro a ser alterado. Recuperamos também a tabela de estados que será utilizada no campo <select>:
                $transID = $_GET['codigo'];

                if (!$transID) {
                    header('location:list_transp.php');
                }

                $sel_transp = "SELECT * FROM transportadoras WHERE transportadoraID = $transID";
                $get_transp = mysqli_query($conecta, $sel_transp);

                if (!$get_transp) {
                    die('Falha na conexão');
                }

                $consulta_estados = "SELECT * FROM estados";
                $estados = mysqli_query($conecta, $consulta_estados);
                if (!$estados) {
                    die('Falha na conexão');
                }
                                    
Recuperados os dados da transportadora atribuimos eles a variáveis e inserimos no atributo value="" das tags <input>. Isso fará comque os dados sejam apresentados nos campos de inserção de dados.
Uma atenção especial deve ser dada ao campo estado. Como esse campo é um <select> para colocar o valor na opção devemos colocar o atributo selected na tag <option> correspondente. Para isso inclui um teste lógico para definir qual o estado da trasnportadora selecionada.
                if (empty($get_transp)) {
                    header('location:list_transp.php');
                }
                $transp = mysqli_fetch_assoc($get_transp);
                if (!$transp['transportadoraID']) {
                    header('location:list_transp.php');
                }
                $nometransportadora = $transp['nometransportadora'];
                $endereco = $transp['endereco'];
                $telefone = $transp['telefone'];
                $cidade = $transp['cidade'];
                $estado = $transp['estadoID'];
                $cep = $transp['cep'];
                $cnpj = $transp['cnpj'];

                <label for="nometransportadora">Nome da Transportadora</label>
                <input type="text" name="nometransportadora" placeholder="Nome transportadora" value="<?php echo $nometransportadora ?>">
                ... 
                <?php
                while ($linha = mysqli_fetch_assoc($estados)) {
                ?>
                <option value="<?php echo $linha['estadoID'] ?>" <?php if ($linha['estadoID'] == $estado) {
                                                                                        echo 'selected';
                                                                                    }?>><?php echo $linha['nome'] ?></option>
                <?php
                }
                ?>
                                    
Após isso, apenas devemos recuperar os dados dos campos do formulário com a variável $_POST e fazer o UPDATE na tabela da mesma forma que fizemos o INSERT.
            if (isset($_POST['nometransportadora'])) {
                print_r($_POST);
                $nometransportadora = $_POST['nometransportadora'];
                $endereco = $_POST['endereco'];
                $telefone = $_POST['telefone'];
                $cidade = $_POST['cidade'];
                $estado = $_POST['estados'];
                $cep = $_POST['cep'];
                $cnpj = $_POST['cnpj'];

                $altera_transp = "UPDATE transportadoras SET nometransportadora = '$nometransportadora' , endereco = '$endereco' , telefone = '$telefone' , cidade = '$cidade' , estadoID = $estado , cep = '$cep', cnpj = '$cnpj' WHERE transportadoraID = $transID ";
                $altera_data = mysqli_query($conecta, $altera_transp);
                if (!$altera_data) {
                    die('Falha na conexão');
                }
                header('location:list_transp.php');
            }                        
                                    
Ao fim da rotina chamo novamente a página list_transp para verificar as alterações.
Aula 445 a 449 - Criar a consulta ao banco de dados / Prrencher os campos do formulário dinamicamente / Preencher o campo select com seleção do estado atual / Pegar as informações enviadas pelo formulário / Realizar a alteração de dados
A primeira parte da resolução ficou parecida com a minha. A diferença é que o teste do valor do atributo $_GET é feito diretamente na query SQL e em caso de não ter valor recupera os dados com id = 1.
Na sequencia para o preenchimento dos campos de <input> foi feito do mesmo modo que eu com a exceção de que os valores recuperados foram passados diretamente para o atributo value e um inclui todos os valores em variáveis primeiro.
Para o preenchimento e seleção do estado padrão da transportadora selecionada foi feito o mesmo teste lógico que eu fiz, porém na aula foram criadas duas tags <option> uma para o caso em que o ID do estado é igual ao estado da transportadora e outra para os demais casos. Desse modo temos toda a linha do <option> criada com o atributo selected e outra linha sem o atributo para os demais valores.
A recuperação dos dados alterados também foi feita do mesmo modo que eu fiz utilizando o $_POST nos campos do formulário. Na aula ele recupera o valor de transportadoraID através da variável $_POST junto com os outros campos. Na minha execução eu recuperei essa informação através da variável recuperada com o $_GET no início da página.
Finalizando a query de UPDATE ficou igual a minha, inclusive com o redirecionamento para a página de listagem.

Curso XII - Unidade 10 - Criar página de exclusão de dados

Aula 451 a 453 - Criar consulta ao Banco de Dados / Montar o formulário de confirmação / Excluir o registro no banco de dados
Para a criação da rotina de exclusão foi utilizado basicamente o mesmo formulário que para alteração de dados. A única diferença é na rotina SQL para manipular os dados que nesse caso é:
DELETE FROM transportadoras WHERE transportadoraID = $tID

Curso XII - Unidade 11 - Realizar upload de arquivo

Aula 454 a 457 - Compreender as configurações padrão / Enviar os dados por um formulário / Conhecer o $_FILES / Explicando as mensagens de erro
Para trabalhar com upload de arquivos no PHP devemos verificar algumas configurações no arquivo php.ini:
file_uploads=On
upload_tmp_dir="diretório_de_uploads"
post_max_size=NNM (valor máximo para POST. No XAMPP o valor estava em 40M)
upload_max_filesize=NNM (valor máximo para uploads. No XAMPP o valor estava em 40M)
max_execution_time=NN (tempo máximo de execução para cada script. No XAMPP o valor estava em 120s)
max_input_time=NN (tempo máximo para analisar o script. No XAMPP o valor estava em 60s).
Para a pasta de upload precisamos autorizar as permissões para leitura? e escrita para todos os usuários e não apenas para o proprietário. Outra coisa a ser feito é não permitir quie a pasta execute scripts de qualquer tipo (não sei se desabilitando a opção de execução é o suficiente).
Para que possamos receber arquivos em nossa página vamos criar um formulário com a tag <form> passando os parametros de action e method=POST e adicionando o parâmetro enctype="multipart/form-data". Esse parâmetro será resposável por avisar ao formulário que ele pode receber arquivos.
Para criar um <input> que permite a seleção de arquivos utilizamos o type="file".
Da mesma forma que as outras variáveis globais do PHP temos a variável $_FILES. Essa variável recebe um array com o nome do arquivo enviado, o tipo de arquivo o nome temporário atribuido pelo sistema o tipo de erro se houver e o tamanho do arquivo:
                    Array
                      (
                        [name] => 583805072179.pdf.pdf
                        [type] => application/pdf
                        [tmp_name] => C:\Programacao\xampp\tmp\phpA851.tmp
                        [error] => 0
                        [size] => 335343
                      )
                  
Para saber os códigos de erro podemos ver a página PHP Docs. Foi criado um array com as mensagens de erro e inserido no arquivo de uploads. Entre os erros, temos o erro por exceder o upload_max_filesize configurado no php.ini e o MAX_FILE_SIZE que podemos definir no HTML em uma tag oculta <input>:
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
Essa tag define em seu value o tamanho máximo definido para arquivos enviados no formulário.
Com essa estrutura fazemos uma verificação nos códigos de erro e enviamos as mensagens de erro de acordo com o array criado:
                    $array_erro = array(
                        UPLOAD_ERR_OK => "Sem erro.",
                        UPLOAD_ERR_INI_SIZE => "O arquivo enviado excede o limite definido na diretiva upload_max_filesize do php.ini.",
                        UPLOAD_ERR_FORM_SIZE => "O arquivo excede o limite definido em MAX_FILE_SIZE no formulário HTML",
                        UPLOAD_ERR_PARTIAL => "O upload do arquivo foi feito parcialmente.",
                        UPLOAD_ERR_NO_FILE => "Nenhum arquivo foi enviado.",
                        UPLOAD_ERR_NO_TMP_DIR => "Pasta temporária ausente.",
                        UPLOAD_ERR_CANT_WRITE => "Falha em escrever o arquivo em disco.",
                        UPLOAD_ERR_EXTENSION => "Uma extensão do PHP interrompeu o upload do arquivo."
                    );
                  
Com esse array selecionamos o numero do código de erro enviado pela variável $_FILES e passamos esse valor como índice no array de erros.
$mensagem = $array_erro[$numero_erro];
Para gravar o arquivo na pasta desejada vamos recuperar os dados da variável $_FILES para variáveis e em seguida executar a função move_uploaded_file() :
move_uploaded_file(nome_do_arquivo_temporario_no $_FILES['tmp_name'], diretorio_de_gravacao . "/" . $nome_do_arquivo_no_$_FILES['name']);
Atenção para a definição da variável de diretório de gravação de acordo com o sistema operacional
No exemplo abaixo a função basename() tem como objetivo limpar nomes associados aos arquivos de acordo com o SO utilizado.
                    $arquivo_temporario = $_FILES['upload_file']['tmp_name'];
                    $arquivo = basename($_FILES['upload_file']['name']);
                    $diretorio = 'C:\git_repo\upload';

                    move_uploaded_file($arquivo_temporario, $diretorio . "/" . $arquivo);
                  
Para finalizar incluimos um teste lógico para enviar a mensagem de conclusão do upload:
                    $arquivo_temporario = $_FILES['upload_file']['tmp_name'];
                    $arquivo = basename($_FILES['upload_file']['name']);
                    $diretorio = 'C:\git_repo\upload';

                    if (move_uploaded_file($arquivo_temporario, $diretorio . "/" . $arquivo)) {
                        $mensagem = "Arquivo enviado";
                    } else {
                        $mensagem = $array_erro[$numero_erro];
                    }
                  
Aula 459 - Otimizar código do upload
Para otimizar o sistema removemos toda a estrutura de upload de arquivos do arquivo base e incluimos em funções no arquivo de apoio.
Desse modo o arquivo principal passa a executar a partir do método $_POST a função responsável pelo upload do arquivo.
A função de upload foi dividida em duas. Uma para as mensagens de erro e outra para o tratamento do $_FILES que chega por parametro para a função de tratamento do upload.
A seguir a função de upload:
                    function publicarArquivo($upload)
                    {
                        $arquivo_temporario = $upload['tmp_name'];
                        $arquivo = basename($upload['name']);
                        $diretorio = 'C:\git_repo\upload';
                        if (move_uploaded_file($arquivo_temporario, $diretorio . "/" . $arquivo)) {
                              $mensagem = "Arquivo enviado";
                        } else {
                              $numero_erro = $upload['error'];
                              $mensagem = mostrarAvisoUpload($numero_erro);
                        }
                        return $mensagem;
                    }
                  
Note que recebemos como parametro o array da super variável $_FILES e desse modo acessamos cada chave desse array diretamente na variável $upload.
A mensagem de erro chama outra função:
                    function mostrarAvisoUpload($numero)
                    {
                      $array_erro = array(
                          UPLOAD_ERR_OK => "Sem erro.",
                          UPLOAD_ERR_INI_SIZE => "O arquivo enviado excede o limite definido na diretiva upload_max_filesize do php.ini.",
                          UPLOAD_ERR_FORM_SIZE => "O arquivo excede o limite definido em MAX_FILE_SIZE no formulário HTML",
                          UPLOAD_ERR_PARTIAL => "O upload do arquivo foi feito parcialmente.",
                          UPLOAD_ERR_NO_FILE => "Nenhum arquivo foi enviado.",
                          UPLOAD_ERR_NO_TMP_DIR => "Pasta temporária ausente.",
                          UPLOAD_ERR_CANT_WRITE => "Falha em escrever o arquivo em disco.",
                          UPLOAD_ERR_EXTENSION => "Uma extensão do PHP interrompeu o upload do arquivo."
                      );
                      return $array_erro[$numero];
                    }
                  
Essa função trata o valor recebido pelo atributo erro da variável $upload e retorna a mensagem apropriada.
Por fim o arquivo de funções pode ser incluido com a função require_once() e deve ser feito no início do arquivo (tive erros com a inclusão no meio do código).

Curso XII - Unidade 12 - Inserção no banco de dados com upload de arquivos

Aula 460 - Apresentar o projeto da unidade Aula 460 a 461 - Apresentar o projeto da unidade / Apresentação dos arquivos do projeto
O formulário que eu fiz ficou bastante parecido com o apresentado pelo professor, com alguns ajustes de estilo. No exemplo da aula foi definido um <input type='hidden'> para definir o MAX_FILE_SIZE.
Outra rotina criada foi a inserção da função para gravar o arquivo conforme explicado na Unidade anterior.
O campo de estoque também é do tipo hidden e passa o valor '0' para ioniciar o estoque.
Outras coisas que foram feitas foi o fechamento das queries de categorias e fornecedores e o fechamento da conexão com o BD.
Com relação as funções serão melhor explicadas na próxima aula. Como eu estou fazendo a aplicação sempre mantendo os dados anteriores acho que será melhor manter o arquivo de funções que já estava criado e criar um novo arquivo de funções apenas para as funções de upload. Até esse ponto meu PHP não está funcionanado. Vou tentar fazer a inclusão de dados por esse formulário sem as imagens antes de continuar para ver se eu cometi algum erro.
Localizei o erro de sintaxe. O outro problema foi que deixei de setar o enctype="multipart/form-data" no formulário.
Outro erro que cometi foi que as variáveis de imagens que serão enviadas para o BD devem receber como valor o índice 1 da variável que será enviada pela função que faz o tratamento do arquivo. Possivelmente haverá uma alteração na função publicarImagem() pois ela só está retornando um valor e na aplicação está recebendo o valor do segundo índice.
Aula 462 a 464 - Função para gerar nome unico / Função para pegar extensão do arquivo / Adicionar os códigos ao arquivo de funções
Para definir nomes únicos para os arquivos recebidos, podemos utilizar a função de data que recupera uma valor instantâneo e consequentemente único, com a função date_default_timezone_set('America/Sao_Paulo') Para verificar as regiões da função verificar o site PHP Documentation.
Em seguida utilizamos a função getdate() para recuperar os valores obtidos. Essa função retorna um array com os seguintes registros:
array(11) { ["seconds"]=> int(43) ["minutes"]=> int(22) ["hours"]=> int(9) ["mday"]=> int(1) ["wday"]=> int(2) ["mon"]=> int(3) ["year"]=> int(2022) ["yday"]=> int(59) ["weekday"]=> string(7) "Tuesday" ["month"]=> string(5) "March" [0]=> int(1646137363) }
Desse array utilizamos os campos year, yday, hours, minutes e seconds.
Em seguida foi criada um gerador randomico de caracteres para criar uma chave única, utilizando um loop for e as funções substr() e rand():
                    $alfabeto = '23456789ABCDEFGHIJKLMNOPQRS';
                    $tamanho = 12;
                    $letra = '';
                    $resultado = '';
                    for ($i = 1; $i %lt; $tamanho; $i++) {
                        $letra = substr($alfabeto, rand(0, 26), 1);
                        $resultado .= $letra;
                    }

                    date_default_timezone_set('America/Sao_Paulo');
                    $agora = getdate();

                    $codigo_data = $agora['year'] . "_" . $agora['yday'];
                    $codigo_data .= $agora['hours'] . $agora['minutes'] . $agora['seconds'];

                    echo "FOTO_" . $codigo_data . "_" . $resultado;
                  

Para recuperar a extensão do arquivo utilizamos a função strrchr(string, 'caractere') que pega todos os valores subsequentes à última ocorrencia do caractere definido.
Esse dois códigos de geração dos nomes aleatórios de arquivo são agora adaptados na função de upload de arquivos que já havíamos criado.
Para isso fizemos algumas adaptações para manipular o nome que é recuperado no array gerado na variável $_FILES para converte-lo antes de passar para a função move_uploaded_file().
O retorno da função de upload, como havia imaginado é um array que passa a mensagem de sucesso/erro e o nome do arquivo para o DB. Aqui é necessário cuidado especial quanto aos caminhos utilizados. No meu caso como o diretório das imagens era diferente do caminho no DB precisei criar duas variáveis diferentes. Uma para o diretório de gravação do arquivo e outra para o caminho relativo a ser armazenado no DB.

Curso XII - Unidade 13 - Contato do site com Mail

Aula 465 - Preparando o formulário
Para criar uma página de envio de mensagens primeiro fizemos um formulário com os campos necessários para o que queremos receber do usuário (no caso nome, email e mensagem).
Em seguida encaminhamos a variável $_POST inteira para uma função que irá fazer o tratamento desses dados.
Isolamos cada um desses dados em variáveis e criamos ainda as variáveis para um destinatário (email que irá receber a mensagem), remetente (não é o usuário que cadastrou a mensagem mas sim um email válido do domínio em que a aplicação está hospedada e que pode ser autenticado pelo serviço de email local), assunto (campo de assunto do email) e mensagem (os dados recebidos pelo $_POST concatenados do modo que queremos que seja apresentado no corpo da mensagem).
Para fazer o envio da mensagem utilizamos a função mail() do PHP PHP Docs
A função mail() recebe como parametros: email de destino
assunto
mensagem
remetente (o email de envio no servidor).
Essa função apenas irá funcionar com um servidor de email habilitado na máquina e com email válido para envio no domínio.
Essas configurações devem ser testadas em um servidor habilitado. Outro ponto a se observar são as configurações do arquivo php.ini nas opções de [mail function].

Curso XIII - Unidade 02 - O que é AJAX

Aula 473 - Introdução ao AJAX
AJAX é uma metodologia de programação que permite a comunicação entre navegador e servidor sem que haja uma mudançã de URL. AJAX significa Assincronous Javascript and XML entretanto hoje se utiliza mais os arquivos do tipo JSON.
A maioria das comunicações AJAX são feitas com a API XMLHttpRequest.
Aula 474 a 475 - Realizando uma requisição síncrona / Identificar os estágios de carregamento
Iniciamos a API AJAX criando uma variável que instancia o objeto XMLHttpRequest()
var ajax = new XMLHttpRequest()
Em seguida chamamos a variável seguida do método .open() passando três parâmetros: o método de comunicação('GET/POST'), o nome do arquivo a ser consultado e o tipo de comunicação(síncrona = false ou assíncrona = true). Em seguida executamos o método .send()
ajax.open('GET', 'dados.txt', false);
ajax.send();
Analisando os dados no console temos algumas informações relevantes:
readyState: 0 = requisição não inicializada; 1 = conexão estabelecida com o servidor; 2 = requisição recebida; 3 = processando requisição; 4 = requisição finalizada;
response e responseText: o valor recebido pela requisição
responseType
responseURL
responseXML
status: 200 = OK ; 404 = Página não encontrada;
Podemos verificar as fases do processamento (através do parâmetro readyState) utilizando o método .onreadystatechange porém só podemos ver as mudanças de estado com a comunicação assíncrona (mudando o parametro da requisição para 'true' ou deixando vazio (padrão)).
Com isso podemos monitorar o momento de cada fase do readyState e através desse procedimento criar funções para mostrar o estado de carregamento para o usuário:
ajax.open('GET', 'dados.txt', true);
ajax.send();
console.log(ajax);
ajax.onreadystatechange = function () {
if (ajax.readyState == 3) {
console.log('Carregando');
}
if (ajax.readyState == 4) {
console.log('Carregou');
}
};
Note que com o método de comunicação alterado para assíncrono não conseguimos mais acessar o valor da propriedade .reponse diretamente no objeto instanciado ajax.
Aula 476 a 479 - Mostrar dados de retorno / Fazer o código compatível com todas as versões de navegadores / Alterar elemento do HTML pelo ID ou nome da Tag / Adicionar um evento
Quando definimos a comunicação do AJAX como assíncrona podemos acessar a resposta na função .onreadystatechange.
Nesse caso podemos também fazer um tratamento de erro monitorando a resposta do método .status:
ajax.onreadystatechange = function () {
if (ajax.status == 200) {
if (ajax.readyState == 3) {
console.log('Carregando');
}
if (ajax.readyState == 4) {
console.log(ajax.response);
}
} else {
console.log('Erro na operação');
}
};
O XMLHttpRequest é uma implementação universal de uma API criada pela Microsoft chamada ActiveX. Desse modo para fazer a compatibilidade com versões mais antigas de navegador, podemos incluir o suporte para o ActiveX.
Para isso fazemos um teste de compatibilidade do navegador cliente com o XMLHttpRequest no início do script. Caso ele seja compatível instanciamos de modo normal, caso contrário instanciamos o ActiveXObject.
var ajax;
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
} else {
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}
Em seguida fizemos a inserção da resposta no HTML utilizando uma <div> e o id da tag h1.
Para finalizar encapsulamos todo o código AJAX criado em uma função que é executada através do evento onclick de um botão. Dessa forma o código AJAX só é executado após ser pressionado o botão.
Outro detalhe. O método .send() pode ser executado a qualquer momento, mas o idel é deixá-lo após o código de requisição.

Curso XIII - Unidade 03 - Introdução ao jQuery/AJAX

Aula 480 a 481 - Introdução ao jQuery / Realizar uma requisição simples com jQuery
As principais funçõa do jQuery são:
  • Acessar e manipular o DOM
  • Adicionar efeitosd visuais e animações
  • Alterar o conteúdo da página
  • Alterar a apresentação de uma página
  • Buscar informações no servidor sem recarregar a página
Quando trabalhamos com o jQuery juntamente com o AJAX não precisamos carregar as definições do XMLHttpRequest. Basta apontarmos para o elemento desejado e utilizar o método .load().
$('#curso').load('./dados.txt');
Aula 482 - Carregar uma variável de uma arquivo externo com jQuery/AJAX
Para importar conteudo de variáveis de arquivos externos com AJAX utilizamos no jQuery o método $.ajax( {url:nome_do_arquivo} ).then( sucesso, falha ) (onde sucesso e falha são funções como a try/catch). Percebe-se que essa é uma requisição assíncrona.
$.ajax({ url: 'nome.php' }).then(sucesso, falha);

function sucesso(valor) {
$('#nome').html(valor);
}

function falha() {
$('#nome').html('Falha no carregamento');
}
Aula 483 - Uso dos métodos done, fail e always
Podemos executar a mesma rotina de captura de erro acima utilizando os métodos .done(), .fail() e .always(). Nesse caso passamos uma função para cada um dos métodos, sendo uma para sucesso (done), uma para erro (fail) e uma opcional para ser executada sempre (always).
$.ajax({
url: 'nome.php'
}).done(function(valor) {
$('#nome').html(valor);
}).fail(function() {
$('#nome').html('Falha no carregamento');
}).always(function() {
$('#mensagem').html('Mesagem de qualquer coisa');
})

Curso XIII - Unidade 04 - XML com jQuery/AJAX

Aula 484 - O que é uma arquivo XML
XML é uma linguagem de marcação, que se tornou padrão em 1998. É utilizado para estruturar e descrever informações e foi planejado para ser usado pela internet. Sua principal função é a comunicação entre serviços. um arquivo XML é formado por uma linha que demonstra a versão do arquivo e o tipo de encode utilizado. Em seguida temos uma tag pai e as tags de informação:
<?xml version="1.0" encoding="UTF-8"?>
<loja>
<produto>
<nomeproduto>Biscottis</nomeproduto>
<codigobarra>789151 823800</codigobarra>
<tempoentrega>15</tempoentrega>
<precounitario>20.00</precounitario>
</produto>

<produto>
<nomeproduto>Biscottis</nomeproduto>
<codigobarra>789151 823800</codigobarra>
<tempoentrega>15</tempoentrega>
<precounitario>20.00</precounitario>
</produto>
</loja>
Aula 485 a 487 - Carregar um arquivo XML / Aplicar estilos para mudar aparencia da listagem / Chamar carregamento através de um evento
Vamos carregar o arquivo XML utilizando o método do jQuery .ajax() como visto na aula 482.
Podemos utilizar no arquivo recebido alguns métodos como o .find(). Esse método procura no arquivo os itens selecionados sendo a chave o nome das tags XML. Para ver o valor das tags terminamos a requisição com o método .text().
Para apresentar os valores dessa forma fazemos a seguinte requisição:
$(arquivo).find('produto').find('nomeproduto').text()
Nesse caso recuperamos o valor de nomeproduto dentro dos elementos produto.
Com isso podemos por exemplo criar uma lista de elementos com o jQuery:
$.ajax({
url: './_xml/produtos.xml'
}).then(sucesso, falha);

function sucesso(arquivo) {
var elemento;
elemento = "<ul>";
$(arquivo).find('produto').each(function() {
var nome = $(this).find('nomeproduto').text();
var preco = $(this).find('precounitario').text();
elemento += "<li>" + nome + " - R$ " + preco + "</li>"
}) elemento += "</ul>";
$('div#listagem').html(elemento);
}
Nesse exemplo recuperamos o arquivo XML e em caso de sucesso criamos uma <ul> com os elementos recuperados no arquivo e para cada item produto pesquisado com o método .each() executamos uma função que recupera o texto dos itens nomeproduto e precounitario. Note que como estamos dentro de uma função chamada pelo método .each() utilizamos como parametro o objeto this. Em seguida criamos alguns estilos CSS e separamos os itens em colunas utilizando o display: inline-block e fixando os tamanhos dos elementos para que fiquem apenas dois por linha.
Por fim encapsulamos a requisição AJAX para ser executada ao clique de um botão.

Curso XIII - Unidade 05 - JSON com jQuery/AJAX

Aula 488 - O que é JSON
O JSON também tem como função compatilhar dados. Podemos criar os dados a partir de um Banco ou descreve-lo manualmente. Hoje o JSON se tornou o padrão na Web.
Aula 489 a 491 - Carregar um arquivo JSON / Mostrar dados em uma lista / Aplicar estilo e aplicar um evento para carregar dados
Com o jQuery carregamos arquivos JSON com um método próprio .getJSON('nome_arquivo', cb_function(){}). É possível também carregar esse arquivo com o método .ajax().
A facilidade de utilizar o JSON é que com ele podemos aplicar diretamente o método .each() passando como parametro os dados obtidos na função de callback e passando uma nova função que recupera os valores de acordo com a chave solicitada.
$.getJSON('./_json/produtos.json', function(data) {
$.each(data, function(i, valor) {
console.log(i, valor.nomeproduto); })
})

Com isso podemos aplicar a mesma técnica para criar a lista utilizada no execício anterior.

Curso XIII - Unidade 06 - Como criar arquivos JSON com PHP

Aula 492 - Criar umarquivo JSON com PHP
Nesta unidade vamos gerar um arquivo JSON a partir de um banco de dados que irá atualizar os dados da página a cada alteração do DB.
Inicialmente criamos a conexão com o DB e fizemos uma query de consulta aos dados apresentando-os em uma lista.
Em seguida criamos uma variável do tipo array() para armazenar os dados recuperados em cada linha da query no DB.
Com esse array podemos apresentar os dados no formato padrão do PHP utilizando o print_r(). Podemos ainda gerar um array de objetos JSON utilizando o método json_encode(). Esse método formata os dados no padrão JSON separando cada par de elemento chave/valor.
Feita a consulta estruturada em JSON precisamos liberar o acesso a esses dados para outros domínios (mesmo em outras linguagens de programação).
Para liberar a consulta ao JSON devemos inserir a seguinte instrução no início do arquivo:
header('Access-Control-Allow-Origin:*');
Essa linha autoriza a consulta aos dados gerados no arquiv o de criação do JSON.
Aula 494 - Realizar uma consulta ao arquivo JSON
Aqui aplicamos a mesma estrutura de carregamento de arquivos JSON estáticos, porém fizemos o carregamento do arquivo criado com a função json_encode que atualiza os dados de modo dinâmico. As demais configurações foram as mesmas feitas anteriormente.

Curso XIII - Unidade 07 - Usando uma função de CallBack

Aula 495 - Preparar o arquivo para uso do CallBack
Uma fonte de informação para esse procedimento é o site Json-P.
Para esse módulo vamos utilizar o gerador de JSON das aulas anteriores, porém sem a instrução que habilita o acesso a outros domínios.
A proposta aqui é inserir o nome de uma função de CallBack no conteúdo JSON através de um parâmetro de url para que essa função seja acessada em outra página do mesmo domínio.
Para isso foi criada uma rotina com operador ternário que verifica se foi passado o nome da função de callback através da variável $_GET e em caso positivo insere o nome definido para a função no conteúdo JSON gerado:
$callback = isset($_GET['callback']) ? $_GET['callback'] : false;

$conecta = mysqli_connect("localhost", "root", "", "andes");

$selecao = "SELECT nomeproduto, precounitario, imagempequena FROM produtos";
$produtos = mysqli_query($conecta, $selecao);

$retorno = array();

while ($linha = mysqli_fetch_object($produtos)) {
$retorno[] = $linha;
}
echo ($callback ? $callback . '(' : '') . json_encode($retorno) . ($callback ? ')' : '');
Note que o operador ternário criado faz apenas a concatenação do valor passado pela url caso ele exista. Caso não exista parametro de callback o JSON permanece inalterado.
$entendendo;
if ($callback) {
$entendendo = $callback . '(';
} else {
$entendendo = '';
}
$entendendo = $entendendo . json_encode($retorno);
if ($callback) {
$entendendo = $entendendo . ')';
} else {
$entendendo = $entendendo . '';
}
echo $entendendo;
Uma vez nomeado esse arquivo JSON podemos implemantar uma função em outro arquivo que permitirá acessar os dados do elemento JSON como um objeto, sem a necessidade de nenhuma instrução adicional bastando incluir a url do gerador de JSON diretamente em uma tag script src:
<script>
function retornarProdutos(data) {
console.log(data);
console.log(data[0].nomeproduto);
}
</script>

<script src="http://localhost/Cursos/udemy/Curso_Desenv_Web_Compl_10_Proj_Mod3/Aula_495/gerar_json.php?callback=retornarProdutos"></script><

Curso XIII - Unidade 08 - Inserção no BD via AJAX

Aula 497 a 499 - Identificar os dados do formulário / Adicionando a função $.ajax / Tratar os dados de retorno
Este exercício é semelhante ao feito anteriormente para inclusão de transportadoras. Aproveitei o arquivo das aulas anteriores (Aula 438) e fiz a separação conforme a nova estrutura.
Uma das primeiras coisas que se percebe é que a tag <form> não tem nem a ação nem o método de envio.
A ação de submit será feita utilizando o jQuery:

$('#formulario_transportadora').submit(function(e) {
e.preventDefault();
alert('teste');
})

Feito o teste da função vamos armazenar os dados do formulário em uma variável. Podemos verificar os dados digitados enviando um alert() para o navegador com os dados capturados. Para ver os dados podemos utilizar junto com a variável o método .serialize():

$('#formulario_transportadora').submit(function(e) {
e.preventDefault();
var formulario = $(this);
alert(formulario.serialize());
})

Agora que já estamos recuperando os dados do formulário através do evento submit precisamos criar a rotina do AJAX. Para isso vamos criar uma função ainda dentro da função do evento submit que irá executar a requisição AJAX.
Essa função foi atribuida a uma variável porém não é necessário (pelo menos até o momento).
A função criada vai criar uma requisição AJAX do tipo POST com os dados recebidos do formulário de forma serializada (com a função .serialize()) e transmitir para o arquivo com a rotina de inserção no BD:

$('#formulario_transportadora').submit(function(e) {
e.preventDefault();
var formulario = $(this);
var retorno = inserirFormulario(formulario);
});

function inserirFormulario(dados) {
$.ajax({
type: "POST",
data: dados.serialize(),
url: "inserir_transportadoras.php",
async: false
}).then(sucesso, falha);
}

Criamos agora no arquivo de comunicação com o BD uma variável para tratar o retorno da inserção de dados. Essa variável é um array que irá enviar alguns dados em caso de sucesso ou falha. Essa mensagem será enviada como um arquivo JSON utilizando a função json_encode().

$retorno = array();
if (!$insert_data) {
$retorno['sucesso'] = false;
$retorno['mensagem'] = 'Falha no sistema, tente mais tarde';
} else {
$retorno['sucesso'] = true;
$retorno['mensagem'] = 'Transportadora inserida com sucesso';
$retorno['nome'] = $nometransportadora;
}
echo json_encode($retorno);

A mensagem recebida é composta de um campo true / false e outro com a mensagem. Recebemos esse arquivo JSON e separamos os dados com o método .parseJSON(). Com esses dados separados fazemos o teste de sucesso/erro e enviamos a mensagem recebida (podemos inclusive enviar o nome da trasnportadora oui outros dados recebidos). Para apresentar os dados na tela utilizamos o método jQuery .show() para mostrar a <div> que está com a propriedade display: none

function sucesso(data) {
$sucesso = $.parseJSON(data)["sucesso"];
$transportadora = $.parseJSON(data)["nome"];
$mensagem = $.parseJSON(data)["mensagem"];
$('#mensagem').show();

if ($sucesso) {
$('#mensagem p').html($transportadora + ": " + $mensagem);
} else {
$('#mensagem p').html($mensagem);
}
}

Curso XIII - Unidade 09 - Alteração de dados via AJAX

Aula 500 a 501 - Mostrar arquivos da unidade / Adicionar função para retorno dos dados
Para o sistema de alteração fizemos basicamente o mesmo procedimento das aulas anteriores.
As instruções de alteração do BD foram as mesmas da aula de PHP com MySQL e as mensagens de retorno foram feitas da mesma forma que na aula anterior. A mudança nesse caso foi em relação ao sistema de retorno do AJAX e apenas para fins didáticos. Nessa aula utilizamos o método done/fail/always.
Note que utilizando esse sistema passamos o método .show() para mostrar a <div> da mensagem no método .always() pois ele sempre é executado.

Curso XIII - Unidade 10 - Excluir dados via AJAX

Aula 502 a 503 - Como excluir um elemento da lista / Como excluir um elemento do banco de dados
Na primeira parte dessa aula vamos remover os itens da lista de elementos, sem a interação com o banco de dados. Para isso utilizamos a seleção pelo JQuery, lembrando que a construção dessa lista é feita com uma repetição de <ul> para cada elemento do banco cujas <li>armazenam em linha os valores do nome da transportadora e cidade.
Desse modo selecionamos o elemento clicado com o evento .click() e executamos uma função que seleciona o elemento com this e sobe os níveis da árvore html utilizando o método .parent(). Para remover o elemento da lista (apenas na tela) utilizamos o método .fadeout().

$('#janela_transportadoras ul li a.excluir').click(function(e) {
e.preventDefault();
$(this).parent().parent().fadeOut();
})

A rotina de exclusão vai receber pelo método post o ID do registro a ser excluido. Para isso criamos um atributo na tag que aciona o evento (no caso a tag <a>) chamado title que irá receber o valor do ID.

<li><a href="" class="excluir" title="<?php echo $linha['transportadoraID'] ?>">Excluir</a></li>

Com isso passamos o valor do atributo title pelo AJAX através do método POST e executamos a exclusão da linha na lista em caso dee sucesso da exclusão no DB.
Entretanto, nesse caso, o this que foi utilizado para identificar o elemento clicado deixou de ter o valor esperado pois ele já está em outra função (como estamos na função de callback do método .done() do AJAX o this faz referencia ao retorno do POST).
Para ajustarmos isso atribuimos o valor do elemento quando selecionado a uma variável e aplicamnos o método .fadeout() nessa variável.

$('#janela_transportadoras ul li a.excluir').click(function(e) {
e.preventDefault();
var select = $(this).parent().parent();
var id = $(this).attr('title');

$.ajax({
type: "POST",
data: "transportadoraID=" + id,
url: "exclusao.php",
async: false
}).done(function(data) {
$sucesso = $.parseJSON(data)["sucesso"];
if ($sucesso) {
$(select).fadeOut();
} else {
console.log('Erro na exclusão');
}
})
.fail(function() {
console.log('Erro no sistema');
});
})

Curso XIII - Unidade 11 - Lista aninhada

Aula 504 - Preenchendo uma lista com dados dinâmicos
Para esse exemplo iremos criar duas listas que serão preenchidas com os dados do BD dinamicamente. Para isso temos dois arquivos de consulta que irão retornar um arquivo JSON com seus dados para serem incluidos no select.
O mais importante nessa aplicação é a utilização de callback no URL.
Quando carregamos a página inicial ela executa um script que chama o arquivo da primeira consulta e executa a função de callback com os dados retornados dela. Esses dados são executados na função de callback e geram a primeira lista de elementos.
Em seguida recuperamos o valor do elemento selecionado no menu utilizando o método .val() (esse método é o mesmo que o atributo value do elemento this, porém é acessado através do objeto jQuery $(this)).
Agora que temos o valor do elemento selecionado vamos fazer uma requisição AJAX no arquivo que fará a pesquisa da segunda consulta. Essa requisição será do tipo GET e enviará o valor do elemento selecionado como data. Note que nessa segunda operação, diferente da primeira, os dados retornam como JSON (na primeira o retorno é um array de dados criado a cada linha consultada no próprio arquivo de consulta), dessa forma devemos utilizar o método .parseJSON() para converter o arquivo em um array de dados.
Aula 506 - Lista itens da consulta
Para fazer a apresentação dos dados do segundo menu na tela fiz da mesma forma que o proposta na aula. A única diferença foi que nela foi criada uma tag <select> diretamente no html e os dados são inseridos dinamicamente. No meu projeto fiz a criação da tag pelo jQuery e nesse caso, precisei fazer a remoção do elemento a cada execução da função pois senão ele criava um novo elemento a cada atualização.

Curso XIII - Unidade Bonus - CEP e Previsão do Tempo

Aula 508 - Como utilizar serviço de CEP
Para utilização de CEP vamos utilizar o webservice ViaCEP. Para recuperar os dados de um CEP nessa API devemos fazer a requisição com o endereço:
https://viacep.com.br/ws/09195-350/json/

Passando a url desse modo obtemos como retorno os dados do endereço no formato JSON.
Fizemos como exemplo um sistema de consulta simples utilizando o AJAX para recuperar os dados:

var cep = '09195-350';
$.ajax({
type: "GET",
url: "https://viacep.com.br/ws/" + cep + "/json/",
async: false
}).done(function(data) {
console.log(data)
})

Aula 509 - Como aplicar o serviço em um formulário completo
Aqui utilizamos um formulário de cadastro simples para testar o preenchimento dos campos de forma automática com os dados recuperados da API. No exemplo da aula foi monitorado o evento .blur() que ocorre quando mudamos de campo no formulário. No meu exercício utilizei o evento .keyup() para contar quantos números foram digitados e executar a função quando tivermos digitado o número de caracteres necessários (no caso do CEP 8 dígitos sem o '-').
Fora essa diferença o resto ficou igual.

$('#cep').keyup(function() {
if ($('input#cep').val().length == 8) {
var cep = $('input#cep').val();
consultaCEP(cep)
};

function consultaCEP(cep) {
$.ajax({
type: "GET",
url: "https://viacep.com.br/ws/" + cep + "/json/",
async: false
}).done(function(data) {
console.log(data);
$('#endereco').val(data['logradouro']);
$('#bairro').val(data['bairro']);
$('#cidade').val(data['localidade']);
$('#estado').val(data['uf']);
}).fail(function() {
console.log('Erro');
})
}
})

Aula 510 - Como testar se o CEP é válido
Nessa aula fiz o código como apresentado na aula anterior. Para a validação do CEP foi criada uma expressão regular para verificar os dados digitados e em seguida é feito um teste nesse dado. Caso seja inválido apresenta uma mensagem de erro.
Aula 511 - Como utilizar serviço de PRevisão de tempo
Assim como na aula de busca de endereço pelo CEP, nessa aula vamos utilizar uma API, para esse exemplo OpenWeather. Essa API requer uma conta (não era necessário no tempo da aula) e uma chave de acesso para fazer as consultas.
Nesse caso apenas fizemos uma requisição AJAX fixa para a API e recebemos o objeto JSON. Com ele fizemos algumas consultas diretamente no console.

$.ajax({
type: 'GET',
url: 'https://api.openweathermap.org/data/2.5/weather?q=santo+andre,br&appid=24d1d5497f91525abcf060938067a36a&units=metric&lang=pt',
async: false
}).done(function(data) {
console.log(data);
console.log(data.main);
console.log(data.main.temp);
}).fail(function() {
console.log("erro");
})

Curso XIII - Unidade Bonus - CEP e Previsão do Tempo