E-commerce
mais simples do que parece




Michael Granados - @dgmike
Então...
você tem
uma idéia,
mas...


Por onde começar?
Seja rápido


Quanto mais tempo demorar para começar sua
startup mais você estará jogando dinheiro fora!

Inicie seu negócio enquanto antes, seu lucro só
 virá depois que você se lançar definitivamente

            Desenvolvimento ágil
Programador preguiçoso?
O seu trabalho é deixar com que as pessoas façam
                 menos esforços

           Inspire-se em você mesmo
Uma idéia!
e-commerce
E-commerce pronto?
●   Magento
●   Joomla + VirtueMart
●   WordPress + WP-shopping-cart
●   Django + Sathmo
●   Loja Locaweb
●   OsCommerce
●   PretaShop
●   ...
O ambiente
O ambiente
●   Sistema de controle de versão - GIT
●   Linguagem forte e madura – PHP
●   Banco de dados – MySQL
●   Servidor – Apache
Controle de versão – existem vários
●   Subversion
●   Bazaar
●   Git
●   Mercuial
●   CVS
Como funciona?
Como funciona?



       FTP
Como funciona?



                       FTP
Skywalker




              UPLOAD
Como funciona?



       FTP
Como funciona?
           Corrige BUG online


       FTP
Como funciona?



        FTP      Darth Vader




      UPLOAD
Como funciona?
REPOSITÓRIO
Como funciona?
    REPOSITÓRIO


                1




Skywalker   Darth Vader
Como funciona?
    REPOSITÓRIO


              1


             clone

1                 1
Como funciona?
    REPOSITÓRIO


              2



      push
2                 1
Como funciona?
    REPOSITÓRIO


              2



             push
2                 1
Como funciona?
    REPOSITÓRIO


              2




2                 1
Como funciona?
    REPOSITÓRIO


              2



             pull
2                   2
Como funciona?
    REPOSITÓRIO


              3



             push
2                 3
Como funciona?
REPOSITÓRIO                  SERVIDOR


                clone/pull



              push
Framework – vantagens
●   Métodos mágicos que auxiliam no
    desenvolvimento
●   Regras que ajudam a manter a organização
    dos arquivos – geralmente MVC
●   Gama de interfaces para bancos de dados
●   Helpers que libertam-te de escrever código
●   Scripts que geram boa parte do código
●   Gerenciamento de cache – deixando a
    aplicação mais rápida
Framework – desvantagens
●   Você precisa aprender uma nova lingua
●   O fato dos scripts gerarem boa parte do código
    interfere em sua criação
●   Regras que nem sempre se aplicam a seu
    negócio
●   Criação de demasiados arquivos que nem
    sempre são necessários
Frameworks - exemplos
●   Zend Framework
●   CodeIgniter
●   CakePHP
●   Synphony
●   Spaghetti*
●   VórticePHP
Proposta, um microframework

●   Público: github
●   Organização: MVC – Model, View, Control
●   Gerenciamento de URLs
O que o framework terá
●   Manipular Banco de Dados
●   Métodos mágicos definidos por você
●   Reaproveitamento de código
●   URLs amigáveis
●   Segurança
●   Fácil de entender
●   Simples de fazer manutenção
M de MVC – Model
Iremos usar PDO (PHP Database Object) como
base para o Model

●   Suporte para vários bancos de dados
●   Nativo desde o PHP5.2
●   Extensível
●   Orientado a Objetos
●   Fácil de usar
M de MVC – Model
Vários bancos, apenas um objeto


new PDO(‘mysql:dbname=banco;host=localhost’,
‘usuario’, ‘senha’);


new PDO(‘sqlite:/opt/database/mydb.sq3’);
Helper – pau pra toda obra!
function error() {
    die('Internal Server Error.');
}


function url($uri) {
    return BASE_URL.$uri;
}


function valor($numero) {
    return "R$ ".number_format($numero);
}
Mapeamento de URLs – URLs
            amigáveis
$urls = array(
     # 'Expressão regular'   => “Controller”
     '^/?$'                  => 'Inicio',
     '^/categoria/(d+)/?$' => 'Categoria',
     '^/produto/(d+)/?$'    => 'Produto',
);
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
Abracadabra: a mágica!
$url = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';


foreach ($urls as $regexp => $class) {
    if (preg_match("@$regexp@", $url, $atributos)) {
           if (class_exists($class)) {
               array_shift($atributos);
               $method = $_POST ? 'post' : 'get';
               $class   = new $class;
               call_user_func_array(array($class, $method), $atributos);
               die();
           }
    }
}
error();
O resultado!
class Inicio {
    function get($attr1, $attr2, $attr3) {
        // seu controller
    }
    function post() { // opcional


    }
}
O resultado!
class Inicio { # controller
    function get($attr1, $attr2, $attr3) {
        // seu controller
    }
    function post() { // opcional


    }
}
O resultado!
class Inicio {
    function get($attr1, $attr2, $attr3) {
        // seu controller
    }
    function post() { // opcional


    }
}
O resultado!
class Inicio {
    function get($attr1, $attr2, $attr3) {
        // seu controller
    }
    function post() { // opcional


    }
}
Template: aproveitando os métodos
             mágicos
Adicionando um produto
class Adiciona {

    public function get($id, $ajax = false) {

        $con =& get_con();

        if (!$con->produto($id)) {

            error();

        }

        if (isset($_SESSION['carrinho'][$id])) {

            $_SESSION['carrinho'][$id]++;

        } else {

            $_SESSION['carrinho'][$id] = 1;

        }

        header('Location: '.url('carrinho'));

    }

}
E-commerce pronto?!

Para que o e-commerce esteja pronto de fato, falta
apenas um detalhe: o comprador deve comprar




   Vamos por a mão na massa!!!
Formas de pagamento

Boleto bancário
Cartão de crédito
Cartões de débito
Transação entre contas...



... ou usar o PagSeguro
PagSeguro: como funciona?
PagSeguro: como funciona?
PagSeguro: como funciona?



          Pague com o
           PagSeguro
PagSeguro: como funciona?



Pague com o   POST
 PagSeguro
E o tal do retorno?


    Usuário - POST
E o tal do retorno?


    Usuário - POST




    Usuário - GET
E o tal do retorno?


       Usuário - POST




       Usuário - GET




Robô
POST
E o tal do retorno?


                 Usuário - POST




                 Usuário - GET



Bad Guy
 POST?    Robô
          POST
E o tal do retorno?


                 Usuário - POST




                 Usuário - GET

                 POST – TOKEN

Bad Guy
 POST?    Robô
          POST


                                  VERIFICADO/FALSO
Na pática, use a biblioteca

A Visie possui uma ótima biblioteca que gera o
formulário de forma simples


     http://visie.com.br/pagseguro/php.php


          http://github.com/pagseguro
#comofas?

require_once('pagseguro/pgs.php');
$cod = uniqid(true);
$pgs = new Pgs(array(
      'email_cobranca' => 'mike@visie.com.br',
      'tipo'     => 'CP',
      'ref_transacao' => $cod,
));
#comofas?
foreach ($_SESSION['carrinho'] as $id => $qtd) {
            $produto = $con->produto($id);
            $pgs->adicionar(array(
                   'id'          => $produto->id,
                   'descricao'   => $produto->nome,
                   'valor'       => $produto->valor,
                   'quantidade' => $qtd,
             ));
}
Melhoria: brincando com JS

$pgs->mostra(array(
      'open_form' => false,
      'show_submit' => false
));


document.forms[0].submit();
#comofas Retorno automático

Use o cod_referencia
Passo final: Publicando!

Com o controle de versão e um servidor bom,
tudo fica mais fácil!
Faça o clone do projeto no servidor
Import do banco de dados
Divulgue!
Links

http://dgmike.com.br/dgeco
http://slideshare.com/dgmike
http://github.com/dgmike/dgeco
Referências
http://php.net/
http://br.php.net/pdo
http://github.com/
http://learn.github.com/
http://visie.com.br/pagseguro
http://www.generatedata.com/
http://tinyurl.com/mkmu58 (W3C: HTML5)
Perguntas?!


http://meadiciona.com/dgmike
 http://formspring.me/dgmike
         @dgmike

Ecommerce, mais simples do que parece

  • 1.
    E-commerce mais simples doque parece Michael Granados - @dgmike
  • 2.
  • 3.
    Seja rápido Quanto maistempo demorar para começar sua startup mais você estará jogando dinheiro fora! Inicie seu negócio enquanto antes, seu lucro só virá depois que você se lançar definitivamente Desenvolvimento ágil
  • 4.
    Programador preguiçoso? O seutrabalho é deixar com que as pessoas façam menos esforços Inspire-se em você mesmo
  • 5.
  • 6.
    E-commerce pronto? ● Magento ● Joomla + VirtueMart ● WordPress + WP-shopping-cart ● Django + Sathmo ● Loja Locaweb ● OsCommerce ● PretaShop ● ...
  • 7.
  • 8.
    O ambiente ● Sistema de controle de versão - GIT ● Linguagem forte e madura – PHP ● Banco de dados – MySQL ● Servidor – Apache
  • 9.
    Controle de versão– existem vários ● Subversion ● Bazaar ● Git ● Mercuial ● CVS
  • 10.
  • 11.
  • 12.
    Como funciona? FTP Skywalker UPLOAD
  • 13.
  • 14.
    Como funciona? Corrige BUG online FTP
  • 15.
    Como funciona? FTP Darth Vader UPLOAD
  • 16.
  • 17.
    Como funciona? REPOSITÓRIO 1 Skywalker Darth Vader
  • 18.
    Como funciona? REPOSITÓRIO 1 clone 1 1
  • 19.
    Como funciona? REPOSITÓRIO 2 push 2 1
  • 20.
    Como funciona? REPOSITÓRIO 2 push 2 1
  • 21.
    Como funciona? REPOSITÓRIO 2 2 1
  • 22.
    Como funciona? REPOSITÓRIO 2 pull 2 2
  • 23.
    Como funciona? REPOSITÓRIO 3 push 2 3
  • 24.
    Como funciona? REPOSITÓRIO SERVIDOR clone/pull push
  • 25.
    Framework – vantagens ● Métodos mágicos que auxiliam no desenvolvimento ● Regras que ajudam a manter a organização dos arquivos – geralmente MVC ● Gama de interfaces para bancos de dados ● Helpers que libertam-te de escrever código ● Scripts que geram boa parte do código ● Gerenciamento de cache – deixando a aplicação mais rápida
  • 26.
    Framework – desvantagens ● Você precisa aprender uma nova lingua ● O fato dos scripts gerarem boa parte do código interfere em sua criação ● Regras que nem sempre se aplicam a seu negócio ● Criação de demasiados arquivos que nem sempre são necessários
  • 27.
    Frameworks - exemplos ● Zend Framework ● CodeIgniter ● CakePHP ● Synphony ● Spaghetti* ● VórticePHP
  • 28.
    Proposta, um microframework ● Público: github ● Organização: MVC – Model, View, Control ● Gerenciamento de URLs
  • 29.
    O que oframework terá ● Manipular Banco de Dados ● Métodos mágicos definidos por você ● Reaproveitamento de código ● URLs amigáveis ● Segurança ● Fácil de entender ● Simples de fazer manutenção
  • 30.
    M de MVC– Model Iremos usar PDO (PHP Database Object) como base para o Model ● Suporte para vários bancos de dados ● Nativo desde o PHP5.2 ● Extensível ● Orientado a Objetos ● Fácil de usar
  • 31.
    M de MVC– Model Vários bancos, apenas um objeto new PDO(‘mysql:dbname=banco;host=localhost’, ‘usuario’, ‘senha’); new PDO(‘sqlite:/opt/database/mydb.sq3’);
  • 32.
    Helper – paupra toda obra! function error() { die('Internal Server Error.'); } function url($uri) { return BASE_URL.$uri; } function valor($numero) { return "R$ ".number_format($numero); }
  • 33.
    Mapeamento de URLs– URLs amigáveis $urls = array( # 'Expressão regular' => “Controller” '^/?$' => 'Inicio', '^/categoria/(d+)/?$' => 'Categoria', '^/produto/(d+)/?$' => 'Produto', );
  • 34.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 35.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 36.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 37.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 38.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 39.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 40.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 41.
    Abracadabra: a mágica! $url= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/'; foreach ($urls as $regexp => $class) { if (preg_match("@$regexp@", $url, $atributos)) { if (class_exists($class)) { array_shift($atributos); $method = $_POST ? 'post' : 'get'; $class = new $class; call_user_func_array(array($class, $method), $atributos); die(); } } } error();
  • 42.
    O resultado! class Inicio{ function get($attr1, $attr2, $attr3) { // seu controller } function post() { // opcional } }
  • 43.
    O resultado! class Inicio{ # controller function get($attr1, $attr2, $attr3) { // seu controller } function post() { // opcional } }
  • 44.
    O resultado! class Inicio{ function get($attr1, $attr2, $attr3) { // seu controller } function post() { // opcional } }
  • 45.
    O resultado! class Inicio{ function get($attr1, $attr2, $attr3) { // seu controller } function post() { // opcional } }
  • 46.
    Template: aproveitando osmétodos mágicos
  • 47.
    Adicionando um produto classAdiciona { public function get($id, $ajax = false) { $con =& get_con(); if (!$con->produto($id)) { error(); } if (isset($_SESSION['carrinho'][$id])) { $_SESSION['carrinho'][$id]++; } else { $_SESSION['carrinho'][$id] = 1; } header('Location: '.url('carrinho')); } }
  • 48.
    E-commerce pronto?! Para queo e-commerce esteja pronto de fato, falta apenas um detalhe: o comprador deve comprar Vamos por a mão na massa!!!
  • 49.
    Formas de pagamento Boletobancário Cartão de crédito Cartões de débito Transação entre contas... ... ou usar o PagSeguro
  • 50.
  • 51.
  • 52.
    PagSeguro: como funciona? Pague com o PagSeguro
  • 53.
    PagSeguro: como funciona? Paguecom o POST PagSeguro
  • 54.
    E o taldo retorno? Usuário - POST
  • 55.
    E o taldo retorno? Usuário - POST Usuário - GET
  • 56.
    E o taldo retorno? Usuário - POST Usuário - GET Robô POST
  • 57.
    E o taldo retorno? Usuário - POST Usuário - GET Bad Guy POST? Robô POST
  • 58.
    E o taldo retorno? Usuário - POST Usuário - GET POST – TOKEN Bad Guy POST? Robô POST VERIFICADO/FALSO
  • 59.
    Na pática, usea biblioteca A Visie possui uma ótima biblioteca que gera o formulário de forma simples http://visie.com.br/pagseguro/php.php http://github.com/pagseguro
  • 60.
    #comofas? require_once('pagseguro/pgs.php'); $cod = uniqid(true); $pgs= new Pgs(array( 'email_cobranca' => 'mike@visie.com.br', 'tipo' => 'CP', 'ref_transacao' => $cod, ));
  • 61.
    #comofas? foreach ($_SESSION['carrinho'] as$id => $qtd) { $produto = $con->produto($id); $pgs->adicionar(array( 'id' => $produto->id, 'descricao' => $produto->nome, 'valor' => $produto->valor, 'quantidade' => $qtd, )); }
  • 62.
    Melhoria: brincando comJS $pgs->mostra(array( 'open_form' => false, 'show_submit' => false )); document.forms[0].submit();
  • 63.
  • 64.
    Passo final: Publicando! Como controle de versão e um servidor bom, tudo fica mais fácil! Faça o clone do projeto no servidor Import do banco de dados Divulgue!
  • 65.
  • 66.
  • 67.