Desenvolvendo uma aplicação Multicamadas em Visual Basic .NET – Parte 2 Camada Intermediária e Apresentação

Continuação do exemplo de uma aplicação para um Disk-Pizza. Tem como objetivo explorar o conceito de programação em multicamadas em VB.NET

Camada Intermediária

Esse artigo é o segundo de uma série de três (03) artigos que apresentam um exemplo prático e simples abordando o desenvolvimento em camadas em VB.NET, sabemos que a programação orientada a objetos (POO) possibilita uma abordagem simples para a utilização de dados usando objetos.

No primeiro artigo apresentamos um cenário para o desenvolvimento da aplicação e criamos o Banco de Dados com as respectivas tabelas e o mapeamento Entidade Relacionamento entre elas. Chamamos o conjunto de dados dentro de um DataSet, que denominamos como sendo nossa camada de dados.

Nesse artigo criaremos as classes da camada “2 – Camada Intermediaria” que representam a lógica de negócio (regras de negócio) e a lógica do controlador (classe que faz a interface com os dados). Essa camada, deve assegurar a confiabilidade dos dados antes que o servidor de Banco de Dados atualize ou exiba as informações ao cliente do aplicativo (camada de apresentação).

Sabe-se que de acordo com as necessidades atuais das empresas e alterações constantes na legislação, as classes facilitam a atualização das aplicações bem como permitem o reuso do código.

Nossa Camada de Negócios, isola as regras, da interface do sistema. Essa camada funciona como intermediária entre os dados da camada “1 – Camada de Dados” e a camada “3 – Camada de Apresentação” cliente do aplicativo.

Iniciaremos também a criação da última camada “3 – Camada de Apresentação”. Onde são apresentados os formulários de clientes e de pesquisa genérica.

Figura 1. Camadas da Aplicação Exemplo

Vamos começar organizando o nosso projeto. Para isso abra o projeto desenvolvido no Artigo “Desenvolvendo uma aplicação Multicamadas em Visual Basic .NET – Parte 1 Camada de Dados”.

Adicione uma nova pasta ao projeto, clique com o botão direito do mouse sobre a solução, selecione Add New Folder. Dê o nome para essa pasta de “2 – Camada Intermediaria” (sem acento).

Crie uma subpasta na pasta “2 – Camada Intermediaria” chamada “2.1 – Logica Controlador” e outra “2.2 – Logica Negocios” (sem acento).

Vamos adicionar a nossa primeira classe, que será responsável pelo controle dos dados. Chamaremos essa classe de clsDados.vb.

Clique com o botão direito sobre “2.1 – Logica Controlador” e selecione Add .. Class .. Dê o nome de clsDados.vb para essa classe. Conforme figura.

Repita o procedimento para a criação das seguintes classes, agora na subpasta “2.2 – Logica Negocios”. Classes essas que comporão a lógica de negócio.Veja a figura

Depois de organizado o nosso projeto, vamos ao código da Classe de Dados, clsDados.vb. Classe genérica que utilizaremos para fazer a interface entre a classe de negócios e a camada de dados. Nela poderemos realizar as operações básicas de banco de dados, como: inclusão, alteração, consulta e exclusão.

Revisando: A orientação a objetos usa classes para encapsular variáveis de instância (dados) e métodos (comportamentos).

Digitar o código abaixo na classe clsDados.vb. Dê um duplo clique sobre o nome do arquivo e digite. Se preferir, é claro, copie.

Classe - Camada de Dados (Lidar diretamente com os dados) Imports System.Data Imports System.Data.SqlClient Public Class ClsDados Dim strConexao As String = My.Settings.cnPizza Private Function AbrirBanco() As SqlConnection Dim cn As New SqlConnection cn.ConnectionString = strConexao cn.Open() Return cn End Function Private Sub FecharBanco(ByVal cn As SqlConnection) If cn.State = ConnectionState.Open Then cn.Close() End If End Sub Public Sub ExecutarComando(ByVal strQuery As String) Dim cn As New SqlConnection() Try Abrir o banco de dados e passar os parametros da consulta SQL, parametros e ordem de execução. cn = AbrirBanco() Dim cmdCommand As New SqlCommand With cmdCommand .CommandText = strQuery.ToString .CommandType = CommandType.Text .Connection = cn .ExecuteNonQuery() End With Catch ex As Exception Throw ex Finally FecharBanco(cn) End Try End Sub Public Function RetornarDataSet(ByVal strQuery As String) As DataSet Dim cn As New SqlConnection() Try Abrir o banco de dados e passar os parametros da consulta SQL, parametros e ordem de execução. cn = AbrirBanco() Dim cmdCommand As New SqlCommand With cmdCommand .CommandText = strQuery.ToString .CommandType = CommandType.Text .Connection = cn .ExecuteNonQuery() End With Declarado um dataadapter e um dataset passar o comando para o dtAdapter e carregar o dataset com resultado da busca Dim dtAdapter As New SqlDataAdapter Dim dsDataSet As New DataSet With dtAdapter .SelectCommand = cmdCommand .Fill(dsDataSet) End With Retorna o Dataset Return dsDataSet Catch ex As Exception Throw ex Finally FecharBanco(cn) End Try End Function Public Function RetornarIdNumerico(ByVal strQuery As String) As Integer Dim cn As New SqlConnection() Try Abrir o banco de dados e passar os parametros da consulta SQL, parametros e ordem de execução e retorna um inteiro. cn = AbrirBanco() Dim cmdCommand As New SqlCommand With cmdCommand .CommandText = strQuery.ToString .CommandType = CommandType.Text .Connection = cn End With Dim dtReader As SqlDataReader dtReader = cmdCommand.ExecuteReader() Dim codigo As Integer If dtReader.Read() Then codigo = dtReader(0) + 1 End If Return codigo Catch ex As Exception Throw ex Finally FecharBanco(cn) End Try End Function Public Function RetornarValorTotal(ByVal strQuery As String) As Decimal Dim cn As New SqlConnection() Try */Abrir o banco de dados e passar os parametros da consulta SQL, parametros e ordem de execução e retorna um inteiro./* cn = AbrirBanco() Dim cmdCommand As New SqlCommand With cmdCommand .CommandText = strQuery.ToString .CommandType = CommandType.Text .Connection = cn End With Dim dtReader As SqlDataReader dtReader = cmdCommand.ExecuteReader() Dim ValorTotal As Decimal If dtReader.Read() Then ValorTotal = dtReader(0) End If Return ValorTotal Catch ex As Exception Throw ex Finally FecharBanco(cn) End Try End Function End Class

Vamos agora criar a classe Clientes, definindo os campos membros, atributos/propriedade e métodos. Como boa prática de programação as variáveis de instância da classe estarão definida como PRIVATE, sendo acessíveis apenas aos membros da classe. Utilizaremos métodos de acesso para exibir ou ler os dados.

Classe Cliente. clnClientes.vb Imports System.Text Imports System.Data.SqlClient Public Class clnClientes Campos membros Private mIdCliente As Integer Private mNomeRazao As String Private mEndereco As String Private mBairro As String Private mCep As String Private mTelefone As String Private mCidade As String Private mEstado As String Private mObservacoes As String atributos Public Property IdCliente() As Integer Get Return mIdCliente End Get Set(ByVal value As Integer) mIdCliente = value End Set End Property Public Property NomeRazao() As String Get Return mNomeRazao End Get Set(ByVal value As String) mNomeRazao = value End Set End Property Public Property Endereco() As String Get Return mEndereco End Get Set(ByVal value As String) mEndereco = value End Set End Property Public Property Bairro() As String Get Return mBairro End Get Set(ByVal value As String) mBairro = value End Set End Property Public Property Cep() As String Get Return mCep End Get Set(ByVal value As String) mCep = value End Set End Property Public Property Telefone() As String Get Return mTelefone End Get Set(ByVal value As String) mTelefone = value End Set End Property Public Property Cidade() As String Get Return mCidade End Get Set(ByVal value As String) mCidade = value End Set End Property Public Property Estado() As String Get Return mEstado End Get Set(ByVal value As String) mEstado = value End Set End Property Public Property Observacoes() As String Get Return mObservacoes End Get Set(ByVal value As String) mObservacoes = value End Set End Property

Métodos da Classe Clientes.

Public Sub Buscar() Dim cSql As String cSql = "Select * From Clientes Where IdCliente=" & mIdCliente Dim ds As DataSet Dim DtPizza As New ClsDados() ds = DtPizza.RetornarDataSet(cSql) If ds.Tables(0).Rows.Count > 0 Then IdCliente = ds.Tables(0).Rows(0).Item(0) NomeRazao = ds.Tables(0).Rows(0).Item(1) Endereco = ds.Tables(0).Rows(0).Item(2) Bairro = ds.Tables(0).Rows(0).Item(3) Cep = ds.Tables(0).Rows(0).Item(4) Telefone = ds.Tables(0).Rows(0).Item(5) Cidade = ds.Tables(0).Rows(0).Item(6) Estado = ds.Tables(0).Rows(0).Item(7) Observacoes = ds.Tables(0).Rows(0).Item(8) End If End Sub Public Function BuscarId() As Integer Dim cSql As String cSql = "Select Top 1 (IdCliente) From Clientes order by IdCliente desc" Dim IdBuscado As Integer Dim DtPizza As New ClsDados() IdBuscado = DtPizza.RetornarIdNumerico(cSql) Return IdBuscado End Function Public Sub Editar() Dim strQuery As New StringBuilder strQuery.Append("Update Clientes ") strQuery.Append("set ") strQuery.Append("IdCliente=") strQuery.Append(mIdCliente) strQuery.Append(", NomeRazao=") strQuery.Append(mNomeRazao) strQuery.Append(", Endereco=") strQuery.Append(mEndereco) strQuery.Append(", Bairro=") strQuery.Append(mBairro) strQuery.Append(", Cep=") strQuery.Append(mCep) strQuery.Append(", Cidade=") strQuery.Append(mCidade) strQuery.Append(", Estado=") strQuery.Append(mEstado) strQuery.Append(", Observacoes=") strQuery.Append(mObservacoes) strQuery.Append("") strQuery.Append(" where IdCliente=") strQuery.Append(mIdCliente & ";") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Excluir() Dim strQuery As New StringBuilder strQuery.Append("Delete From Clientes ") strQuery.Append("where IdCliente=") strQuery.Append(mIdCliente) Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Sub Gravar() Dim strQuery As New StringBuilder strQuery.Append("Insert into Clientes ") strQuery.Append(" (") strQuery.Append("IdCliente,") strQuery.Append("NomeRazao,") strQuery.Append("Endereco,") strQuery.Append("Bairro,") strQuery.Append("Cep,") strQuery.Append("telefone,") strQuery.Append("Cidade,") strQuery.Append("Estado,") strQuery.Append("Observacoes") strQuery.Append(") ") strQuery.Append(" VALUES (") strQuery.Append(mIdCliente) strQuery.Append(", " & mNomeRazao & "") strQuery.Append(", " & mEndereco & "") strQuery.Append(", " & mBairro & "") strQuery.Append(", " & mCep & "") strQuery.Append(", " & mTelefone & "") strQuery.Append(", " & mCidade & "") strQuery.Append(", " & mEstado & "") strQuery.Append(", " & mObservacoes & "") strQuery.Append(");") Dim BancoPizza As New ClsDados() BancoPizza.ExecutarComando(strQuery.ToString) End Sub Public Function Pesquisar(ByVal Campo As String, _ ByVal Parametro As String, ByVal Valor As String, _ ByVal tipo As String) As DataSet Dim strQuery As New StringBuilder strQuery.Append("Select * From Clientes ") strQuery.Append("where " & Campo & " ") strQuery.Append(Parametro & " ") strQuery.Append(Valor) Dim a As String = strQuery.ToString() Dim ds As DataSet Dim BancoPizza As New ClsDados() ds = BancoPizza.RetornarDataSet(strQuery.ToString) Return ds End Function End Class

Como bom exercício para entendimento, você poderá implementar a Classe de Produtos, seguindo como modelo a classe de clientes. Caso queira, anexei essa classe em downloads.

Vamos voltar à organização do nosso projeto e criar uma nova pasta para organização do projeto, que conterá os objetos da Terceira e última camada de nossa aplicação, ou seja, a “3 – Camada Apresentacao” sem acento. Veja figura:

Arraste o Form1.vb e Renomeie-o para FrmClientes.vb.

Crie a interface abaixo, nomeando os controles (TextBox) conforme abaixo:

Defina os nomes dos botões acrescentando o prefixo cmd nos nomes: cmdIncluir, cmdAlterar, cmdExcluir, cmdCancelar e cmdPesquisar.

Adicionando um módulo para utilização nesse projeto. Colocaremos nele as rotinas gerais. O Módulo deve estar fora da pasta “3 – Camada de Apresentação” para uma melhor organização.

Clique com o botão direito sobre o nome do projeto e selecione Add.. Module.., dê o nome para esse módulo de: modGlobal.vb.

Acrescente o código abaixo dentro do módulo criado.

Public Sub Limpar(ByRef f As GroupBox) For Each ctl As Control In f.Controls If TypeOf ctl Is TextBox Then ctl.Text = "" If TypeOf ctl Is ComboBox Then ctl.Text = "" Next ctl End Sub Public Sub ParaGravar(ByRef f As GroupBox) For Each ctl As Control In f.Controls If ctl.Name = "cmdIncluir" Then ctl.Enabled = True End If If ctl.Name = "cmdCancelar" Then ctl.Enabled = True End If If ctl.Name = "cmdAlterar" Then ctl.Enabled = False End If If ctl.Name = "cmdExcluir" Then ctl.Enabled = False End If Next End Sub Public Sub ParaAlterar(ByRef f As GroupBox) For Each ctl As Control In f.Controls If ctl.Name = "cmdIncluir" Then ctl.Enabled = False End If If ctl.Name = "cmdCancelar" Then ctl.Enabled = False End If If ctl.Name = "cmdAlterar" Then ctl.Enabled = True End If If ctl.Name = "cmdExcluir" Then ctl.Enabled = True End If Next End Sub Public Sub Liberar(ByRef f As GroupBox) For Each ctl As Control In f.Controls If ctl.Name = "cmdPesquisar" Then ctl.Enabled = True Else ctl.Enabled = False End If Next End Sub

Explicação das rotinas do módulo acima. O primeiro procedimento (Limpar), recebe como parâmetro a referência do GroupBox do formulário de envio (por exemplo: Clientes) e limpa todos os controles TextBox dentro do conteiner Groupbox referenciado. O segundo procedimento (ParaGravar) e o terceiro (ParaAlterar) recebe como parâmetro a referência do GroupBox onde se encontram os botões e os trata respectivamente habilitando ou desabilitando o controle conforme o caso. O último (liberar) trata o botão pesquisar.

Agora, vamos aos códigos que responderão aos eventos dos usuários. O formulário de clientes deverá funcionar da seguinte maneira: assim que o formulário for carregado o usuário deverá digitar o código do cliente, se existir o cliente, cujo código tenha sido digitado, será exibido os seus dados no formulário e os botões: alterar, excluir e pesquisar, deverão ficar habilitados, incluir e cancelar deverão ficar desabilitado, caso não exista o campo receberá a palavra e os botões: incluir, cancelar, pesquisar ficarão habilitados e os demais desabilitados.

Código do que responderá ao evento LostFocus do IdClienteTextBox (ao perder o foco):

If IdClienteTextBox.Text.Trim = Nothing Then Exit Sub End If IdClienteTextBox.Enabled = False Dim Clientes As New clnClientes Clientes.IdCliente = IdClienteTextBox.Text Clientes.Buscar() If Clientes.NomeRazao <> "" Then IdClienteTextBox.Text = Clientes.IdCliente NomeRazaoTextBox.Text = Clientes.NomeRazao EnderecoTextBox.Text = Clientes.Endereco BairroTextBox.Text = Clientes.Bairro CepTextBox.Text = Clientes.Cep TelefoneTextBox.Text = Clientes.Telefone CidadeTextBox.Text = Clientes.Cidade EstadoTextBox.Text = Clientes.Estado ObservacoesTextBox.Text = Clientes.Observacoes ParaAlterar(GroupBox2) Else IdClienteTextBox.Text = "<AUT>" NomeRazaoTextBox.Text = "" EnderecoTextBox.Text = "" BairroTextBox.Text = "" CepTextBox.Text = "" TelefoneTextBox.Text = "" CidadeTextBox.Text = "" EstadoTextBox.Text = "" ObservacoesTextBox.Text = "" ParaGravar(GroupBox2) End If

Agora vamos ao código que deverá responder ao evento click do botão Incluir.

Dim incluir As New clnClientes() If IdClienteTextBox.Text.Trim = Nothing Then MsgBox("Identificação do cliente necessária", 16, "Erro") Exit Sub End If If IdClienteTextBox.Text = "<AUT>" Then busca o último código cadastrado Dim busca As New clnClientes() incluir.IdCliente = busca.BuscarId() End If incluir.NomeRazao = NomeRazaoTextBox.Text incluir.Endereco = EnderecoTextBox.Text incluir.Bairro = BairroTextBox.Text incluir.Cep = CepTextBox.Text incluir.Telefone = TelefoneTextBox.Text incluir.Cidade = CidadeTextBox.Text incluir.Estado = EstadoTextBox.Text incluir.Observacoes = ObservacoesTextBox.Text Try incluir.Gravar() Catch ex As Exception MsgBox("Ocorreu o erro: " & ex.Message) Limpar(GroupBox1) Exit Sub End Try MsgBox("Cliente Cadastrado com o código:" & incluir.IdCliente, 64, "Sucesso") Limpar(GroupBox1) Liberar(GroupBox2) IdClienteTextBox.Enabled = True

Agora vamos ao código que deverá responder ao evento click do botão Alterar.

Dim alterar As New clnClientes() If IdClienteTextBox.Text.Trim = Nothing Then MsgBox("Identificação do cliente necessária", 16, "Erro") Exit Sub End If alterar.IdCliente = IdClienteTextBox.Text alterar.NomeRazao = NomeRazaoTextBox.Text alterar.Endereco = EnderecoTextBox.Text alterar.Bairro = BairroTextBox.Text alterar.Cep = CepTextBox.Text alterar.Telefone = TelefoneTextBox.Text alterar.Cidade = CidadeTextBox.Text alterar.Estado = EstadoTextBox.Text alterar.Observacoes = ObservacoesTextBox.Text Try alterar.Editar() Catch ex As Exception MsgBox("Ocorreu o erro: " & ex.Message) Limpar(GroupBox1) Exit Sub End Try MsgBox("Cadastro Alterado com Sucesso", 64, "Aviso") Limpar(GroupBox1) Liberar(GroupBox2) IdClienteTextBox.Enabled = True

Código que responderá ao evento click no botão Excluir.

Dim Excluir As New clnClientes Excluir.IdCliente = IdClienteTextBox.Text Excluir.NomeRazao = NomeRazaoTextBox.Text Dim ret As Integer ret = MsgBox("Deseja excluir: " & _ Excluir.NomeRazao & " ?", 36, "Atenção") If ret = vbYes Then Excluir.Excluir() MsgBox("Registro Excluído com Sucesso", 64, "Aviso") Else MsgBox("Operação Cancelada", 64, "Aviso") End If Limpar(GroupBox1) Liberar(GroupBox2) IdClienteTextBox.Enabled = True

Código que responderá ao evento click no botão Cancelar.

Limpar(GroupBox1) Liberar(GroupBox2) IdClienteTextBox.Enabled = True

Agora para finalizar esse artigo, adicione na pasta “3 – Camada Apresentação” um novo Formulário. Dê o nome de FrmConsulta.vb

Arraste para o formulário FrmConsulta os seguintes objetos 02 groupboxs, 03 labels, 02 combobox, 01 textbox, 01 button. Conforme figura:

Altere as propriedades dos objetos do formulário conforme quadro:

Objeto Propriedade Valor
ComboBox1 NAME
DROPDOWNSTYLE
cmbCampo
DropDownList
ComboBox2 NAME
DROPDOWNSTYLE
cmbParam
DropDownList
TextBox1 NAME TxtBusca
Button1 NAME cmdFiltrar
DataGridView1 NAME Dgv1
Tabela 1. Os controles do tipo GroupBox não precisam alterar a propriedade NAME

Alterne para o formulário FrmClientes e adicione o código que responde ao evento click no botão pesquisar.

FrmConsulta.Text = "Pesquisa dados de Clientes" FrmConsulta.Tag = "Clientes" Aqui guardamos o nome da tabela FrmConsulta.Show()

Alterne agora para o formulário FrmConsulta e adicione o código para o evento Load do formulário FrmConsulta.

Dim ds As New DataSet Dim Busca As New ClsDados ds = Busca.RetornarDataSet("Select * From " & Me.Tag) cmbCampo.Items.Clear() Dim i As Integer For i = 0 To ds.Tables(0).Columns.Count - 1 cmbCampo.Items.Add(ds.Tables(0).Columns(i).ColumnName.ToString) Next i Me.Dgv1.AutoGenerateColumns = True Me.Dgv1.DataSource = ds.Tables(0)

No evento acima (Load do FrmConsulta) realizamos uma busca da tabela (genérica) pois o código servirá para qualquer consulta a tabela. Dentro do laço for, adicionamos a cada passagem no loop o nome de campo ao controle cmbCampo.

Agora assim que o usuário escolher o campo para pesquisa, criaremos uma rotina para adicionar os parâmetros possíveis para o tipo de campo selecionado.

Defina uma variável local para o todo o formulário FrmConsulta.vb, é só colocá-la após a declaração da classe, como abaixo:

Public Class FrmConsulta Dim tipoCampo As System.Type

Agora digite o código abaixo para o evento SelectedIndexChanged, do cmbCampo.

Dim ds As New DataSet tipoCampo = Me.Dgv1.Columns(cmbCampo.SelectedIndex).ValueType If tipoCampo.ToString = "System.Int32" Then cmbParam.Items.Clear() cmbParam.Items.Add("=") cmbParam.Items.Add(">") cmbParam.Items.Add(">=") cmbParam.Items.Add("<") cmbParam.Items.Add("<=") cmbParam.Items.Add("<>") End If If tipoCampo.ToString = "System.String" Then cmbParam.Items.Clear() cmbParam.Items.Add("=") cmbParam.Items.Add("Começa com") cmbParam.Items.Add("Termina em") cmbParam.Items.Add("Tem a palavra") End If

Nota sobre o código acima: ele deve ser melhorado para tratar todos os tipos de campos possíveis, eu só tratei os dois tipos que estão definidos na tabela de clientes.

Para finalizar o conteúdo desse artigo, vamos ao código que responderá ao evento click do Botão Pesquisar.

Dim campo As String = cmbCampo.Text Dim parametro As String = cmbParam.Text Dim valor As String = TxtBusca.Text Dim tipo As String = tipoCampo.ToString Dim ds As New DataSet Verificar formulário origem pelo TAG do FrmConsulta If Me.Tag = "Clientes" Then Dim BuscaClientes As New clnClientes Ps: Não há a necessidade de fazer tratamento para os campos numéricos ------------------- Para tipos String If tipo = "System.String" Then Verificar formulário origem pelo TAG do FrmConsulta If parametro = "Tem a palavra" Then parametro = "Like " valor = "%" & valor & "%" End If If parametro = "=" Then valor = "" & valor & "" End If If parametro = "Começa com" Then parametro = "Like " valor = "" & valor & "%" End If If parametro = "Termina em" Then parametro = "Like " valor = "%" & valor & "" End If End If ds = BuscaClientes.Pesquisar(campo, parametro, valor, tipo) Me.Dgv1.AutoGenerateColumns = True Me.Dgv1.DataSource = ds.Tables(0) End If

Esse foi o segundo artigo de uma série de três (03) artigos os quais apresentam um exemplo prático e simples abordando o desenvolvimento em camadas em VB.NET, sabemos que a programação orientada a objetos (POO) possibilita uma abordagem simples para a utilização de dados usando objetos.

Nesse artigo foram criadas as classes da camada “2 – Camada Intermediaria” e iniciada a construção da “3 – Camada de Apresentação”.

Gostaria de receber comentários da comunidade devmedia, para que eu possa melhorá-lo. Um abraço e até o próximo artigo.


Links Úteis

  • Curso de Xamarin: Primeiros passos:
    O Xamarin é uma plataforma para desenvolvimento de aplicações móveis dentro da plataforma .NET, utilizando o C#.
  • Curso de Lógica de Programação:
    Neste curso veremos uma introdução a algoritmos, utilizando como linguagem de apoio o Portugol. Para isso, abordaremos assuntos como descrição narrativa, fluxogramas e pseudocódigos, fundamentais para quem está iniciando na programação.
  • Como aprender PHP:
    Neste Guia de Consulta você encontrará todo o conteúdo que precisa para aprender PHP, uma linguagem de programação amplamente utilizada para a construção de aplicações web.

Saiba mais sobre Visual Basic ;)

Artigos relacionados