34
TWIG L. Gustavo A. TWIG Gustavo Almeida

Aprimore seus templates com TWIG - Mini Curso PHP Conf 2016

Embed Size (px)

Citation preview

TWIGL. Gustavo A.

TWIG

Gustavo Almeida

Prazer, meu nome é Gustavo!

Porque aprender mais uma linguagem ?1. Ajuda a separar dados e apresentação (MVC).2. Fim das short open tags do PHP7.3. Contemplado por : Symfony, Drupal8, eZPublish, phpBB, Piwik, OroCRM,Slim,

Yii, Laravel, Codeigniter and Kohana.4. Pre-req : PHP 5.2.7+

Do fabricante (Symphony) :● Fast: Twig compiles templates down to plain optimized PHP code. The

overhead compared to regular PHP code was reduced to the very minimum.

● Secure: Twig has a sandbox mode to evaluate untrusted template code. This allows Twig to be used as a template language for applications where users may modify the template design.

● Flexible: Twig is powered by a flexible lexer and parser. This allows the developer to define their own custom tags and filters, and to create their own DSL.

Na prática - Imagine trocar isto

Por isso

<?php● composer e inicialização (twig, pdo, etc)● busque no servidor oq eu preciso● se for o caso analise $_POST, $_GET● faça as contas necessárias● jogue nas variáveis

extends ‘principal.twig’

{% for … %}{{ dados }}{% endfor %}use aqui as tags html sem medo de ser feliz

echo $twig->render(‘listagem.twig’, [‘produtos’=>$produtos,...

]);

MYSQL

Metodologia TWIG

Instalando via Composerphp -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e115a8dc7871f15d853148a7fbac7da27d6c0030b848d9b3dc09e2a0388afed865e6a3d6b3c0fad45c48e2b5fc1196ae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"php composer-setup.phpphp composer-setup.phpphp -r "unlink('composer-setup.php');"

composer require "twig/twig:~1.0"

The ~ operator example:

~1.2 is equivalent to >=1.2 <2.0.0

Twig_Autoloader::register();

Ex. prático : Estrutura de diretorios

Banco de dadosCREATE TABLE `categorias` (

`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`nome` VARCHAR(40) NOT NULLPRIMARY KEY (`id`)

)

CREATE TABLE `produtos` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,`nome` VARCHAR(80) NOT NULL COLLATE 'utf8_swedish_ci',`preco` FLOAT NOT NULL,`prazo` VARCHAR(10) NOT NULL COLLATE 'utf8_swedish_ci',`estoque` INT(11) NOT NULL,`peso` FLOAT NOT NULL DEFAULT '0',`categ_id` INT(11) NOT NULL,PRIMARY KEY (`id`)

)

Hello World com TWIG

sintaxe

{{ printar coisas }}

{% fazer coisas %}

{# comentários #}

if e for{% for produto in produtos %}

{{ produto.nome }} por R$ {{ produto.preco }}

{% if produto.estoque > 0 %}

pronta-entrega

{% endif %}

{% endfor %}

variáveis{% set total=0 %}

{{ total }}

{% set nome=”Gustavo Almeida” %}

{{ nome }}

{% set items=[‘fogao’,’geladeira’,’tv’] %}

{{ items.1 }}

block, include e extendsCom block eu defino no bloco pai, o trecho que vai ser herdado dos filhos.

{% block conteúdo %}{% endblock %}

Com extends eu defino qual será o bloco pai.

{% extends “main.html” %}

Exemplo - usar include para incluir o menu de categs.

{% include ‘categs.html’ %}

block, include e extends

PAGINA MODELO

includes ‘menu.twig’

block conteudo

PAGINA FILHA

endblock

extends ‘modelo.twig’

block, include e extends

global (carrinho, login)

categs

global

include

conteudo dinamico

{% block content %}

{% endblock %}

main.twig

global$twig->addGlobal(‘carrinho’,$_SESSION[‘carrinho’]);

$twig->addGlobal(‘login’,$_SESSION[‘login’]);

Usando as variáveis global :

{% if login %} Estou logado {% else %} fazer login {% endif %}

Se for um array posso inclusive obter o nome do usuario

{{ login.nome }} ou {{ login.imagem }}

macro{% macro input(name,value,type,size) %}

<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}">

{% endmacro %}

usando as macros :

{% import 'forms.twig' as forms %}

Login : {{ forms.input('login') }}

filters{{ nome|upper }}

{{ idade|default(30) }}

{{ 9800.333|number_format(2, '.', ',') }}

{{ [1, 2, 3]|join('|') }}

Muitas funções do PHP migram para os filtros

url_encode, trim, sort, splitround, slice ...

index.php com TWIGrequire __DIR__.'/../../vendor/autoload.php';require 'init.php'; Twig_Autoloader::register();$loader = new Twig_Loader_Filesystem('views');$twig = new Twig_Environment($loader);require 'model/produto_model.php';#globals.php

$produtos = getProductsByRand(12);echo $twig->render('index.twig', array('produtos' => $produtos));$cn->close();

index.twig{% extends main.twig %}

{% block content %}

{% for produto in produtos %}

<p>{{ produto.nome }}></p>

<h5>R$ {{ produto.preco }}</h5>

{% endfor %}

{% endblock %}

categ.twig<ul class="nav list-group">

{% for categoria in categorias %}

<li>

<a href="listagem.php?id={{categoria.id}}"> {{categoria.nome}} </a>

</li>

{% endfor %}

</ul>

{% includes “categ.twig” %}

detalhes.phpinclude 'twig.php';

include 'model/produtos_model.php';

$id = (int) $_GET['id'];

$produtos = getProdutosById($id);

echo $twig->render('detalhes.twig', array('produto' => $produto));

detalhes.twig{% extends "main.twig" %}{% block content %}

{% if produto %} <div class="col-md-12"> <div class="card"> <img src="http://lorempixel.com/450/450/sports/5" class="img-fluid rounded"> <h1>{{ produto.nome }}</h1> <h5>R$ {{ produto.preco }} - {{ produto.disponib }}</h5> </div> </div>{% else %} <h1>Produto Indisponivel ou com erro.</h1>{% endif %}

{% endblock %}

cart.php<?phpif(!isset($_SESSION[‘cart’])){

$_SESSION[‘cart’]=[];}if(isset($_REQUEST[‘action’])){

$id=$_GET[‘id’];switch $_REQUEST[‘action’]{

case ‘add’:$item = getProductById($id);$item[‘qtd’]=1;$_SESSION[‘cart’][$id]=$item;

break;case ‘del’:

unset($_SESSION[‘cart’][$id]);break;

}}echo $twig->render(‘cart.twig’,[ ‘cart’=>$_SESSION[‘cart’] ]);

$twig->addGlobal(‘cart’,$_SESSION[‘cart’);# ……

{% for item in cart %}{{ item.qtd }} {{ item.nome }} - R$ {{ item.preco }} <a

href=#>X</a><br>{% else %}

Vazio{% endfor %}

carrinho.twig{% extends "main.twig" %}{% block content %} <table class="table table-striped table-hover table-bordered table-condensed"> <tr> <th>ID</th> ... <th>Total</th> <th>Del</th> </tr>{% set subtotal=0 %}{% set frete=12 %}{% for index,item in carrinho %} <tr> <td>{{ item.id }}</td> <td>{{ item.preco }}</td> <td>X</td> </tr> {# subtotal = subtotal + (item.qtd*item.preco) #}{% else %} <h1>Carrinho vazio</h1>{% endfor %}{% set total = subtotal + frete %} <tr class="warning"> <td colspan="4">SubTotal</td> <td colspan="2">{{ subtotal }}</td> </tr> <tr>

{% endblock %}

LOOP

Cabeçalho tabela

Totais

admin.php<?phpif(isset($_REQUEST[‘action’])){

switch $_REQUEST[‘action’]{case ‘add’:

$set = parseParamsPost($_POST);$q = sprintf(“INSERT CATEGS SET %s”,$set);$cn->exec($q);

break;case ‘del’:

$q = sprintf(“DELETE FROM CATEGS WHERE id=%d”,$id);break;case ‘upd’:

$q = sprintf(“UPDATE CATEGS SET %s WHERE id=%d,$set,$id)”;break;

}}echo $twig->render(‘admin.twig’,[ ‘categs’=>$categs ]);

function parseParamsPost(array $post){$set = “”;foreach($post as $k=>$v){

$set .= “$k= ‘$v’”;}return $set;

}

admin.twig{% extends 'main.twig' %}{% block content %}<table class="table table-striped table-hover table-bordered table-condensed">

<tr> <th>id</th> <th>nome</th> <th>upd</th> <th>del</th> </tr><tr class="table-info"><form method=post action="?a=add">

<td>X</td><td><input name="nome"></td><td colspan=2><button class="btn btn-success">ADD</button></td>

</form></tr>

{% for index,categ in categs %}<tr>

<form method=post action=”?a=upd”><td><input type=hidden name='id' value="{{categ.id}}">{{categ.id}}</td><td><input name='nome' class='form-control' value="{{categ.nome}}"></td><td><button class='btn btn-info'>UPD</button></td></form><td>X</td>

</tr>{% else %}<tr><td colspan=4>Sem registros</td></tr>{% endfor %}</table>{% endblock %}

LOOP

REG. NOVO

login.php<?phpif($_SERVER[‘REQUEST_METHOD’]===’POST’){

$erros=[];if(!isset($_POST[‘login’])){

$erros[‘login’]=”login nao informado”;break;

}

if(!$_POST[‘login’]===’adm’){$erros[‘login’]=”login nao encontrado”;

}

if(!$_POST[‘senha’]===’123’){$erros[‘senha’]=”senha invalida/inconsistente”;

}

$_SESSION[‘logado’]= empty($erros)? ’sim’ : null;redirect(‘cadastro.php’);

}echo $twig->render(‘login.twig’,[ ‘erros’=>$erros ]);

$twig->addGlobal(‘logado’,$_SESSION[‘logado’);# ……

{% if logado == “sim” %}Ola, {{ logado.user }}<a href=#>Logout</a>

{% else %}<a href=#>Login</a>

{% endif %}

login.twig{% extends "main.twig" %}{% block content %}

{% import 'macros.twig' as forms %}

<form method="POST" name="login" action="?a=login"> <legend>Ja sou Cliente</legend> {{ forms.input('login') }} {{ forms.input('senha') }} <button class="btn btn-lg btn-success-outline">Login</button></form>

<form method="POST" name="novo" action="?a=novo"> <legend>Não sou Cliente</legend> <input class="form-control" name="login" placeholder="Email"> <input name="cep" class="form-control" placeholder="CEP"> <button class="btn btn-lg btn-success-outline">Cadastrar</button> </form>

{% endblock %}

Certificação em twig

github: lga37slideshare: lga33br.linkedin.com/in/lga37