├── .gitattributes ├── .gitignore ├── CNAME ├── LICENSE ├── README.md ├── Vagrantfile ├── _config.yml ├── _includes └── welcome.md ├── _layouts ├── default.html └── page.html ├── _posts ├── 01-01-01-Getting-Started.md ├── 01-02-01-Use-the-Current-Stable-Version.md ├── 01-03-01-Built-in-Web-Server.md ├── 01-04-01-Mac-Setup.md ├── 01-05-01-Windows-Setup.md ├── 01-06-01-Common-Directory-Structure.md ├── 02-01-01-Code-Style-Guide.md ├── 03-01-01-Language-Highlights.md ├── 03-02-01-Programming-Paradigms.md ├── 03-03-01-Namespaces.md ├── 03-04-01-Standard-PHP-Library.md ├── 03-05-01-Command-Line-Interface.md ├── 03-06-01-XDebug.md ├── 04-01-01-Dependency-Management.md ├── 04-02-01-Composer-and-Packagist.md ├── 04-03-01-PEAR.md ├── 05-01-01-Coding-Practices.md ├── 05-02-01-The-Basics.md ├── 05-03-01-Date-and-Time.md ├── 05-04-01-Design-Patterns.md ├── 05-05-01-PHP-and-UTF8.md ├── 06-01-01-Dependency-Injection.md ├── 06-02-01-Basic-Concept.md ├── 06-03-01-Complex-Problem.md ├── 06-04-01-Containers.md ├── 06-05-01-Further-Reading.md ├── 07-01-01-Databases.md ├── 07-02-01-Interacting-via-Code.md ├── 07-03-01-Abstraction-Layers.md ├── 08-01-01-Templating.md ├── 08-02-01-Benefits.md ├── 08-03-01-Plain-PHP-Templates.md ├── 08-04-01-Compiled-Templates.md ├── 08-05-01-Further-Reading.md ├── 09-01-01-Errors-and-Exceptions.md ├── 09-02-01-Errors.md ├── 09-03-01-Exceptions.md ├── 10-01-01-Security.md ├── 10-02-01-Web-Application-Security.md ├── 10-03-01-Password-Hashing.md ├── 10-04-01-Data-Filtering.md ├── 10-05-01-Configuration-Files.md ├── 10-06-01-Register-Globals.md ├── 10-07-01-Error-Reporting.md ├── 11-01-01-Testing.md ├── 11-02-01-Test-Driven-Development.md ├── 11-03-01-Behavior-Driven-Development.md ├── 11-04-01-Complementary-Testing-Tools.md ├── 12-01-01-Servers-and-Deployment.md ├── 12-02-01-Platform-as-a-Service.md ├── 12-03-01-Virtual-or-Dedicated-Servers.md ├── 12-04-01-Shared-Servers.md ├── 12-05-01-Building-your-Application.md ├── 13-01-01-Virtualization.md ├── 13-02-01-Vagrant.md ├── 13-03-01-Docker.md ├── 14-01-01-Caching.md ├── 14-02-01-Bytecode-Cache.md ├── 14-03-01-Object-Caching.md ├── 15-01-01-Resources.md ├── 15-02-01-Frameworks.md ├── 15-03-01-Components.md ├── 15-04-01-Books.md ├── 16-01-01-Community.md └── 17-01-01-PHPDoc.md ├── banners.md ├── images ├── banners │ ├── btn1-120x90.png │ ├── btn2-120x60.png │ ├── leaderboard-728x90.png │ ├── lg-rect-386x280.png │ ├── med-rect-300x250.png │ ├── rect-180x150.png │ ├── sq-btn-125x125.png │ └── vert-rect-240x400.png ├── favicon.png ├── nmc-logo.gif └── og-logo.png ├── index.html ├── notas_de_traducao.md ├── pages ├── Design-Patterns.md ├── Functional-Programming.md ├── The-Basics.md └── example.md ├── scripts └── setup.js ├── sitemap.xml ├── styles ├── all.css ├── all.less ├── base │ ├── all.less │ ├── bars-buttons.less │ ├── buttons.less │ ├── grid.less │ ├── idioms.less │ ├── prefixer.less │ ├── reset.less │ ├── spacing.less │ ├── typography.less │ └── variables.less ├── print.css ├── site │ ├── site-content.less │ ├── site-footer.less │ ├── site-header.less │ ├── site-navigation.less │ └── variables.less └── syntax.css └── vagrant.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ##################### 2 | ## Project Specifics 3 | ##################### 4 | 5 | /_site/ 6 | *.DS_Store 7 | /.vagrant 8 | 9 | ################# 10 | ## JetBrains 11 | ################# 12 | 13 | /.idea 14 | *.iml 15 | 16 | ################# 17 | ## Eclipse 18 | ################# 19 | 20 | *.pydevproject 21 | .project 22 | .metadata 23 | bin/ 24 | tmp/ 25 | *.tmp 26 | *.bak 27 | *.swp 28 | *~.nib 29 | local.properties 30 | .classpath 31 | .settings/ 32 | .loadpath 33 | 34 | # External tool builders 35 | .externalToolBuilders/ 36 | 37 | # Locally stored "Eclipse launch configurations" 38 | *.launch 39 | 40 | # CDT-specific 41 | .cproject 42 | 43 | # PDT-specific 44 | .buildpath 45 | 46 | 47 | ################# 48 | ## Visual Studio 49 | ################# 50 | 51 | ## Ignore Visual Studio temporary files, build results, and 52 | ## files generated by popular Visual Studio add-ons. 53 | 54 | # User-specific files 55 | *.suo 56 | *.user 57 | *.sln.docstates 58 | 59 | # Build results 60 | 61 | [Dd]ebug/ 62 | [Rr]elease/ 63 | x64/ 64 | build/ 65 | [Bb]in/ 66 | [Oo]bj/ 67 | 68 | # MSTest test Results 69 | [Tt]est[Rr]esult*/ 70 | [Bb]uild[Ll]og.* 71 | 72 | *_i.c 73 | *_p.c 74 | *.ilk 75 | *.meta 76 | *.obj 77 | *.pch 78 | *.pdb 79 | *.pgc 80 | *.pgd 81 | *.rsp 82 | *.sbr 83 | *.tlb 84 | *.tli 85 | *.tlh 86 | *.tmp 87 | *.tmp_proj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.log 94 | *.scc 95 | 96 | # Visual C++ cache files 97 | ipch/ 98 | *.aps 99 | *.ncb 100 | *.opensdf 101 | *.sdf 102 | *.cachefile 103 | 104 | # Visual Studio profiler 105 | *.psess 106 | *.vsp 107 | *.vspx 108 | 109 | # Guidance Automation Toolkit 110 | *.gpState 111 | 112 | # ReSharper is a .NET coding add-in 113 | _ReSharper*/ 114 | *.[Rr]e[Ss]harper 115 | 116 | # TeamCity is a build add-in 117 | _TeamCity* 118 | 119 | # DotCover is a Code Coverage Tool 120 | *.dotCover 121 | 122 | # NCrunch 123 | *.ncrunch* 124 | .*crunch*.local.xml 125 | 126 | # Installshield output folder 127 | [Ee]xpress/ 128 | 129 | # DocProject is a documentation generator add-in 130 | DocProject/buildhelp/ 131 | DocProject/Help/*.HxT 132 | DocProject/Help/*.HxC 133 | DocProject/Help/*.hhc 134 | DocProject/Help/*.hhk 135 | DocProject/Help/*.hhp 136 | DocProject/Help/Html2 137 | DocProject/Help/html 138 | 139 | # Click-Once directory 140 | publish/ 141 | 142 | # Publish Web Output 143 | *.Publish.xml 144 | *.pubxml 145 | 146 | # NuGet Packages Directory 147 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 148 | #packages/ 149 | 150 | # Windows Azure Build Output 151 | csx 152 | *.build.csdef 153 | 154 | # Windows Store app package directory 155 | AppPackages/ 156 | 157 | # Others 158 | sql/ 159 | *.Cache 160 | ClientBin/ 161 | [Ss]tyle[Cc]op.* 162 | ~$* 163 | *~ 164 | *.dbmdl 165 | *.[Pp]ublish.xml 166 | *.pfx 167 | *.publishsettings 168 | 169 | # RIA/Silverlight projects 170 | Generated_Code/ 171 | 172 | # Backup & report files from converting an old project file to a newer 173 | # Visual Studio version. Backup files are not needed, because we have git ;-) 174 | _UpgradeReport_Files/ 175 | Backup*/ 176 | UpgradeLog*.XML 177 | UpgradeLog*.htm 178 | 179 | # SQL Server files 180 | App_Data/*.mdf 181 | App_Data/*.ldf 182 | 183 | ############# 184 | ## Windows detritus 185 | ############# 186 | 187 | # Windows image file caches 188 | Thumbs.db 189 | ehthumbs.db 190 | 191 | # Folder config file 192 | Desktop.ini 193 | 194 | # Recycle Bin used on file shares 195 | $RECYCLE.BIN/ 196 | 197 | # Mac crap 198 | .DS_Store 199 | 200 | 201 | ############# 202 | ## Python 203 | ############# 204 | 205 | *.py[co] 206 | 207 | # Packages 208 | *.egg 209 | *.egg-info 210 | dist/ 211 | build/ 212 | eggs/ 213 | parts/ 214 | var/ 215 | sdist/ 216 | develop-eggs/ 217 | .installed.cfg 218 | 219 | # Installer logs 220 | pip-log.txt 221 | 222 | # Unit test / coverage reports 223 | .coverage 224 | .tox 225 | 226 | #Translations 227 | *.mo 228 | 229 | #Mr Developer 230 | .mr.developer.cfg -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | br.phptherightway.com 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Josh Lockhart 2 | 3 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP: Do Jeito Certo 2 | 3 | ## Sobre 4 | 5 | Este é o repositório GitHub Pages para o projeto _PHP: Do Jeito Certo_, tradução brasileira do projeto _PHP: The Right Way_. 6 | 7 | * Este website é um projeto Jekyll. 8 | * Cada seção e sub-seção são arquivos Markdown em `_posts/`. 9 | * Sub-seções possuem `isChild: true` em seu front matter. 10 | * Navegação e estrutura de páginas são geradas automaticamente. 11 | 12 | ## Espalhe a palavra! 13 | 14 | _PHP: Do Jeito Certo_ possui banners que você pode usar em seu site. Para mostrar seu apoio, deixe que novos desenvolvedores PHP saibam onde encontrar boas informações! 15 | 16 | [Banners para divulgação](http://br.phptherightway.com/banners.html) 17 | 18 | ## Como contribuir 19 | 20 | 1. Fork e edite 21 | 2. Instale opcionalmente [Ruby](https://rvm.io/rvm/install/) com [Jekyll](https://github.com/mojombo/jekyll/) gem para visualizar 22 | 3. Envie um pull request para consideração 23 | 24 | [Instalar utilizando o Vagrant](vagrant.md) 25 | 26 | ## Guia de Estilo para o Contribuidor 27 | 28 | 1. Use a ortografia do Português do Brasil neste repositório. 29 | 2. Use quatro (4) espaços para indentar o texto; não use TAB. 30 | 3. Limite o texto em 120 caracteres. 31 | 4. Os exemplos de código devem seguir a [PSR-1](http://www.php-fig.org/psr/psr-1/) ou superior. 32 | 33 | ## Onde 34 | 35 | 36 | 37 | * [English](http://www.phptherightway.com) 38 | * [Deutsch](http://rwetzlmayr.github.io/php-the-right-way) 39 | * [Español](http://phpdevenezuela.github.io/php-the-right-way) 40 | * [Français](http://eilgin.github.io/php-the-right-way/) 41 | * [Indonesia](http://id.phptherightway.com) 42 | * [Italiano](http://it.phptherightway.com) 43 | * [Polski](http://pl.phptherightway.com) 44 | * [Português do Brasil](http://br.phptherightway.com) 45 | * [Română](https://bgui.github.io/php-the-right-way/) 46 | * [Slovenščina](http://sl.phptherightway.com) 47 | * [Srpski](http://phpsrbija.github.io/php-the-right-way/) 48 | * [Türkçe](http://hkulekci.github.io/php-the-right-way/) 49 | * [български](http://bg.phptherightway.com) 50 | * [Русский язык](http://getjump.github.io/ru-php-the-right-way) 51 | * [Українська](http://iflista.github.com/php-the-right-way) 52 | * [العربية](https://adaroobi.github.io/php-the-right-way/) 53 | * [فارسى](http://novid.github.io/php-the-right-way/) 54 | * [ภาษาไทย](https://apzentral.github.io/php-the-right-way/) 55 | * [한국어판](http://modernpug.github.io/php-the-right-way) 56 | * [日本語](http://ja.phptherightway.com) 57 | * [简体中文](http://laravel-china.github.io/php-the-right-way/) 58 | * [繁體中文](http://laravel-taiwan.github.io/php-the-right-way) 59 | 60 | 61 | ## Traduções 62 | 63 | Se você tem interesse em traduzir _PHP: The Right Way_, faça o fork do repo no GitHub e publique seu fork para sua 64 | própria conta do GitHub. Nós vamos vincular sua tradução a partir do documento principal. 65 | 66 | Para evitar fragmentação e confusão para o leitor, por favor escolha uma destas opções: 67 | 68 | 1. Vincularemos seu fork com a sua GitHub Page `[username].github.com/php-the-right-way` 69 | 2. Vincularemos seu fork com a sua GitHub Page com um subdomínio (por exemplo, "br.phptherightway.com") 70 | 71 | Se você usa um subdomínio, coloque-o no arquivo `CNAME`, e avise-nos para configurar o DNS para você. Se não usa um 72 | subdomínio, apague o arquivo `CNAME` senão seu fork não vai fazer o build quando for publicado. 73 | 74 | Quando sua tradução estiver pronta, abra uma issue no Isse Tracker para nos avisar. 75 | 76 | [Notas de tradução](notas_de_traducao.md) 77 | 78 | ## Por que? 79 | 80 | Têm havido muita discussão ultimamente sobre como a comunidade PHP carece de informação válida e suficiente para programadores novos no PHP. Este repositório busca resolver este problema. 81 | 82 | ## Quem 83 | 84 | Meu nome é [Josh Lockhart](http://twitter.com/codeguy). Sou o autor do [Slim Framework](http://www.slimframework.com/) e trabalho para a [New Media Campaigns](http://www.newmediacampaigns.com/). 85 | 86 | ## Colaboradores 87 | 88 | * [Kris Jordan](http://krisjordan.com/) 89 | * [Phil Sturgeon](http://philsturgeon.co.uk/) 90 | 91 | ## Licença 92 | 93 | [Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/) 94 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "precise32" 3 | config.vm.box_url = "http://files.vagrantup.com/precise32.box" 4 | config.vm.network :forwarded_port, guest: 4000, host: 4000 5 | 6 | $script = < 33 | 34 | 35 | 49 |
50 | 51 | 52 | Faça fork no GitHub 55 | 56 | 57 | 65 | {{ content }} 66 | 90 |
91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% if page.title %}{{ page.title }} - {% endif %}PHP: Do Jeito Certo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 29 | 30 | 31 |
32 | 33 |
Do Jeito Certo.
34 | Voltar ao início 35 | 36 | Faça fork no GitHub 37 | 38 |
39 |
40 |
Você está lendo conteúdo extra sobre…
41 | {{ content }} 42 | 47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /_posts/01-01-01-Getting-Started.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Começando 3 | anchor: comecando 4 | --- 5 | 6 | # Começando {#comecando_title} -------------------------------------------------------------------------------- /_posts/01-02-01-Use-the-Current-Stable-Version.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Use a versão estável atual (8.0) 3 | isChild: true 4 | anchor: use_a_versao_estavel_atual 5 | --- 6 | 7 | ## Use a versão estável atual (8.0) {#use_a_versao_estavel_atual_title} 8 | 9 | Se você está começando com PHP, comece com a versão estável atual do [PHP 8.1][php-release]. O PHP 8.x adiciona 10 | muitas [novas funcionalidades](#destaques_da_linguagem) às versões 7.x e 5.x mais antigas. O motor foi amplamente 11 | reescrito, e o PHP agora é ainda mais rápido do que as versões mais antigas. O PHP 8 é uma grande atualização da 12 | linguagem e contém muitas novas funcionalidades e otimizações. 13 | 14 | Você deveria tentar atualizar rapidamente para a última versão estável - o PHP 15 | 7.4 [já está em fim de vida](http://php.net/supported-versions.php). A atualização é fácil, pois não há 16 | muitas [quebras de compatibilidade][php-bc]. Se você não tiver certeza em qual versão uma função ou recurso está, você 17 | pode verificar a documentação do PHP no site php.net. 18 | 19 | [php-release]: http://php.net/downloads.php 20 | 21 | [php-docs]: http://php.net/manual/ 22 | 23 | [php-bc]: http://php.net/manual/migration80.incompatible.php 24 | -------------------------------------------------------------------------------- /_posts/01-03-01-Built-in-Web-Server.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Servidor web embutido 3 | isChild: true 4 | anchor: servidor_web_embutido 5 | --- 6 | 7 | ## Servidor web embutido {#servidor_web_embutido_title} 8 | 9 | Com a versão PHP 5.4+, você pode começar a aprender PHP sem os problemas de instalar e configurar um servidor web. Para 10 | iniciar o servidor, execute o seguinte comando no seu terminal dentro da raiz de seu projeto: 11 | 12 | {% highlight console %} 13 | > php -S localhost:8000 14 | {% endhighlight %} 15 | 16 | * [Saiba mais sobre o servidor web embutido, pela linha de comando][cli-server] 17 | 18 | [cli-server]: http://php.net/manual/pt_BR/features.commandline.webserver.php 19 | -------------------------------------------------------------------------------- /_posts/01-04-01-Mac-Setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instalação no Mac 3 | isChild: true 4 | anchor: instalacao_no_mac 5 | --- 6 | 7 | ## Instalação no Mac {#instalacao_no_mac_title} 8 | 9 | O macOS já vem com o PHP, mas ele é normalmente um pouco atrasado em relação à última versão estável. Existem várias 10 | maneiras de instalar a última versão do PHP no macOS. 11 | 12 | ### Instalar PHP via Homebrew 13 | 14 | [Homebrew] é um gerenciador de pacotes para MacOS que ajuda você a instalar facilmente o PHP e várias extensões. O 15 | repositório central Homebrew fornece "fórmulas" para o PHP 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0 e o PHP 8.1. Instale a última 16 | versão com este comando: 17 | 18 | ``` 19 | brew install php@8.1 20 | ``` 21 | 22 | Você pode alternar entre as versões do PHP do Homebrew modificando a variável `PATH`. Alternativamente você pode usar 23 | o [brew-php-switcher][brew-php-switcher] para alternar as versões PHP automaticamente. 24 | 25 | Você também pode alternar entre as versões do PHP manualmente desvinculando e vinculando a versão desejada: 26 | 27 | ``` 28 | brew unlink php 29 | brew link --overwrite php@8.0 30 | ``` 31 | 32 | ``` 33 | brew unlink php 34 | brew link --overwrite php@8.1 35 | ``` 36 | 37 | ### Instalar PHP via Macports 38 | 39 | O projeto [MacPorts] é uma iniciativa da comunidade de código aberto para projetar um sistema fácil de usar para 40 | compilar, instalar e atualizar softwares pela linha de comando, X11 ou software de código aberto baseado em Aqua no 41 | sistema operacional OS X. 42 | 43 | O MacPorts suporta binários pré-compilados, portanto, você não precisa recompilar todas as dependências dos arquivos tar 44 | de origem, ele agiliza sua vida se você não tiver nenhum pacote instalado no seu sistema. 45 | 46 | Neste momento, você pode instalar `php54`, `php55`, `php56`, `php70`, `php71`, `php72`, `php73`, `php74`, `php80` ou `php81` 47 | usando o comando `port install`, como por exemplo: 48 | 49 | ``` 50 | sudo port install php74 51 | sudo port install php81 52 | ``` 53 | 54 | E você pode utilizar o comando `select` para trocar a versão ativa do PHP: 55 | 56 | ``` 57 | sudo port select --set php php81 58 | ``` 59 | 60 | ### Instalar PHP via phpbrew 61 | 62 | [phpbrew] é uma ferramenta para instalar e gerenciar múltiplas versões do PHP. Isso pode ser realmente útil se duas 63 | diferentes aplicações/projetos precisam de diferentes versões do PHP e você não está usando máquinas virtuais. 64 | 65 | ### Instalar PHP via instalador binário da Liip's 66 | 67 | Outra opção popular é o [php-osx.liip.ch] que fornece métodos de instalação para versões PHP da 5.3 até a 7.3. Ele não 68 | substitui os binários do PHP instalados pela Apple, mas instala tudo em uma localização separada (/usr/local/php5). 69 | 70 | ### Compilar do código fonte 71 | 72 | Outra opção que lhe dá o controle sobre a versão do PHP você instalar, é [compilar o código fonte][mac-compile]. Nesse 73 | caso, certifique-se de ter instalado o [Xcode][xcode-gcc-substitution] ou o substituto da 74 | Apple ["Command Line Tools for XCode"] que pode ser encontrado no _Apple's Mac Developer Center_. 75 | 76 | ### Instaladores _All-in-One_ 77 | 78 | As soluções listadas acima lidam apenas com o PHP e não fornecem coisas como [Apache][apache], [Nginx][nginx] ou um 79 | servidor SQL. As soluções _All-in-one_ como [MAMP][mamp-downloads] e [XAMPP][xampp] vão instalar estes outros programas 80 | para você e amarrá-los todos juntos, mas a facilidade de configuração compromete a flexibilidade. 81 | 82 | [Homebrew]: https://brew.sh/ 83 | 84 | [Homebrew PHP]: https://github.com/Homebrew/homebrew-php#installation 85 | 86 | [MacPorts]: https://www.macports.org/install.php 87 | 88 | [phpbrew]: https://github.com/phpbrew/phpbrew 89 | 90 | [php-osx.liip.ch]: https://php-osx.liip.ch/ 91 | 92 | [mac-compile]: https://secure.php.net/install.macosx.compile 93 | 94 | [xcode-gcc-substitution]: https://github.com/kennethreitz/osx-gcc-installer 95 | 96 | ["Command Line Tools for XCode"]: https://developer.apple.com/downloads 97 | 98 | [apache]: https://httpd.apache.org/ 99 | 100 | [nginx]: https://www.nginx.com/ 101 | 102 | [mamp-downloads]: https://www.mamp.info/en/downloads/ 103 | 104 | [xampp]: https://www.apachefriends.org/ 105 | 106 | [brew-php-switcher]: https://github.com/philcook/brew-php-switcher 107 | -------------------------------------------------------------------------------- /_posts/01-05-01-Windows-Setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instalação no Windows 3 | isChild: true 4 | anchor: instalacao_no_windows 5 | --- 6 | 7 | ## Instalação no Windows {#instalacao_no_windows_title} 8 | 9 | Você pode fazer o download dos binários no site [windows.php.net/download][php-downloads]. Depois de extrair o arquivo 10 | baixado, é recomendado incluir na variável [PATH][windows-path] a pasta raiz do seu PHP (onde o arquivo php.exe está 11 | localizado). Dessa forma você pode executar o PHP de qualquer lugar. 12 | 13 | Para aprender e desenvolver localmente, você pode utilizar o servidor web embutido do PHP 5.4+, de forma que você não 14 | precisa se preocupar em configurá-lo. Se você prefere um "pacote completo" que inclui um servidor web e MySQL, então 15 | ferramentas como [XAMPP][xampp], [EasyPHP][easyphp], [OpenServer][openserver] 16 | e [WAMP][wamp] irão te ajudar a montar rapidamente um ambiente de desenvolvimento em Windows. Dito isso, estas 17 | ferramentas serão um pouco diferentes das ferramentas em produção, portanto tenha cuidado quanto às diferenças de 18 | ambiente caso esteja trabalhando em Windows e publicando em Linux. 19 | 20 | Caso você precise rodar seu ambiente de produção em Windows, então o IIS7 vai lhe dar mais estabilidade e melhor 21 | performance. Você pode usar o [phpmanager][phpmanager] (um plugin GUI para o IIS7) para tornar a configuração e o 22 | gerenciamento do PHP mais simples. O IIS7 vem com o FastCGI embutido e pronto para uso, você só precisa configurar o PHP 23 | como handler. Para suporte e mais recursos, existe uma [área dedicada no iis.net][php-iis] ao PHP. 24 | 25 | Geralmente rodar sua aplicação em ambientes diferentes para desenvolvimento e produção podem levar a bugs estranhos 26 | enquanto estiverem rodando. Se você está desenvolvendo no Windows e irá fazer deploy no Linux (ou qualquer outro 27 | ambiente não Windows) então você deveria considerar usar uma [Máquina Virtual](/#virtualizacao_title). 28 | 29 | Chris Tankersley tem uma postagem muito útil em quais ferramentas ele usa para 30 | o [Desenvolvimento PHP usando Windows][windows-tools]. 31 | 32 | [easyphp]: https://www.easyphp.org/ 33 | [phpmanager]: http://phpmanager.codeplex.com/ 34 | [openserver]: https://ospanel.io/ 35 | [wamp]: https://www.wampserver.com/en/ 36 | [php-downloads]: https://windows.php.net/download/ 37 | [php-iis]: https://php.iis.net/ 38 | [windows-path]: https://www.windows-commandline.com/set-path-command-line/ 39 | [windows-tools]: https://ctankersley.com/2016/11/13/developing-on-windows-2016/ 40 | [xampp]: https://www.apachefriends.org/ -------------------------------------------------------------------------------- /_posts/01-06-01-Common-Directory-Structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Estrutura Padrão de Diretório 3 | isChild: true 4 | anchor: estrutura_padrao_diretorio 5 | --- 6 | 7 | ## Estrutura Padrão de Diretório {#estrutura_padrao_diretorio_title} 8 | 9 | Uma pergunta comum entre quem está começando com programação para a web é: "onde coloco minhas coisas?". Ao longo dos 10 | anos, esta resposta tem sido sempre "onde está o `DocumentRoot` (a raiz do diretório)". Embora esta resposta não seja 11 | completa, é um ótimo lugar para começar. 12 | 13 | Por razões de segurança, os arquivos de configuração não devem ser acessíveis por visitantes de um site; portanto, os 14 | scripts públicos são mantidos em um diretório público e as configurações e dados privados são mantidos fora desse 15 | diretório. 16 | 17 | Para cada time, CMS ou estrutura em que se trabalha, uma estrutura de diretório padrão é usada por cada uma dessas 18 | entidades. Entretanto, se alguém está iniciando um projeto por conta própria, saber qual estrutura de diretórios usar 19 | pode ser assustador. 20 | 21 | [Paul M. Jones] tem feito algumas pesquisas fantásticas sobre práticas comuns de dezenas de milhares de projetos github 22 | no reino do PHP. Ele compilou uma estrutura padrão de arquivos e diretórios, o [Standard PHP Package Skeleton], com base 23 | nesta pesquisa. Nesta estrutura de diretórios, o `DocumentRoot` deve apontar para `public/`, os testes unitários devem 24 | estar no diretório `tests/`, e bibliotecas de terceiros, como as instaladas pelo [composer], pertencem ao diretório 25 | `vendor/`. Para outros arquivos e diretórios, obedecer ao [Standard PHP Package Skeleton] fará mais sentido para quem 26 | contribui com um projeto. 27 | 28 | [Paul M. Jones]: http://paul-m-jones.com/ 29 | 30 | [Standard PHP Package Skeleton]: https://github.com/php-pds/skeleton 31 | 32 | [Composer]: /#composer_and_packagist 33 | -------------------------------------------------------------------------------- /_posts/02-01-01-Code-Style-Guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Guia de estilo de código 3 | anchor: guia_de_estilo_de_codigo 4 | --- 5 | 6 | # Guia de estilo de código {#guia_de_estilo_de_codigo_title} 7 | 8 | A comunidade PHP é grande e diversificada, composta de inúmeras bibliotecas, estruturas e componentes. É comum para 9 | pessoas desenvolvedoras PHP escolherem vários destes e combiná-los em um único projeto. É importante que o código PHP 10 | respeite (o mais próximo possível) a um estilo de código comum para facilitar a desenvolvedores a mistura e combinação de 11 | várias bibliotecas para seus projetos. 12 | 13 | O [Framework Interop Group][fig] propôs e aprovou uma série de recomendações de estilo. Nem todas elas estão 14 | relacionadas ao estilo de código, mas aquelas que estão são [PSR-1][psr1], [PSR-12][psr12] e [PSR-4][psr4]. Estas 15 | recomendações são apenas um conjunto de regras que muitos projetos como Drupal, Zend, Symfony, Laravel, CakePHP, phpBB, 16 | AWS SDK, FuelPHP, Lithium, etc estão adotando. Você pode usá-los para seus próprios projetos, ou continuar a usar seu 17 | próprio estilo pessoal. 18 | 19 | Idealmente, você deveria escrever um código PHP que aderisse a um padrão conhecido. Isto poderia ser qualquer combinação 20 | de PSRs, ou um dos padrões de codificação feitos pela PEAR ou Zend. Isto significa que qualquer desenvolvedor pode 21 | facilmente ler e trabalhar com seu código, e as aplicações que implementam os componentes podem ter consistência mesmo 22 | quando se trabalha com muitos códigos de terceiros. 23 | 24 | * [Leia sobre PSR-1][psr1] 25 | * [Leia sobre PSR-12][psr12] 26 | * [Leia sobre PSR-4][psr4] 27 | * [Leia sobre PEAR Coding Standards][pear-cs] 28 | * [Leia sobre Symfony Coding Standards][symfony-cs] 29 | 30 | Você pode usar o [PHP_CodeSniffer][phpcs] para verificar o código em relação a qualquer uma destas recomendações, e 31 | plugins para editores de texto como [Sublime Text][st-cs] para receber feedback em tempo real. 32 | 33 | Você pode corrigir o layout do código automaticamente usando uma das seguintes ferramentas: 34 | 35 | - Uma delas é o [PHP Coding Standards Fixer][phpcsfixer], que tem uma base de código muito bem testada. 36 | - Além disso, a ferramenta [PHP Code Beautifier and Fixer][phpcbf], incluída no PHP_CodeSniffer, pode ser usada para 37 | ajustar seu código de acordo. 38 | 39 | E você pode executar o phpcs manualmente a partir do terminal: 40 | 41 | phpcs -sw --standard=PSR1 file.php 42 | 43 | Ele mostrará os erros e indicará como corrigi-los. Também pode ser útil incluir este comando em um git hook. Dessa 44 | forma, os branches que contêm violações contra o padrão escolhido não podem entrar no repositório até que aquelas 45 | violações tenham sido corrigidas. 46 | 47 | Se você tem o PHP_CodeSniffer, então você pode corrigir os problemas de layout de código reportados por ele, 48 | automaticamente, com o 49 | [PHP Code Beautifier and Fixer][phpcbf]. 50 | 51 | phpcbf -w --standard=PSR1 file.php 52 | 53 | Outra opção é usar o [PHP Coding Standards Fixer][phpcsfixer]. Ele mostrará que tipo de erros a estrutura do código 54 | tinha antes de corrigi-los. 55 | 56 | php-cs-fixer fix -v --rules=@PSR1 file.php 57 | 58 | O inglês é o idioma preferido para todos os nomes de símbolos e infra-estrutura de código. Os comentários podem ser 59 | facilmente escritos em qualquer idioma legível por todas as pessoas, atuais e futuras, que possam estar trabalhando na 60 | base de código. 61 | 62 | Finalmente, um bom recurso suplementar para escrever código PHP limpo é [Clean Code PHP][cleancode]. 63 | 64 | [fig]: https://www.php-fig.org/ 65 | 66 | [psr1]: https://www.php-fig.org/psr/psr-1/ 67 | 68 | [psr12]: https://www.php-fig.org/psr/psr-12/ 69 | 70 | [psr4]: https://www.php-fig.org/psr/psr-4/ 71 | 72 | [pear-cs]: https://pear.php.net/manual/en/standards.php 73 | 74 | [symfony-cs]: https://symfony.com/doc/current/contributing/code/standards.html 75 | 76 | [phpcs]: https://pear.php.net/package/PHP_CodeSniffer/ 77 | 78 | [phpcbf]: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Fixing-Errors-Automatically 79 | 80 | [st-cs]: https://github.com/benmatselby/sublime-phpcs 81 | 82 | [phpcsfixer]: https://cs.symfony.com/ 83 | 84 | [cleancode]: https://github.com/jupeter/clean-code-php 85 | -------------------------------------------------------------------------------- /_posts/03-01-01-Language-Highlights.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Destaques da linguagem 3 | anchor: destaques_da_linguagem 4 | --- 5 | 6 | # Destaques da linguagem {#destaques_da_linguagem_title} -------------------------------------------------------------------------------- /_posts/03-02-01-Programming-Paradigms.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Paradigmas de programação 3 | isChild: true 4 | anchor: paradigmas_de_programacao 5 | --- 6 | 7 | ## Paradigmas de programação {#paradigmas_de_programacao_title} 8 | 9 | O PHP é uma linguagem dinâmica e flexível, que suporta uma variedade de técnicas de programação. Ele evoluiu 10 | drasticamente com o passar dos anos, notavelmente adicionando um sólido modelo de orientação a objetos no PHP 5.0 11 | (2004), funções anônimas e namespaces no PHP 5.3 (2009) e traits no PHP 5.4 (2012). 12 | 13 | ### Programação orientada a objetos {#programacao_orientada_objetos} 14 | 15 | O PHP possui um conjunto completo de funcionalidades de programação orientada a objetos, incluindo suporte a classes, 16 | classes abstratas, interfaces, herança, construtores, clonagem, exceções e muito mais. 17 | 18 | * [Leia sobre PHP orientado a objetos][oop] 19 | * [Leia sobre Traits][traits] 20 | 21 | ### Programação funcional {#programacao_funcional} 22 | 23 | PHP suporta funções de primeira classe, o que significa que funções podem ser atribuídas a variáveis. Tanto funções 24 | nativas como funções definidas por usuários podem ser referenciadas por uma variável e invocadas dinamicamente. Funções 25 | também pode ser passadas como argumentos para outras funções (funcionalidade chamada de funções de ordem superior) e 26 | funções podem retornar outras funções. 27 | 28 | Recursão, uma funcionalidade que permite que funções realizem chamadas para elas mesmas também é suportada pela 29 | linguagem, mas a maioria dos códigos em PHP tem foco em iteração. 30 | 31 | Novas funções anônimas (incluindo suporte para closures) também estão presentes a partir do PHP 5.3 (2009). 32 | 33 | PHP 5.4 adicionou a habilidade de vincular closures com o escopo de objetos e também melhorou o suporte para invocáveis 34 | (callables) tanto que elas podem ser usadas indistintamente com funções anônimas na maioria dos casos. 35 | 36 | * Continue lendo em [Programação Funcional em PHP]({{ site.baseurl }}pages/Functional-Programming.html) 37 | * [Leia mais sobre Funções Anônimas][anonymous-functions] 38 | * [Leia mais sobre Closures][closure-class] 39 | * [Mais detalhes na RFC sobre Closures][closures-rfc] 40 | * [Leia mais sobre invocáveis (callables)][callables] 41 | * [Leia sobre invocamento dinâmico de funções com `call_user_func_array`][call-user-func-array] 42 | 43 | ### Meta Programação {#meta_programacao} 44 | 45 | PHP suporta várias formas de meta-programação através de mecanismos como a API de reflexão (Reflection) e métodos mágicos. 46 | Existem vários métodos mágicos disponíveis como `__get()`, `__set()`, `__clone()`, `__toString()`, `__invoke()`, etc. 47 | Isso permite que quem está desenvolvendo altere o comportamento das classes. Quem desenvolve em Ruby costuma dizer que o 48 | PHP carece de `method_missing`, mas ele está disponível com `__call()` e `__callStatic()`. 49 | 50 | * [Leia sobre Métodos Mágicos][magic-methods] 51 | * [Leia sobre Reflexão][reflection] 52 | * [Leia sobre Overloading][overloading] 53 | 54 | [oop]: https://secure.php.net/language.oop5 55 | [traits]: https://secure.php.net/language.oop5.traits 56 | [anonymous-functions]: https://secure.php.net/functions.anonymous 57 | [closure-class]: https://secure.php.net/class.closure 58 | [closures-rfc]: https://wiki.php.net/rfc/closures 59 | [callables]: https://secure.php.net/language.types.callable 60 | [call-user-func-array]: https://secure.php.net/function.call-user-func-array 61 | [magic-methods]: https://secure.php.net/language.oop5.magic 62 | [reflection]: https://secure.php.net/intro.reflection 63 | [overloading]: https://secure.php.net/language.oop5.overloading 64 | -------------------------------------------------------------------------------- /_posts/03-03-01-Namespaces.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Namespaces 3 | isChild: true 4 | anchor: namespaces 5 | --- 6 | 7 | ## Namespaces {#namespaces_title} 8 | 9 | Como mencionado anteriormente, a comunidade PHP tem muitas pessoas desenvolvedoras criando muito código. Isso significa 10 | que o código de uma biblioteca PHP pode usar o mesmo nome de classe que uma outra biblioteca. Quando ambas bibliotecas são 11 | usadas no mesmo namespace, elas colidem e causam problemas. 12 | 13 | Os _Namespaces_ resolvem esse problema. Como descrito no manual de referência do PHP, os namespaces podem ser comparados 14 | com os diretórios dos sistemas operacionais, que fazem _namespace_ dos arquivos; dois arquivos com o mesmo nome podem 15 | coexistir em diretórios separados. Da mesma forma, duas classes PHP com o mesmo nome podem coexistir em namespaces PHP 16 | separados. Simples assim. 17 | 18 | É importante que você use namespace no seu código para que ele possa ser usado por outras pessoas sem risco de colisão 19 | com outras bibliotecas. 20 | 21 | Um modo recomendado de usar namespaces está descrito na [PSR-4][psr4], que tem como objetivo fornecer uma convenção 22 | padrão para arquivos, classes e namespaces para permitir um código plug-and-play. 23 | 24 | Em outubro de 2014 o PHP-FIG (Framework Interop Group) descontinuou o padrão para autoloading anterior: a [PSR-0][psr0]. 25 | Tanto a PSR-0 e a PSR-4 ainda são perfeitamente utilizáveis. A última requer o PHP 5.3, então muitos projetos que rodam 26 | apenas em PHP 5.2 implementam a PSR-0. 27 | 28 | Se você estiver planejando usar um padrão para auto-carregamento para uma nova aplicação ou pacote, olhe na PSR-4. 29 | 30 | * [Leia sobre os Namespaces][namespaces] 31 | * [Leia sobre a PSR-0][psr0] 32 | * [Leia sobre a PSR-4][psr4] 33 | 34 | [namespaces]: https://secure.php.net/language.namespaces 35 | [psr0]: https://www.php-fig.org/psr/psr-0/ 36 | [psr4]: https://www.php-fig.org/psr/psr-4/ 37 | -------------------------------------------------------------------------------- /_posts/03-04-01-Standard-PHP-Library.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Standard PHP Library 3 | isChild: true 4 | anchor: standard_php_library 5 | --- 6 | 7 | ## Standard PHP Library {#standard_php_library_title} 8 | 9 | A Standard PHP Library (SPL), ou Biblioteca Padrão do PHP, vem empacotada com o PHP e fornece uma coleção de classes e 10 | interfaces. Ela é composta principalmente por classes de estruturas de dados normalmente necessárias (pilha, fila, heap 11 | e outras) e iteradores que podem percorrer por essas estruturas de dados ou por suas próprias classes que implementem as 12 | interfaces SPL. 13 | 14 | * [Leia sobre a SPL][spl] 15 | * [Curso em vídeo sobre SPL no Lynda.com(pago)][spllynda] 16 | 17 | [spl]: https://php.net/book.spl 18 | [spllynda]: https://www.lynda.com/PHP-tutorials/Up-Running-Standard-PHP-Library/175038-2.html 19 | -------------------------------------------------------------------------------- /_posts/03-05-01-Command-Line-Interface.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interface de Linha de Comando 3 | isChild: true 4 | anchor: interface_de_linha_de_comando 5 | --- 6 | 7 | ## Interface de Linha de Comando {#interface_de_linha_de_comando_title} 8 | 9 | O PHP foi criado primariamente para escrever aplicações web, mas ele também é útil para criar scripts de linha de 10 | comando (CLI). Programas PHP de linha de comando podem te ajudar a automatizar tarefas comuns como testes, publicação 11 | e administração de aplicações. 12 | 13 | Programas PHP CLI são poderosos pois você pode usar o código de sua aplicação diretamente sem precisar criar e proteger 14 | uma GUI (Interface Gráfica do Usuário) web para isso. Apenas tenha a certeza de **não** colocar seus scripts PHP CLI na 15 | raiz pública do seu servidor web! 16 | 17 | Tente executar o PHP a partir da sua linha de comando: 18 | 19 | {% highlight console %} 20 | > php -i 21 | {% endhighlight %} 22 | 23 | A opção `-i` irá mostrar a sua configuração do PHP da mesma forma que a função [`phpinfo()`][phpinfo]. 24 | 25 | A opção `-a` fornece um shell interativo, similar ao IRB do ruby e ao shell interativo do python. Também existem várias 26 | outras [opções de linha comando][cli-options] úteis. 27 | 28 | Vamos escrever um programa CLI "Hello, $name" simples. Para testá-lo, crie um arquivo chamado `hello.php`, como 29 | mostrado a seguir. 30 | 31 | {% highlight php %} 32 | .\n"; 35 | exit(1); 36 | } 37 | $name = $argv[1]; 38 | echo "Hello, $name\n"; 39 | {% endhighlight %} 40 | 41 | O PHP define duas variáveis especiais baseadas nos argumentos que seu script receber. [`$argc`][argc] é uma variável 42 | integer que contém a *quantidade* de argumentos e [`$argv`][argv] é uma variável array que contém o *valor* de cada 43 | argumento. O primeiro argumento sempre é o nome do arquivo PHP do seu programa, no caso `hello.php`. 44 | 45 | A expressão `exit()` é usada com um número diferente de zero para informar ao shell que o comando falhou. Códigos de 46 | saída normalmente usados podem ser encontrados [aqui][exit-codes]. 47 | 48 | Para executar nosso script acima, a partir da linha de comando: 49 | 50 | {% highlight console %} 51 | > php hello.php 52 | Uso: php hello.php 53 | > php hello.php world 54 | Hello, world 55 | {% endhighlight %} 56 | 57 | 58 | * [Aprenda sobre como executar o PHP a partir da linha de comando][php-cli] 59 | 60 | [phpinfo]: https://secure.php.net/function.phpinfo 61 | [cli-options]: https://secure.php.net/features.commandline.options 62 | [argc]: https://secure.php.net/reserved.variables.argc 63 | [argv]: https://secure.php.net/reserved.variables.argv 64 | [exit-codes]: https://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits 65 | [php-cli]: https://secure.php.net/features.commandline.options 66 | -------------------------------------------------------------------------------- /_posts/03-06-01-XDebug.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: XDebug 3 | isChild: true 4 | anchor: xdebug 5 | --- 6 | 7 | ## XDebug {#xdebug_title} 8 | 9 | Uma das ferramentas mais úteis no desenvolvimento de software é um depurador apropriado. Ele permite que você trace a 10 | execução do seu código e monitore os itens na pilha de execução. XDebug, um depurador de PHP, pode ser utilizado por 11 | várias IDEs para prover *breakpoints* e inspecionar a pilha. Ele também lhe permite que ferramentas como PHPUnit e 12 | KCacheGrind realizem análise de cobertura e perfis de código. 13 | 14 | Se você perceber que você está sem conseguir sair do lugar, querendo recorrer a *var_dump*/*print_r*, e ainda assim 15 | não conseguir resolver o problema - talvez você devesse usar um depurador. 16 | 17 | [Instalar o XDebug][xdebug-install] pode ser complicado, mas uma das características mais importantes é a "Depuração 18 | Remota" - se você desenvolve seu código localmente e depois o testa dentro de uma VM (máquina virtual) ou em outro 19 | servidor, a "Depuração Remota" é uma característica que você vai querer manter ativa desde o início. 20 | 21 | Tradicionalmente, você modificará o VHost ou o .htaccess do seu Apache para incluir os seguintes valores: 22 | 23 | {% highlight ini %} 24 | php_value xdebug.remote_host=192.168.?.? 25 | php_value xdebug.remote_port=9000 26 | {% endhighlight %} 27 | 28 | O "remote host" e o "remote port" vão corresponder ao seu computador local e a porta que você configurar para ser 29 | escutada na sua IDE. É apenas uma questão de colocar a sua IDE em modo para "escutar por conexões", e carregar a URL: 30 | 31 | http://your-website.example.com/index.php?XDEBUG_SESSION_START=1 32 | 33 | Sua IDE agora irá interceptar o estado atual enquanto seu script é executado, permitindo a você definir *breakpoints* 34 | e inspecionar os valores na memória. 35 | 36 | Depuradores gráficos deixam muito fácil o processo de percorrer o código, inspecionar variáveis e avaliar o código em 37 | tempo de execução. Várias IDE's possuem incluso ou suportam um plugin para depurar graficamente com o XDebug. MacGDBp é 38 | gratuito tem o código fonte aberto uma GUI (Interface Gráfica do Usuário) stand-alone do XDebug para Mac. 39 | 40 | * [Aprenda sobre o XDebug][xdebug-docs] 41 | * [Aprenda sobre o MacGDBp][macgdbp-install] 42 | 43 | [xdebug-docs]: https://xdebug.org/docs/ 44 | [xdebug-install]: https://xdebug.org/docs/install 45 | [macgdbp-install]: https://www.bluestatic.org/software/macgdbp/ 46 | -------------------------------------------------------------------------------- /_posts/04-01-01-Dependency-Management.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Gerenciamento de Dependência 3 | anchor: gerenciamento_de_dependencia 4 | --- 5 | 6 | # Gerenciamento de Dependência {#gerenciamento_de_dependencia_title} 7 | 8 | Há uma tonelada de bibliotecas PHP, estruturas e componentes para escolher. Seu projeto provavelmente usará várias delas 9 | - estas são dependências de projetos. Até recentemente, o PHP não tinha uma boa maneira de administrar estas 10 | dependências de projeto. Mesmo se você as administrasse manualmente, ainda teria que se preocupar com os autoloaders. 11 | Isso não é mais um problema. 12 | 13 | Atualmente existem dois grandes sistemas de gerenciamento de pacotes para PHP - [Composer] e [PEAR]. O Composer é 14 | atualmente o gerenciador de pacotes mais popular para PHP, porém por muito tempo o PEAR foi o principal gerenciador de 15 | pacotes em uso. Conhecer a história do PEAR é uma boa idéia, já que você ainda pode encontrar referências a ele, mesmo 16 | que nunca o use. 17 | 18 | [Composer]: /#composer_and_packagist 19 | [PEAR]: /#pear 20 | -------------------------------------------------------------------------------- /_posts/04-02-01-Composer-and-Packagist.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Composer e Packagist 3 | isChild: true 4 | anchor: composer_e_packagist 5 | --- 6 | 7 | ## Composer e Packagist {#composer_e_packagist_title} 8 | 9 | O Composer é o gerenciador de dependências recomendado para PHP. Lista as dependências de seu projeto em um arquivo 10 | `composer.json` e, com alguns comandos simples, o Composer fará automaticamente o download das dependências de seu 11 | projeto e configurará o autoloading para você. O Composer é semelhante ao NPM no mundo do node.js, ou Bundler no mundo 12 | do Ruby. 13 | 14 | Há uma infinidade de bibliotecas PHP compatíveis com o Composer e estão prontas para serem usadas em seu projeto. 15 | Estes "pacotes" estão listados no [Packagist], o repositório oficial para bibliotecas PHP compatíveis com o Composer. 16 | 17 | ### Como Instalar o Composer 18 | 19 | A forma mais segura de fazer o download do composer é [seguindo as instruções oficiais](https://getcomposer.org/download/). 20 | Isso vai verificar se o instalador não está corrompido ou foi adulterado. O instalador gera um arquivo binário 21 | `composer.phar` no seu _diretório atual_. 22 | 23 | Nós recomendamos instalar o Composer *globalmente* (por exemplo, uma única cópia no diretório `/usr/local/bin`). Para 24 | fazer isso, rode o seguinte comando: 25 | 26 | {% highlight console %} 27 | mv composer.phar /usr/local/bin/composer 28 | {% endhighlight %} 29 | 30 | **Nota:** Se o comando falhar devido à permissão, use o comando `sudo` no início. 31 | 32 | Para rodar o Composer instalado localmente, use o comando `php composer.phar`, e globalmente apenas `composer`. 33 | 34 | #### Instalação no Windows 35 | 36 | Para aqueles que usam Windows a forma mais fácil de obter e executá-lo é usar o instalador [ComposerSetup], que realiza 37 | uma instalação global e configura seu `$PATH` de modo que você possa executar o comando `composer` de qualquer diretório 38 | pela linha de comando. 39 | 40 | ### Como Definir e Instalar Dependências 41 | 42 | O Composer mantém o controle de dependências do seu projeto em um arquivo chamado `composer.json`. Você pode alterá-lo 43 | na mão se preferir ou usar o próprio Composer. O comando `composer require` adiciona uma dependência ao projeto e se 44 | você não tem um arquivo `composer.json`, ele será criado. Aqui está um exemplo que adiciona o [Twig] como uma dependência 45 | do seu projeto. 46 | 47 | {% highlight console %} 48 | composer require twig/twig:^2.0 49 | {% endhighlight %} 50 | 51 | Outra alternativa é o comando `composer init` que guiará a criação completa do arquivo `composer.json` para seu projeto. 52 | De qualquer maneira, uma vez criado o arquivo `composer.json` você pode chamar o Composer para baixar suas dependências 53 | para o diretório `vendor/`. Isto também se aplica para projetos baixados que fornecem um arquivo `composer.json`: 54 | 55 | {% highlight console %} 56 | composer install 57 | {% endhighlight %} 58 | 59 | Em seguida, adicione esta linha ao arquivo PHP principal da sua aplicação; isso dirá ao PHP para usar o autoloader do 60 | Composer para as dependências do seu projeto. 61 | 62 | {% highlight php %} 63 | pear-channel/Package 64 | 65 | O prefixo "pear" é padrão para evitar qualquer conflito, por exemplo, um canal pear pode ter o mesmo nome de um pacote 66 | no vendor. Então, o nome curto do canal (ou a URL completa) pode ser usada para referenciar o canal em que o pacote se 67 | encontra. 68 | 69 | Quando este código for instalado, ficará disponível dentro do seu diretório vendor e disponível automaticamente através 70 | do autoloader do Composer: 71 | 72 | > vendor/pear-pear2.php.net/PEAR2_HTTP_Request/pear2/HTTP/Request.php 73 | 74 | Para usar este pacote PEAR, basta referenciá-lo assim: 75 | 76 | {% highlight php %} 77 | format('Y-m-d') . "\n"; 23 | {% endhighlight %} 24 | 25 | Cálculos com a DateTime são possíveis com a classe DateInterval. A DateTime tem métodos como o `add()` e o `sub()` que 26 | recebem um DateInterval como argumento. Não escreva código que espera o mesmo número de segundos para todos os dia, 27 | pois tanto as alterações de horário de verão quanto as de fuso horário irão quebrar essa suposição. Em vez disso use 28 | intervalos de data. Para calcular diferenças entre datas use o método `diff()`. Ele retornará um novo DateInterval, 29 | que é bem fácil de mostrar. 30 | 31 | {% highlight php %} 32 | add(new DateInterval('P1M6D')); 36 | 37 | $diff = $end->diff($start); 38 | echo "Difference: " . $diff->format('%m month, %d days (total: %a days)') . "\n"; 39 | // Diferença: 1 mês, 6 dias (total: 37 dias) 40 | {% endhighlight %} 41 | 42 | Com objetos DateTime, você pode usar a comparação padrão: 43 | {% highlight php %} 44 | format('Y-m-d') . " "; 61 | } 62 | {% endhighlight %} 63 | 64 | * [Leia sobre a classe DateTime][datetime] 65 | * [Leia sobre formatação de datas][dateformat] (opções aceitas para formatos de strings de data) 66 | 67 | [datetime]: http://php.net/book.datetime 68 | [dateformat]: http://php.net/function.date -------------------------------------------------------------------------------- /_posts/05-04-01-Design-Patterns.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Design Patterns 3 | isChild: true 4 | anchor: design_patterns 5 | --- 6 | 7 | ## Design Patterns {#design_patterns_title} 8 | 9 | Quando você está construindo sua aplicação web é muito útil utilizar padrões de codificação para formar a estrutura do 10 | seu projeto. Usar "design patterns" (padrões de projeto) é útil pois eles facilitam bastante na hora de gerenciar seu 11 | código e permite que outros desenvolvedores entendam rapidamente como tudo está se encaixando. 12 | 13 | Se você utiliza um framework então a maior parte do código de alto nível e a estrutura do projeto serão baseados no 14 | framework, ou seja, uma grande parte das decisões de padrões de design do código já foram decididas para você. Mas ainda 15 | cabe a você escolher os melhores padrões a seguir no código na hora de utilizá-los no framework. Se, por outro lado, 16 | você não estiver utilizando uma framework para construir sua aplicação, então você terá que descobrir os padrões que 17 | melhor se encaixam para o tipo e tamanho da aplicação que você está construindo. 18 | 19 | * Continue lendo em [Design Patterns]({{ site.baseurl }}pages/Design-Patterns.html) -------------------------------------------------------------------------------- /_posts/06-01-01-Dependency-Injection.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Dependency Injection 3 | anchor: dependency_injection 4 | --- 5 | 6 | # Dependency Injection (Injeção de Dependência) {#dependency_injection_title} 7 | 8 | Fonte [Wikipedia](http://en.wikipedia.org/wiki/Dependency_injection): 9 | 10 | > Dependency Injection é um Design Pattern que permite retirar as dependências hard-coded e torna possível mudá-las, 11 | > seja em tempo de execução ou em tempo de compilação. 12 | 13 | Esta citação torna o conceito muito mais complicado do que realmente é. Dependency Injection fornece um componente com 14 | suas dependências, seja por injeção no construtor, chamada de método ou na definição de propriedades. É simples assim. -------------------------------------------------------------------------------- /_posts/06-02-01-Basic-Concept.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conceito Básico 3 | isChild: true 4 | anchor: conceito_basico 5 | --- 6 | 7 | ## Conceito Básico {#conceito_basico_title} 8 | 9 | Demostraremos o conceito com um simples exemplo. 10 | 11 | Temos uma classe `Database` que requer um adaptador para se comunicar com o banco de dados. Instanciaremos o adaptador 12 | no construtor e assim criamos uma forte de dependência. Isto dificulta os testes e significa que a classe `Database` 13 | está fortemente acoplada ao adaptador. 14 | 15 | {% highlight php %} 16 | adapter = new MySqlAdapter; 26 | } 27 | } 28 | 29 | class MysqlAdapter {} 30 | {% endhighlight %} 31 | 32 | Este código pode ser refatorado para usar a Dependency Injection para desacoplar a dependência. 33 | 34 | {% highlight php %} 35 | adapter = $adapter; 45 | } 46 | } 47 | 48 | class MysqlAdapter {} 49 | {% endhighlight %} 50 | 51 | Agora, damos a classe `Database` a sua dependência em vez de criar dentro dela. Poderiamos também, criar um método 52 | que aceitaria um argumento da dependência e defini-la dessa forma, ou definir a propriedade `$adapter` como `public` 53 | para defini-la diretamente. -------------------------------------------------------------------------------- /_posts/06-03-01-Complex-Problem.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Problema Complexo 3 | isChild: true 4 | anchor: problema_complexo 5 | --- 6 | 7 | ## Problema Complexo {#problema_complexo_title} 8 | 9 | Se você já leu sobre Inversão de Dependência, então você provavelmente viu os termos *"Inversão de Controle"* ou 10 | *"Princípio da Inversão de Dependência"*. 11 | Estes são os problemas complexos que a Inversão de Dependência resolve. 12 | 13 | ### Inversão de Controle 14 | 15 | Inversão de controle é como se diz, "invertendo o controle" de um sistema para manter os controles organizacionais 16 | totalmente separados dos seus objetos. 17 | Em termos de Dependency Injection, isto significa desacoplar as dependências para controlá-las e instanciá-las em outro 18 | lugar do sistema. 19 | 20 | Por anos, os frameworks PHP usam a Inversão de Controle, no entanto, a questão é: que parte do controle está invertendo, 21 | e onde? Por exemplo, frameworks MVC, em geral, fornecem um super objeto ou um controlador base que outros controladores 22 | devem extender para obter acesso as suas dependências. Isto **é** Inversão de Controle, no entanto, em vez de desacoplar 23 | as dependências, este método simplesmente as mudou. 24 | 25 | Dependency Injection permite resolver de forma mais elegante este problema apenas injetando a dependência que precisamos, 26 | quando precisamos dela, sem a necessidade de quaisquer dependências no código. 27 | 28 | ### Princípio da Inversão de Dependência 29 | 30 | O Princípio da Inversão de Dependência é o "D", no S.O.L.I.D, define o princípio de design da orientação a objeto que 31 | afirma que *"Dependa de uma Abstração. Não depende de Objetos concretos"*. Simplificando, isto significa que nossas 32 | dependências devem ser classes de interfaces/contratos ou class abstratas em vez de implementações concretas. 33 | Podemos facilmente refatorar o exemplo abaixo para seguir este princípio. 34 | 35 | {% highlight php %} 36 | adapter = $adapter; 46 | } 47 | } 48 | 49 | interface AdapterInterface {} 50 | 51 | class MysqlAdapter implements AdapterInterface {} 52 | {% endhighlight %} 53 | 54 | Existem vários benefícios para a classe `Database`, agora, dependendo de uma interface em vez de um objeto concreto. 55 | 56 | Considerando que você trabalha em uma equipe e o adaptador está sendo trabalhado por um colega. No primeiro exemplo, 57 | teriamos que esperar o colega dizer que terminou o adaptador antes que pudéssemos simulá-la(mock) nos testes unitários. 58 | Agora, que a dependência é uma interface/contrato podemos facilmente simulá-la(mock) sabendo que o colega vai 59 | construir o adaptador com base neste contrato. 60 | 61 | Um benefício ainda maior para este método é que nosso código, agora, está mais escalável. Se um ano depois decidir 62 | migrar para um banco de dados diferente, podemos escrever um novo adaptador que implementa a interface original e 63 | injetá-lo, não seria preciso nenhuma refatoração, pois o adaptador segue o contrato definido pela interface. 64 | -------------------------------------------------------------------------------- /_posts/06-04-01-Containers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Containers 3 | isChild: true 4 | anchor: containers 5 | --- 6 | 7 | ## Containers {#containers_title} 8 | 9 | A primeira coisa que você deve entender sobre os Containers da Dependency Injection é que eles não são a mesma coisa 10 | que ela. Um container é um utilitário de conveniência que nos ajuda implementar a Dedepency Injection, no entanto, eles 11 | podem ser, e muitas vezes são, uma implementação anti-pattern, Service Location (Serviço de Localização). 12 | Injetar um container DI como um Localizador de Serviço para suas classes, sem dúvida, cria uma dependência difícil de 13 | substituir no container. Isso também torna seu código menos transparente e, finalmente, mais difícil de testar. 14 | 15 | A maioria dos frameworks têm seu próprio Container de Dependency Injection que permite ligar suas dependências em 16 | conjunto, através de configuração. 17 | O que isto significa, na prática, que você pode escrever o código da aplicação tão limpo e desacoplado como do framework 18 | foi construído. -------------------------------------------------------------------------------- /_posts/06-05-01-Further-Reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Leitura Adicional 3 | isChild: true 4 | anchor: leitura_adicional 5 | --- 6 | 7 | ## Leitura Adicional {#leitura_adicional_title} 8 | 9 | - [Aprenda sobre Dependency Injection e PHP](http://ralphschindler.com/2011/05/18/learning-about-dependency-injection-and-php) 10 | - [O que é Dependency Injection?](http://fabien.potencier.org/article/11/what-is-dependency-injection) 11 | - [Dependency Injection: uma analogia](http://mwop.net/blog/260-Dependency-Injection-An-analogy.html) 12 | - [Dependency Injection: Huh?](http://net.tutsplus.com/tutorials/php/dependency-injection-huh/) 13 | - [Dependency Injection como uma ferramenta para testes](http://www.happyaccidents.me/dependency-injection-as-a-tool-for-testing/) -------------------------------------------------------------------------------- /_posts/07-01-01-Databases.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Banco de Dados 3 | anchor: banco_de_dados 4 | --- 5 | 6 | # Bancos de Dados {#banco_de_dados_title} 7 | 8 | Muitas vezes o seu código PHP usará um banco de dados para persistir informações. Você tem algumas opções para 9 | conectar e interagir com o seu banco de dados. A opção recomendada _até o PHP 5.1.0_ era usar os drivers nativos, como 10 | o [mysqli], o [pgsql], [mssql] etc. 11 | 12 | Drivers nativos são excelentes se você estiver usando apenas _um_ banco de dados em sua aplicação, mas se, por exemplo, 13 | você estiver usando o MySQL e um pouco de MSSQL, ou você precisar conectar em um banco de dados Oracle, aí você não 14 | poderá usar os mesmos drivers. Você precisará aprender um API totalmente nova para cada um dos bancos de dados — 15 | e isso pode ficar chato. 16 | 17 | ## MySQL Extension 18 | 19 | A extensão [mysql] para o PHP não está mais em desenvolvimento ativo e foi [oficialmente descontinuada no PHP 5.5.0]. Isso 20 | significa que ela será removida dentro de alguns lançamentos das próximas versões. Se você estiver usando funções que 21 | inicial com `mysql_*` como a `mysql_connect()` e a `mysql_query()` em suas aplicações você irá se deparar com uma 22 | reescrita em algum momento no futuro, por isso a melhor opção é substituir o uso do mysql pelo mysqli ou pela PDO na sua 23 | aplicação dentro de sua própria agenda de desenvolvimento, assim você não terá que correr lá na frente. 24 | 25 | **Se você estiver começando do zero então não utilize de forma nenhuma a 26 | extensão mysql: use a [extensão MySQLi][mysqli], ou use a [PDO].** 27 | 28 | * [PHP: Choosing an API for MySQL](http://php.net/mysqlinfo.api.choosing) 29 | * [PDO Tutorial for MySQL Developers](http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers) 30 | 31 | ## Extensão PDO 32 | 33 | A [PDO] é uma biblioteca para abstração de conexões a bancos de dados — embutida no PHP desde a versão 5.1.0 34 | — que fornece uma interface comum para conversar com vários bancos de dados diferentes. Por exemplo, você pode 35 | usar basicamente o mesmo código para fazer a interface com o MySQL ou SQLite: 36 | 37 | {% highlight php %} 38 | query("SELECT some\_field FROM some\_table"); 42 | $row = $statement->fetch(PDO::FETCH_ASSOC); 43 | echo htmlentities($row['some_field']); 44 | 45 | // PDO + SQLite 46 | $pdo = new PDO('sqlite:/path/db/foo.sqlite'); 47 | $statement = $pdo->query("SELECT some\_field FROM some\_table"); 48 | $row = $statement->fetch(PDO::FETCH_ASSOC); 49 | echo htmlentities($row['some_field']); 50 | {% endhighlight %} 51 | 52 | A PDO não irá traduzir 53 | suas consultas SQL ou emular funcionalidades que não existem; ela é feita puramente para conectar múltiplos tipos de 54 | bancos de dados com a mesma API. 55 | 56 | Mais importante, a `PDO` permite que você injete de forma segura entradas externas (e.g IDs) em suas consultas SQL 57 | sem se preocupar com ataques de SQL injection. 58 | Isso é possível usando instruções PDO (PDO statements) e parâmetros restritos (bound parameters). 59 | 60 | Vamos assumir que um script PHP recebe um ID numérico como parâmetro de uma consulta. Este ID deve ser usado para 61 | buscar um registro de um usuário no banco de dados. Essa é a forma `errada` de fazer isso: 62 | 63 | {% highlight php %} 64 | query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- NÃO! 67 | {% endhighlight %} 68 | 69 | Esse código é péssimo. Você está inserindo um parâmetro bruto na sua consulta SQL. Isso fará você ser hackeado num 70 | piscar de olhos, usando uma prática chamada [SQL Injection](http://wiki.hashphp.org/Validation). Apenas imagine se um 71 | hacker passar como parâmetro um `id` inventivo chamando uma URL como `http://domain.com/?id=1%3BDELETE+FROM+users`. 72 | Isso irá definir a variável `$_GET['id']` como `id=1;DELETE FROM users`, o que irá excluir todos os seus usuários. Em 73 | vez disso, você deveria higienizar (sanitize) a entrada do ID usando parâmetros restritos da PDO. 74 | 75 | {% highlight php %} 76 | prepare('SELECT name FROM users WHERE id = :id'); 79 | $stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); //<-- Higienizado automaticamente pela PDO 80 | $stmt->execute(); 81 | {% endhighlight %} 82 | 83 | Esse é o código correto. Ele usa um parâmetro restrito em uma instrução PDO. Assim a entrada externa do ID é escapada 84 | antes de ser introduzida no banco de dados, prevenindo contra potenciais ataques de SQL injection. 85 | 86 | * [Leia mais sobre a PDO] 87 | 88 | Você também deve estar ciente de que usam recursos do servidor e não é raro ter esses recursos esgotados se essas 89 | conexões não forem implicitamente fechadas, entretanto isso é mais comum em outras linguagens. Com PDO você pode 90 | implicitamente fechar as conexões pela destruição dos objetos garantindo que todas as referências a ele forem excluídas, 91 | ex. atribuindo NULL a elas. Se você não fizer isso explicitamente o PHP irá fechar todas as conexões quando seu script 92 | terminar - a não ser é claro que você esteja usando conexões persistentes. 93 | 94 | * [Leia mais sobre conexões PDO] 95 | 96 | [Leia mais sobre a PDO]: http://php.net/book.pdo 97 | [Leia mais sobre conexões PDO]: http://php.net/pdo.connections 98 | [oficialmente descontinuada no PHP 5.5.0]: http://php.net/migration55.deprecated 99 | [SQL Injection]: http://wiki.hashphp.org/Validation 100 | 101 | [pdo]: http://php.net/pdo 102 | [mysql]: http://php.net/mysql 103 | [mysqli]: http://php.net/mysqli 104 | [pgsql]: http://php.net/pgsql 105 | [mssql]: http://php.net/mssql -------------------------------------------------------------------------------- /_posts/07-02-01-Interacting-via-Code.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Interagindo com o banco de dados 4 | anchor: interagindo_com_o_banco_de_dados 5 | --- 6 | 7 | ## Interagindo com o banco de dados {#interagindo_com_o_banco_de_dados_title} 8 | 9 | Quando os desenvolvedores começam a aprender PHP, muitas vezes acabam misturando a interação com o banco de dados com a 10 | camada de apresentação, usando código que pode parecer com isso: 11 | 12 | {% highlight php %} 13 | 20 | {% endhighlight %} 21 | 22 | Esta é uma má prática por várias razões, principalmente por ser difícil de depurar, testar, ler e ainda pode gerar na 23 | saída um monte de campos se não houver um limite. 24 | 25 | Embora existam muitas outras soluções para fazer isso - dependendo se você preferir a 26 | [OOP](/#programacao_orientada_objetos) ou [programação funcional](/#programacao_funcional) - deve haver algum elemento 27 | de separação. 28 | 29 | Considere o passo mais básico: 30 | 31 | {% highlight php %} 32 | query('SELECT * FROM table'); 35 | } 36 | 37 | foreach (getAllFoos($db) as $row) { 38 | echo "
  • ".$row['field1']." - ".$row['field1']."
  • "; // BAD!! 39 | } 40 | {% endhighlight %} 41 | 42 | Este é um bom começo. Coloque estes dois itens em dois arquivos diferentes e você terá alguma separação limpa. 43 | 44 | Crie uma classe para colocar este método e você terá um "Modelo". Criando um arquivo `.php` simples para colocar a 45 | lógica de apresentação e você terá uma "View", que é quase um [MVC] - uma arquitura OOP comum para a maioria dos 46 | [frameworks](/#frameworks). 47 | 48 | **foo.php** 49 | 50 | {% highlight php %} 51 | db = $db; 76 | } 77 | 78 | public function getAllFoos() { 79 | return $this->db->query('SELECT * FROM table'); 80 | } 81 | } 82 | {% endhighlight %} 83 | 84 | **views/foo-list.php** 85 | 86 | {% highlight php %} 87 | 88 | - 89 | 90 | {% endhighlight %} 91 | 92 | Isto é essenciamente o mesmo que a maioria dos frameworks modernos fazem, todos sejam eles um pouco mais manual. Você 93 | pode não precisar de tudo a todo momento, mas misturando muita lógica de apresentação e interação com o banco de dados 94 | pode ser um problema real se você quiser [testes unitários](/#testes_unitarios) em sua aplicação. 95 | 96 | [PHPBridge] tem um grande recurso chamado [Criando uma classe de dados] que aborda um tópico muito similar e é ótimo 97 | para os desenvolvedores se acostumar ao o conceito de interagir com o banco de dados. 98 | 99 | [MVC]: http://code.tutsplus.com/tutorials/mvc-for-noobs--net-10488 100 | [PHPBridge]: http://phpbridge.org/ 101 | [Criando uma classe de dados]: http://phpbridge.org/intro-to-php/creating_a_data_class -------------------------------------------------------------------------------- /_posts/07-03-01-Abstraction-Layers.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Camadas de Abstração 4 | anchor: camadas_de_abstracao_de_banco_de_dados 5 | --- 6 | 7 | ## Camadas de Abstração {#camadas_de_abstracao_de_banco_de_dados_title} 8 | 9 | Muitos frameworks fornecem sua própria camada de abstração que pode ou não sobrepor o [PDO][1]. Estes muitas vezes 10 | simulam características de um sistema de banco de dados que outro banco de dados não possui envolvendo suas consultas 11 | em métodos PHP, dando-lhe a abstração real do banco de dados em vez de apenas a abstração da conexão como o PDO oferece. 12 | 13 | Isto obviamente adiciona um pequeno peso, mas se você estiver construindo uma aplicação portátil que precise trabalhar 14 | com MySQL, PostgreSQL e SQLite, então este pequeno peso vai valer a pena pela limpeza e menos linhas de código. 15 | 16 | Algumas camadas de abstração foram construídas utilizando o padrão de namespaces da [PSR-0][psr0] ou [PSR-4][psr4] para 17 | que possa ser instalado em qualquer aplicação que você queira. 18 | 19 | * [Aura SQL][6] 20 | * [Doctrine2 DBAL][2] 21 | * [Propel][7] 22 | * [ZF2 Db][4] 23 | 24 | [1]: http://php.net/book.pdo 25 | [2]: http://www.doctrine-project.org/projects/dbal.html 26 | [4]: http://packages.zendframework.com/docs/latest/manual/en/index.html#zend-db 27 | [6]: https://github.com/auraphp/Aura.Sql 28 | [7]: http://propelorm.org/ 29 | 30 | [psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 31 | [psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md -------------------------------------------------------------------------------- /_posts/08-01-01-Templating.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Templates 3 | anchor: templates 4 | --- 5 | 6 | # Templates {#templates_title} 7 | 8 | Os templates fornecem uma forma conveniente de separar seu controlador e a camada de domínio da sua camada de 9 | apresentação. 10 | 11 | Eles contém geralmente o HTML de sua aplicação, mas também podem ser usados para outros formatos, como o XML. 12 | 13 | São muitas vezes referidos como a camada de visão que faz parte do segundo componente do padrão de arquitetura de 14 | software [modelo-visão-controlador]({{ site.baseurl }}pages/Design-Patterns.html#model-view-controller) (MVC) -------------------------------------------------------------------------------- /_posts/08-02-01-Benefits.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Benefícios 4 | anchor: templating_benefits 5 | --- 6 | 7 | ## Benefícios {#templating_benefits_title} 8 | 9 | O principal benefício de se utilizar templates é a clara separação que eles criam entre a lógica de apresentação e o 10 | resto da sua aplicação. Templates têm a responsabilidade exclusiva de exibir o conteúdo formatado. Eles não são 11 | responsáveis por pesquisa de dados, persistência ou outras tarefas mais complexas. Isto leva a código mais limpo, mais 12 | legível que é especialmente útil em um ambiente de equipe, onde os desenvolvedores trabalham no código do lado do 13 | servidor (controladores, modelos) e designers trabalham no código do lado do cliente (markup). 14 | 15 | Os templates também melhoram a organização do código de apresentação. Os templates são normalmente colocados em uma 16 | pasta "views", cada um definido dentro de um único arquivo. Essa abordagem incentiva a reutilização de código, onde 17 | grandes blocos de código são quebrados em pequenos pedaços reutilizáveis, chamados frequentemente de partials. Por 18 | exemplo, o cabeçalho e o rodapé do site de cada um pode ser definido como templates, que são então incluídos antes e 19 | depois de cada template de página. 20 | 21 | Finalmente, dependendo da biblioteca que você usa, os templates podem oferecer mais segurança ao escapar automaticamente 22 | o conteúdo gerado pelo usuário. Algumas bibliotecas oferecem até mesmo sand-boxing, onde os criadores de templates só 23 | têm acesso à white-listed (lista branca) de variáveis e funções. 24 | -------------------------------------------------------------------------------- /_posts/08-03-01-Plain-PHP-Templates.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Templates Simples em PHP 4 | anchor: plain_php_templates 5 | --- 6 | 7 | ## Templates Simples em PHP {#plain_php_templates_title} 8 | 9 | Templates Simples em PHP são templates que usam código nativo do PHP. Eles são uma escolha natural já que o PHP é na 10 | realidade um linguagem de template por si só. Isso significa simplesmente que você pode combinar código PHP dentro de 11 | outro código, como HTML. Isso é benéfico para os desenvolvedores de PHP pois não há uma nova sintaxe para aprender, 12 | eles sabem as funções disponíveis e seus editores de código PHP já tem syntax highlighting and auto-completion 13 | embutidos. Além disso, estes templates tendem a ser muito mais rápido já que não é necessária a fase de compilação. 14 | 15 | Cada framework moderno PHP emprega algum tipo de sistema de templates, a maioria usam PHP simples por padrão. Fora dos 16 | frameworks, bibliotecas como [Plates](http://platesphp.com/) ou [Aura.View](https://github.com/auraphp/Aura.View) 17 | tornam o trabalho mais fácil, oferecendo funcionalidade modernas ao template, tais como herança, layouts e extensões. 18 | 19 | ### Exemplo de um template simples em PHP 20 | 21 | Utilizando a biblioteca [Plates](http://platesphp.com/). 22 | 23 | {% highlight php %} 24 | 25 | 26 | insert('header', ['title' => 'User Profile']) ?> 27 | 28 |

    User Profile

    29 |

    Hello, escape($name)?>

    30 | 31 | insert('footer') ?> 32 | {% endhighlight %} 33 | 34 | ### Exemplo de um template simples em PHP usando herança 35 | 36 | Utilizando a biblioteca [Plates](http://platesphp.com/). 37 | 38 | {% highlight php %} 39 | 40 | 41 | 42 | 43 | <?=$title?> 44 | 45 | 46 | 47 |
    48 | section('content')?> 49 |
    50 | 51 | 52 | 53 | {% endhighlight %} 54 | 55 | {% highlight php %} 56 | 57 | 58 | layout('template', ['title' => 'User Profile']) ?> 59 | 60 |

    User Profile

    61 |

    Hello, escape($name)?>

    62 | {% endhighlight %} -------------------------------------------------------------------------------- /_posts/08-04-01-Compiled-Templates.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Templates Compilados 4 | anchor: compiled_templates 5 | --- 6 | 7 | ## Templates Compilados {#compiled_templates_title} 8 | 9 | Enquanto o PHP evoluiu para uma linguagem orientada a objetos madura, ele 10 | [não melhorou muito](http://fabien.potencier.org/article/34/templating-engines-in-php) como uma linguagem de templates. 11 | Templates compilados, como [Twig](http://twig.sensiolabs.org/) ou [Smarty](http://www.smarty.net/)*, preenchem este 12 | vazio oferecendo uma nova sintaxe que foi direcionada especificamente para templating. De escape automático, à herança 13 | e estruturas de controle simplificadas, templates compilados são projetados para ser mais fácil de escrever, simples de 14 | ler e mais seguro de usar. 15 | Templates compilados pode ser até compartilhados entre diferentes linguagens, [Mustache](http://mustache.github.io/) 16 | vem sendo um bom exemplo disso. Uma vez que esses templates devem ser compilados há uma pequena queda de performance, 17 | no entanto, este é mínimo quando o cache apropriado é usado. 18 | 19 | ** Enquanto Smarty oferece escape automático, este recurso NÃO está habilitado por padrão.* 20 | 21 | ### Exemplo simples de um template compilado 22 | 23 | Utilizando a biblioteca [Twig](http://twig.sensiolabs.org/). 24 | 25 | {% highlight html+jinja %} 26 | {% raw %} 27 | {% include 'header.html' with {'title': 'User Profile'} %} 28 | 29 |

    User Profile

    30 |

    Hello, {{ name }}

    31 | 32 | {% include 'footer.html' %} 33 | {% endraw %} 34 | {% endhighlight %} 35 | 36 | ### Exemplo de templates compilados usando herança 37 | 38 | Utilizando a biblioteca [Twig](http://twig.sensiolabs.org/). 39 | 40 | {% highlight html+jinja %} 41 | {% raw %} 42 | // template.php 43 | 44 | 45 | 46 | {% block title %}{% endblock %} 47 | 48 | 49 | 50 |
    51 | {% block content %}{% endblock %} 52 |
    53 | 54 | 55 | 56 | {% endraw %} 57 | {% endhighlight %} 58 | 59 | {% highlight text %} 60 | {% raw %} 61 | // user_profile.php 62 | 63 | {% extends "template.html" %} 64 | 65 | {% block title %}User Profile{% endblock %} 66 | {% block content %} 67 |

    User Profile

    68 |

    Hello, {{ name }}

    69 | {% endblock %} 70 | {% endraw %} 71 | {% endhighlight %} -------------------------------------------------------------------------------- /_posts/08-05-01-Further-Reading.md: -------------------------------------------------------------------------------- 1 | --- 2 | isChild: true 3 | title: Templates - Leitura Adicional 4 | anchor: templates_leitura_adicional 5 | --- 6 | 7 | ## Templates - Leitura Adicional {#templates_leitura_adicional_title} 8 | 9 | ### Artigos & Tutoriais 10 | 11 | - [Templating Engines in PHP](http://fabien.potencier.org/article/34/templating-engines-in-php) 12 | - [An Introduction to Views & Templating in CodeIgniter](http://code.tutsplus.com/tutorials/an-introduction-to-views-templating-in-codeigniter--net-25648) 13 | - [Getting Started With PHP Templating](http://www.smashingmagazine.com/2011/10/17/getting-started-with-php-templating/) 14 | - [Roll Your Own Templating System in PHP](http://code.tutsplus.com/tutorials/roll-your-own-templating-system-in-php--net-16596) 15 | - [Master Pages](https://laracasts.com/series/laravel-from-scratch/episodes/7) 16 | - [Working With Templates in Symfony 2](http://code.tutsplus.com/tutorials/working-with-templates-in-symfony-2--cms-21172) 17 | 18 | ### Bibliotecas 19 | 20 | - [Aura.View](https://github.com/auraphp/Aura.View) *(nativo)* 21 | - [Blade](http://laravel.com/docs/templates) *(compilado, específico do framework)* 22 | - [Dwoo](http://dwoo.org/) *(compilado)* 23 | - [Latte](https://github.com/nette/latte) *(compilado)* 24 | - [Mustache](https://github.com/bobthecow/mustache.php) *(compilado)* 25 | - [PHPTAL](http://phptal.org/) *(compilado)* 26 | - [Plates](http://platesphp.com/) *(nativo)* 27 | - [Smarty](http://www.smarty.net/) *(compilado)* 28 | - [Twig](http://twig.sensiolabs.org/) *(compilado)* 29 | - [Zend\View](http://framework.zend.com/manual/2.3/en/modules/zend.view.quick-start.html) *(nativo, específico do framework)* -------------------------------------------------------------------------------- /_posts/09-01-01-Errors-and-Exceptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Erros e Exceções 3 | anchor: erros_e_excecoes 4 | --- 5 | 6 | # Erros e Exceções {#erros_e_excecoes_title} -------------------------------------------------------------------------------- /_posts/09-02-01-Errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Erros 3 | isChild: true 4 | anchor: erros 5 | --- 6 | 7 | ## Erros {#erros_title} 8 | 9 | Em muitas linguagens de programação que fazem o uso generalizado das exceções, sempre que algo dá errado uma exceção é lançada. Esta é certamente uma forma viável de fazer as coisas, mas o PHP é uma linguagem que utiliza menos exceções. Mesmo que elas existam e mais membros do núcleo de desenvolvimento estejam começando a usá-las quando trabalhando com objetos, o PHP irá na maioria das vezes tentar manter a linha de processamento independentemente do que aconteça, a não ser que ocorra um erro fatal. 10 | 11 | Por exemplo: 12 | 13 | {% highlight console %} 14 | $ php -a 15 | php > echo $foo; 16 | Notice: Undefined variable: foo in php shell code on line 1 17 | {% endhighlight %} 18 | 19 | Este é apenas um `notice error` e o PHP irá continuar a excecução. Isso pode ser confuso para quem vem de linguagens 20 | "exception-heavy", porque referência a uma variável que falta em Python, por exemplo, irá lançar uma exceção: 21 | 22 | {% highlight console %} 23 | $ python 24 | >>> print foo 25 | Traceback (most recent call last): 26 | File "", line 1, in 27 | NameError: name 'foo' is not defined 28 | {% endhighlight %} 29 | 30 | A única diferença real é que Python vai surtar sobre qualquer coisa pequena, de modo que os desenvolvedores podem ter 31 | certeza que qualquer problema em potencial ou caso extremo será capturado, enquanto o PHP irá continuar o 32 | processamento, a menos que algo extremo aconteça e neste ponto irá lançar um erro e relatá-lo. 33 | 34 | ### Severidade dos Erros 35 | 36 | O PHP tem vários níveis de severidade de erro. Os três tipos mais comuns de mensagens são erros, avisos e advertências 37 | (error, notice e warnings). Estes têm diferentes níveis de severidade; `E_ERROR`, `E_NOTICE` e `E_WARNING`. _Erros_ são 38 | erros fatais em tempo de execução e são geralmente causados por falhas no seu código e precisam ser corrigidos à medida 39 | que eles causam a parada da execução do PHP. Os avisos são erros não fatais, a execução do script não será interrompida. 40 | Avisos são mensagens de conselho causadas por um código que pode ou não causar problemas durante a execução do script, 41 | a execução não é interrompida. 42 | 43 | Outro tipo de mensagem de erro relatado em tempo de compilação são mensagens `E_STRICT`. Estas mensagens são usadas para 44 | sugerir mudanças no seu código para ajudar a assegurar melhor interoperabilidade e compatibilidade com futuras versões 45 | do PHP. 46 | 47 | ### Mudando o comportamento do relatório de erros do PHP 48 | 49 | O relatório de erros pode ser alterado nas configurações do PHP e/ou através de chamadas de função. Usando a função 50 | nativa do PHP `error_reporting()` você pode definir o nível dos erros para a duração da execução do script, passando 51 | um dos níveis de erro pré-definidos, ou seja, se você só quer ver os _Warnings_ e os _Errors_ - mas não _Notices_ - 52 | então você pode configurar como: 53 | 54 | {% highlight php %} 55 | upload->get_error()` para 18 | ver o que houve de errado. O problema, aqui, é você tem que sair procurando por um erro e verificar na documentação para 19 | saber como achar o método que retorna o erro para essa classe, em vez de ter isso de forma extremamente óbvia. 20 | 21 | Outro problema é quando as classes automaticamente disparam um erro para a tela e finalizam o processo. Quando você 22 | faz isso você impede que outro programador seja capaz de dinamicamente lidar com o erro. Exceções devem ser disparadas 23 | para que os desenvolvedores fiquem a par do erro, para então decidirem como lidar com ele. Ex: 24 | 25 | {% highlight php %} 26 | subject('My Subject'); 29 | $email->body('How the heck are you?'); 30 | $email->to('guy@example.com', 'Some Guy'); 31 | 32 | try 33 | { 34 | $email->send(); 35 | } 36 | catch(Fuel\Email\ValidationFailedException $e) 37 | { 38 | // A validação falhou 39 | } 40 | catch(Fuel\Email\SendingFailedException $e) 41 | { 42 | // O driver não pode enviar o e-mail 43 | } 44 | finally 45 | { 46 | // Executado independentemente de se uma exceção foi acionada e antes de retomar a execução normal 47 | } 48 | {% endhighlight %} 49 | 50 | ### Exceções SPL 51 | 52 | A classe genérica `Exception` fornece muito pouco contexto de depuração para o desenvolvedor; no entanto, para remediar 53 | esta situação, é possível criar uma `Exception` especializada como sub-classes da classe genérica `Exception`: 54 | 55 | {% highlight php %} 56 | muitas exceções customizadas e algumas delas poderiam ter sido evitadas como o uso das 62 | Exceções SPL (exceções da biblioteca padrão) que estão disponíveis em [SPL extension][splext]. 63 | 64 | Se por exemplo você fizer uso do método mágico `__call()` e o método chamado for inválido, então em vez de disparar 65 | uma exceção padrão que seria muito vaga, ou criar uma exceção apenas para isso, você poderia disparar apenas um 66 | `throw new BadFunctionCallException;`. 67 | 68 | * [Leia sobre Exceções][exceptions] 69 | * [Leia sobre SPL Exceptions][splexe] 70 | * [Aninhando exceções no PHP][nesting-exceptions-in-php] 71 | * [Melhores práticas com exceções no PHP 5.3][exception-best-practices53] 72 | 73 | [exceptions]: http://php.net/language.exceptions 74 | [splexe]: http://php.net/spl.exceptions 75 | [splext]: {{ site.baseurl }}#standard_php_library 76 | [exception-best-practices53]: http://ralphschindler.com/2010/09/15/exception-best-practices-in-php-5-3 77 | [nesting-exceptions-in-php]: http://www.brandonsavage.net/exceptional-php-nesting-exceptions-in-php/ -------------------------------------------------------------------------------- /_posts/10-01-01-Security.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Segurança 3 | anchor: seguranca 4 | --- 5 | 6 | # Segurança {#seguranca_title} -------------------------------------------------------------------------------- /_posts/10-02-01-Web-Application-Security.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Segurança em uma Aplicação Web 3 | isChild: true 4 | anchor: seguranca_em_uma_aplicacao_web 5 | --- 6 | 7 | ## Segurança em uma Aplicação Web {#seguranca_em_uma_aplicacao_web_title} 8 | 9 | Existem pessoas ruins prontas e dispostas a invadir sua aplicação web. É importante que você tome as medidas 10 | necessárias para reforçar a segurança da sua aplicação web. Felizmente, o pessoal bacana da 11 | [Open Web Application Security Project][1] (OWASP) compilou uma lista abrangente dos problemas de segurança 12 | conhecidos e dos métodos para se proteger contra eles. É uma leitura obrigatória para o desenvolvedor preocupado com 13 | segurança. 14 | 15 | * [Leia o Guia OWASP de Segurança][2] 16 | 17 | [1]: https://www.owasp.org/ 18 | [2]: https://www.owasp.org/index.php/Guide_Table_of_Contents -------------------------------------------------------------------------------- /_posts/10-03-01-Password-Hashing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hash de Senhas 3 | isChild: true 4 | anchor: hash_de_senhas 5 | --- 6 | 7 | ## Hash de Senhas {#hash_de_senhas_title} 8 | 9 | No fim, todos construímos aplicações PHP que dependem de login dos usuários. Usuários e senhas (com hash) são 10 | armazenadas em um banco de dados e posteriormente são usados para autenticar os usuários no login. 11 | 12 | É importante que você faça adequadamente o [_hash_][3] das senhas que são armazenadas em um banco de dados. O hash da 13 | senha é irreversível, uma função executada contra a senha do usuário. Isto produz uma sequência de comprimento fixo que 14 | não pode ser revertido. Isto significa que você pode comparar um hash contra o outro para determinar se ambos foram 15 | produzidos da mesma string, mas você não pode determinar o string original. 16 | Se as senhas não estiverm com hash, e seu banco for hackeado ou acessado por alguém não autorizado, todas as contas dos 17 | usuários ficarão comprometidas. Alguns usuários (infelizmente) usam a mesma senha para outros serviços. Por isso, é 18 | importante levar segurança a sério. 19 | 20 | **Faça o hash das senhas com `password_hash`** 21 | 22 | No PHP 5.5 `password_hash` foi adicionado. Neste momento utiliza o BCrypt, o mais forte algorítimo suportado pelo PHP. 23 | Ele será atualizado no futuro para suportar mais algorítimos conforme for preciso. 24 | A biblioteca `password_compat` foi criada para ter compatibilidade para o PHP >= 5.3.7. 25 | 26 | Abaixo um exemplo, vamos fazer o hash de uma string, e em seguida, verificamos o hash contra uma nova string. 27 | As duas string são diferentes ('secret-password' vs. 'bad-password') e por isso o login falhará. 28 | 29 | {% highlight php %} 30 | = 5.3.7 && < 5.5] [2] 44 | * [Aprenda sobre hashing no que diz respeito à criptografia] [3] 45 | * [PHP `password_hash` RFC] [4] 46 | 47 | [1]: http://php.net/function.password-hash 48 | [2]: https://github.com/ircmaxell/password_compat 49 | [3]: http://en.wikipedia.org/wiki/Cryptographic_hash_function 50 | [4]: https://wiki.php.net/rfc/password_hash -------------------------------------------------------------------------------- /_posts/10-04-01-Data-Filtering.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Filtro de Dados 3 | isChild: true 4 | anchor: filtro_de_dados 5 | --- 6 | 7 | ## Filtro de Dados {#filtro_de_dados_title} 8 | 9 | Nunca, jamais (nunca mesmo), confie em entradas externas feitas no seu código PHP. Sempre higienize (sanitize) e valide 10 | as entradas externas antes de utilizá-las no seu código. As funcões `filter_var` e `filter_input` podem higienizar 11 | textos e validar formatos (e.g. endereços de email). 12 | 13 | Entradas externas podem ser qualquer coisa: dados de entrada de formulário `$_GET` ou `$_POST`, alguns valores na 14 | superglobal `$_SERVER` e o corpo da requisição HTTP via `fopen('php://input', 'r')`. Lembre-se, entradas externas não 15 | estão limitadas a dados de formulários enviados pelo usuário. Arquivos carregados e baixados, valores em sessões, 16 | dados dos cookies e dados de web services de terceiros também são entradas externas. 17 | 18 | Enquanto o dado externo puder ser armazenado, combinado ou acessado posteriormente, ele continua sendo uma entrada 19 | externa. Todo momento que você processar, emitir, concatenar ou incluir dados no seu código, pergunte a si mesmo se 20 | eles foram filtrados adequadamente e se são confiáveis. 21 | 22 | Os dados podem ser _filtrados_ de maneiras diferentes baseando-se em sua finalidade. Por exemplo, quando entradas 23 | externas não filtradas são passadas para uma saída de página HTML, elas podem executar HTML e JavaScript no seu site! 24 | Isso é conhecido como Cross-Site Scripting (XSS) e pode ser um ataque bem perigoso. Um modo de evitar o XSS é 25 | higienizar todas as tags HTML da entrada, removendo as tags ou escapando-as usando entidades HTML. 26 | 27 | Outro exemplo é ao passar opções para execução na linha de comando. Isso pode ser extremamente perigoso (e geralmente 28 | é má ideia), mas você pode usar a função embutida `escapeshellarg` para higienizar os argumentos executados. 29 | 30 | Um último exemplo é aceitar entradas externas para determinar o carregamento de um arquivo do sistema de arquivos. 31 | Isso pode ser explorado alterando o nome e o caminho do arquivo. Você precisa remover os "/", "../", [null bytes][6] e 32 | outros caracteres do caminho do arquivo, dessa forma não será possível carregar arquivos ocultos, privados ou 33 | confidenciais. 34 | 35 | * [Aprenda sobre filtro de dados][1] 36 | * [Aprenda sobre a `filter_var`][4] 37 | * [Aprenda sobre a `filter_input`][5] 38 | * [Aprenda sobre tratamento de null bytes][6] 39 | 40 | ### Higienização/Sanitization 41 | 42 | A higienização remove (ou "escapa") caracteres ilegais ou inseguros das entradas externas. 43 | 44 | Por exemplo, você deveria higienizar entradas externas antes de incluí-las no HTML ou de inseri-las em consultas SQL 45 | brutas. Quando você usar parâmetros restritos com a [PDO](#databases), ela já irá higienizar as entradas para você. 46 | 47 | Às vezes será obrigatório permitir algumas tags HTML seguras na sua entrada quando estiver incluindo-as em um página 48 | HTML. Isso é bem difícil de fazer e muitas evitam isso utilizando outros formatos mais restritos, como o Markdown ou 49 | o BBCode, embora bibliotecas para listas brancas/whitelistening, como a [HTML Purifier][html-purifier], existem por 50 | essa razão. 51 | 52 | [Veja sobre os Filtros de Higienização][2] 53 | 54 | ### Validação 55 | 56 | A validação garante que as entradas externas são o que você espera. Por exemplo, você pode querer validar um endereço 57 | de email, um número de telefone ou uma idade quando for processar o envio de um registro. 58 | 59 | [Veja sobre os Filtros de Validação][3] 60 | 61 | [1]: http://php.net/book.filter 62 | [2]: http://php.net/filter.filters.sanitize 63 | [3]: http://php.net/filter.filters.validate 64 | [4]: http://php.net/function.filter-var 65 | [5]: http://php.net/function.filter-input 66 | [6]: http://php.net/security.filesystem.nullbytes 67 | [html-purifier]: http://htmlpurifier.org/ -------------------------------------------------------------------------------- /_posts/10-05-01-Configuration-Files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Arquivos de Configuração 3 | isChild: true 4 | anchor: arquivos_de_configuracao 5 | --- 6 | 7 | ## Arquivos de Configuração {#arquivos_de_configuracao_title} 8 | 9 | Quando criar arquivos de configuração para suas aplicações, as melhores práticas recomendam que um dos seguintes métodos 10 | seja seguido: 11 | 12 | - É recomendado que você armazene sua informação de configuração onde ela não possa ser acessada diretamente ou puxada 13 | através do sistema de arquivos. 14 | - Se você tiver que armazenar seus arquivos de configuração no diretório raiz, nomeie os arquivos com a extensão `.php`. 15 | Isso garante que, mesmo se um script for acessado diretamente, ele não será mostrado como texto puro. 16 | - As informações nos arquivos de configuração devem ser adequadamente protegidas, ou através de criptografia ou por 17 | permissões de grupos/usuários no sistema de arquivos -------------------------------------------------------------------------------- /_posts/10-06-01-Register-Globals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Register Globals 3 | isChild: true 4 | anchor: register_globals 5 | --- 6 | 7 | ## Register Globals {#register_globals_title} 8 | 9 | **OBSERVAÇÃO:** A partir do PHP 5.4.0 a configuração `register_globals` foi removida e não pode mais ser utilizada. 10 | Isto só foi incluído como um alerta para alguém no processo de atualização de uma aplicação legada. 11 | 12 | Quando habilitada, a configuração `register_globals` torna disponível, no escopo global da sua aplicação, vários 13 | tipos de variáveis (`$_POST`, `$_GET` e `$_REQUEST`). Isso pode facilmente levar a problemas de segurança pois sua 14 | aplicação não pode dizer de forma efetiva de onde o dado está vindo. 15 | 16 | Por exemplo: `$_GET['foo']` poderia ficar disponível via `$foo`, o que poderia sobrescrever variáveis que não tiverem 17 | sido declaradas. Se você estiver usando PHP < 5.4.0 __garanta__ que `register_globals` esteja __desligado__. 18 | 19 | * [Register_globals no manual do PHP](http://php.net/security.globals) -------------------------------------------------------------------------------- /_posts/10-07-01-Error-Reporting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Relatório de Erros 3 | isChild: true 4 | anchor: relatorio_de_erros 5 | --- 6 | 7 | ## Relatório de Erros {#relatorio_de_erros_title} 8 | 9 | O registro de erros pode ser útil para encontrar pontos problemáticos em sua aplicação, mas isso também pode expor 10 | informações sobre a estrutura de sua aplicação para o mundo exterior. Para proteger efetivamente sua aplicação dos 11 | problemas que poderiam ser causados com a exposição dessas mensagens, você precisa configurar seu servidor de formas 12 | diferentes quando em desenvolvimento versus quando em produção (no ar). 13 | 14 | ### Desenvolvimento 15 | 16 | Para mostrar erros no seus ambiente de desenvolvimento, configure as definições a seguir no seu `php 17 | ini`: 18 | 19 | {% highlight ini %} 20 | display_errors = On 21 | display_startup_errors = On 22 | error_reporting = -1 23 | log_errors = On 24 | {% endhighlight %} 25 | 26 | Do [php.net](http://php.net/function.error-reporting): 27 | 28 | > Passar o valor -1 irá mostrar todos os erros possíveis, até mesmo quando novos níveis e constantes forem adicionados 29 | em versões futuras do PHP. A constante E_ALL também se comporta desta maneira a partir do PHP 5.4. 30 | 31 | O nível de error `E_STRICT` foi introduzido no 5.3.0 e não faz parte do `E_ALL`, contudo ele tornou-se parte do `E_ALL 32 | ` no 5.4.0. O que isso significa? Que para mostrar todos os erros possíveis na versão 5.3 você precisa usar `-1` ou 33 | `E_ALL | E_STRICT`. 34 | 35 | **Reportando todos os erros possíveis em diferentes versões do PHP** 36 | 37 | * < 5.3 `-1` ou `E_ALL` 38 | *   5.3 `-1` ou `E_ALL | E_STRICT` 39 | * > 5.3 `-1` ou `E_ALL` 40 | 41 | ### Produção 42 | 43 | Para esconder os erros no seu ambiente de produção, configure seu `php.ini` assim: 44 | 45 | {% highlight ini %} 46 | display_errors = Off 47 | display_startup_errors = Off 48 | error_reporting = E_ALL 49 | log_errors = On 50 | {% endhighlight %} 51 | 52 | Com essas configurações em produção, os erros continuarão sendo registrados nos logs de erros do servidor web, mas 53 | eles não serão mostrados para o usuário. Para mais informações sobre essas configurações, veja o manual do PHP: 54 | 55 | * [error_reporting](http://php.net/errorfunc.configuration#ini.error-reporting) 56 | * [display_errors](http://php.net/errorfunc.configuration#ini.display-errors) 57 | * [display_startup_errors](http://php.net/errorfunc.configuration#ini.display-startup-errors) 58 | * [log_errors](http://php.net/errorfunc.configuration#ini.log-errors) 59 | -------------------------------------------------------------------------------- /_posts/11-01-01-Testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Testes 3 | anchor: testes 4 | --- 5 | 6 | # Testes {#testes_title} 7 | 8 | Escrever testes automatizados para o seu código PHP é considerado uma boa prática, e leva a aplicações bem escritas. 9 | Testes automatizados são uma excelente ferramenta para garantir que sua aplicação não irá quebrar quando você estiver 10 | fazendo alterações ou adicionando novas funcionalidades, e não deveriam ser ignorados. 11 | 12 | Existem vários tipos diferentes de ferramentas de testes (ou frameworks) disponíveis para PHP, com diferentes 13 | abordagens: todas elas tentam evitar os testes manuais e a necessidade de equipes grandes de Garantia de Qualidade 14 | Quality Assurance, ou QA) apenas para garantir que alterações recentes não interrompam funcionalidade existentes. -------------------------------------------------------------------------------- /_posts/11-02-01-Test-Driven-Development.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Desenvolvimento Guiado por Testes 3 | isChild: true 4 | anchor: desenvolvimento_guiado_por_testes 5 | --- 6 | 7 | ## Desenvolvimento Guiado por Testes {#desenvolvimento_guiado_por_testes_title} 8 | 9 | Da [Wikipedia](http://en.wikipedia.org/wiki/Test-driven_development): 10 | 11 | > O desenvolvimento guiado por testes (TDD) é um processo de desenvolvimento que se baseia na repetição de um ciclo 12 | de desenvolvimento bem curto: primeiro o desenvolvedor escreve um caso de teste automatizado que falha, definindo uma 13 | melhoria ou uma nova função desejada, em seguida produz o código para passar no teste, e finalmente refatora o novo 14 | código pelos padrões aceitáveis. Kent Beck, que é creditado como quem desenvolveu ou "redescobriu" essa técnica, 15 | afirmou em 2003 que o TDD encoraja design simples e inspira confiança. 16 | 17 | Existem vários tipos diferentes de testes que você pode fazer para sua aplicação. 18 | 19 | ### Testes Unitários {#testes_unitarios} 20 | 21 | Testes unitários são uma metodologia de programação que garante que as funções, as classes e os métodos estão 22 | funcionando como esperado, desde o momento que você os constrói até o fim do ciclo de desenvolvimento. Verificando 23 | como os valores entram e saem em várias funções e métodos, você pode garantir que a lógica interna está funcionando 24 | corretamente. Utilizando Injeção de Dependências e construindo classes "mock" e stubs, você pode verificar se as 25 | dependências foram utilizadas corretamente para uma cobertura de testes ainda melhor. 26 | 27 | Quando for criar uma classe ou função, você deveria criar um teste unitário para cada comportamento que ela deveria 28 | ter. Num nível bem básico, você deveria garantir que são emitidos erros quando você envia argumentos errados e 29 | garantir que tudo funciona bem se você enviar argumentos válidos. Isso ajudará a garantir que, quando você alterar 30 | sua classe ou sua função posteriormente no ciclo de desenvolvimento, as funcionalidades antigas continuarão 31 | funcionando como esperado. A única alternativa a isso seria usar var_dump() em um test.php, o que não é o certo a 32 | fazer na construção de uma aplicação - grande ou pequena. 33 | 34 | O outro uso para testes unitários é contribuir para projetos open source. Se você puder escrever um teste que 35 | demonstra uma funcionalidade incorreta (i.e. uma falha), em seguida consertá-la e mostrar o teste passando, os 36 | patches serão muito mais suscetíveis a serem aceitos. Se você estiver em um projeto que aceite pull requests, você 37 | deveria sugerir isso como um requisito. 38 | 39 | O [PHPUnit](http://phpunit.de) é o framework de testes de fato para escrever testes unitários em aplicações PHP, mas 40 | existem várias alternativas: 41 | 42 | * [SimpleTest](http://simpletest.org) 43 | * [Enhance PHP](http://www.enhance-php.com/) 44 | * [PUnit](http://punit.smf.me.uk/) 45 | * [atoum](https://github.com/mageekguy/atoum) 46 | 47 | ### Testes de Integração {#testes_integracao} 48 | 49 | Da [Wikipedia](http://en.wikipedia.org/wiki/Integration_testing): 50 | 51 | > Testes de integração (chamado às vezes de "Integração e Teste", abreviado como "I&T") é a fase do teste do software 52 | na qual módulos individuais do sistema são combinados e testados como um grupo. Ela acontece após os testes unitários 53 | e antes dos testes de validação. Os testes de integração recebem como entrada os módulos que foram testados 54 | unitariamente, os agrupa em grandes blocos, aplica testes definidos em um plano de teste de integração, e entrega como 55 | saída o sistema integrado pronto para os testes de sistema. 56 | 57 | Muitos das mesmas ferramentas que são usadas para testes unitários podem ser usadas para testes de integração, pois 58 | muitos dos mesmos princípios são usados. 59 | 60 | ### Testes Funcionais {#testes_funcionais} 61 | 62 | Algumas vezes conhecidos também como testes de aceitação, os testes funcionais consistem em utilizar ferramentas para 63 | criar testes automatizados que usem de verdade sua aplicação, em vez de apenas verificar se unidades individuais de 64 | código se comportam adequadamente ou se essas partes conversam entre si do jeito certo. Essas ferramentas geralmente 65 | trabalham usando dados reais e simulam usuários verdadeiros da sua aplicação. 66 | 67 | #### Ferramentas para Testes Funcionais {#ferramentas_para_testes_funcionais} 68 | 69 | * [Selenium](http://seleniumhq.com) 70 | * [Mink](http://mink.behat.org) 71 | * O [Codeception](http://codeception.com) é um framework de testes full-stack que inclui ferramentas para testes de 72 | aceitação 73 | * O [Storyplayer](http://datasift.github.io/storyplayer/) é um framework de testes full-stack que inclui suporte para 74 | criação e destruição de ambientes sob demanda -------------------------------------------------------------------------------- /_posts/11-03-01-Behavior-Driven-Development.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Desenvolvimento Guiado por Comportamentos 3 | isChild: true 4 | anchor: desenvolvimento_guiado_por_comportamentos 5 | --- 6 | 7 | ## Desenvolvimento Guiado por Comportamentos {#desenvolvimento_guiado_por_comportamentos_title} 8 | 9 | Existem dois tipos diferentes de Desenvolvimento Guiado por Comportamentos (BDD): o SpecBDD e o StoryBDD. O SpecBDD 10 | foca nos comportamentos técnicos, no código, enquanto que o StoryBDD foca nos comportamentos de negócio e de 11 | funcionalidades, nas interações. O PHP possui frameworks para ambos os tipos de BDD. 12 | 13 | No StoryBDD, você escreve histórias humanamente legíveis que descrevem o comportamento da sua aplicação. Estas 14 | histórias podem então ser executadas como testes reais em sua aplicação. O framework usado nas aplicações PHP para 15 | StoryBDD é o Behat, que foi inspirado no projeto [Cucumber](http://cukes.info/) do Ruby e implementa a linguagem 16 | Gherkin DSL para descrever o comportamento das funcionalidades. 17 | 18 | No SpecBDD, você escreve as especificações que descrevem como seu código real deveria se comportar. Em vez de escrever 19 | uma função ou método, você descreve como a função ou o método deveriam se comportar. O PHP fornece o framework PHPSpec 20 | para esse propósito. Esse framework foi inspirado no [projeto RSpec](http://rspec.info/) do Ruby. 21 | 22 | ### Links sobre BDD 23 | 24 | * O [Behat](http://behat.org/) é inspirado pelo projeto [Cucumber](http://cukes.info/) do Ruby 25 | * O [PHPSpec](http://www.phpspec.net/) é o framework para SpecBDD do PHP 26 | * O [Codeception](http://www.codeception.com) é um framework de testes full-stack que usa os princípios do BDD -------------------------------------------------------------------------------- /_posts/11-04-01-Complementary-Testing-Tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ferramentas Complementares para Testes 3 | isChild: true 4 | anchor: ferramentas_complementares_para_testes 5 | --- 6 | 7 | ## Ferramentas Complementares para Testes {#ferramentas_complementares_para_testes_title} 8 | 9 | Além dos testes individuais e dos frameworks guiados por comportamentos, também existe uma série de frameworks 10 | genéricos e bibliotecas auxiliares úteis para qualquer das abordagem escolhidas. 11 | 12 | ### Links para as Ferramentas 13 | 14 | * O [Selenium](http://seleniumhq.org/) é uma ferramenta para automação de navegação que pode ser 15 | [intregada ao PHPUnit](http://www.phpunit.de/manual/3.1/en/selenium.html) 16 | * O [Mockery](https://github.com/padraic/mockery) é um Framework para Objetos Mock que pode ser integrado ao 17 | [PHPUnit](http://phpunit.de/) e ao [PHPSpec](http://www.phpspec.net/). 18 | * O [Prophecy](https://github.com/phpspec/prophecy) é um framework para Objetos Mock bastante obstinado porém poderoso 19 | e flexível. É integrado com PHPSpec e pode ser usado com PHPUnit(http://phpunit.de/). -------------------------------------------------------------------------------- /_posts/12-01-01-Servers-and-Deployment.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Servidores e Publicação 3 | anchor: servidores_e_publicacao 4 | --- 5 | 6 | # Servidores e Publicação {#servidores_e_publicacao_title} 7 | 8 | As aplicações PHP podem ser publicadas e executadas em servidores web de produção de diversas formas. -------------------------------------------------------------------------------- /_posts/12-02-01-Platform-as-a-Service.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Plataforma como Serviço (PaaS) 3 | isChild: true 4 | anchor: plataforma_como_servico_paas 5 | --- 6 | 7 | ## Plataforma como Serviço (PaaS) {#plataforma_como_servico_paas_title} 8 | 9 | O PaaS fornece o sistema e a arquitetura de rede necessários para executar aplicações PHP na web. Isso significa não 10 | precisar de quase nenhuma configuração para publicar aplicações ou frameworks PHP. 11 | 12 | Recentemente o PaaS se tornou um método popular para publicar, hospedar e escalar aplicações PHP de todos os tamanho 13 | . Você pode encontrar uma lista de [fornecedores de PHP PaaS "Platform as a Service"](#php_paas_providers) na 14 | [seção sobre recursos](#resources). -------------------------------------------------------------------------------- /_posts/12-03-01-Virtual-or-Dedicated-Servers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Servidores Virtuais ou Dedicados 3 | isChild: true 4 | anchor: servidores_virtuais_ou_dedicados 5 | --- 6 | 7 | ## Servidores Virtuais ou Dedicados {#servidores_virtuais_ou_dedicados_title} 8 | 9 | Se você estiver confortável com administração de sistemas, ou estiver interessado em aprender sobre isso, os 10 | servidores virtuais ou dedicados te dão controle completo do ambiente de produção da sua aplicação. 11 | 12 | ### nginx e PHP-FPM 13 | 14 | O PHP, por meio do seu Gerenciador de Processos FastCGI (FPM), funciona muito bem junto com o [nginx](http://nginx.or), 15 | que é um servidor web leve e de alta performance. Ele usa menos memória do que o Apache e pode lidar melhor como 16 | muitas requisições concorrentes. Ele é importante especialmente em servidores virtuais que não tem muita memória 17 | sobrando. 18 | 19 | * [Leia mais sobre o nginx](http://nginx.org) 20 | * [Leia mais sobre o PHP-FPM](http://php.net/install.fpm) 21 | * [Leia mais sobre como configurar de forma segura o nginx e o PHP-FPM](https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/) 22 | 23 | ### Apache e PHP 24 | 25 | O PHP e o Apache tem um longo histórico juntos. O Apache é amplamente configurável e tem muitos 26 | [módulos](http://httpd.apache.org/docs/2.4/mod/) disponíveis para estender suas funcionalidades. Ele é uma escolha 27 | popular para servidores compartilhados e pela configuração fácil em frameworks PHP e aplicativos open source como, o 28 | Wordpress. Infelizmente, o Apache utiliza mais recursos do que o nginx por padrão e não pode lidar com tantos 29 | visitantes ao mesmo tempo. 30 | 31 | O Apache tem várias configurações possíveis para executar o PHP. A mais comum e mais fácil para configurar é a 32 | [prefork MPM](http://httpd.apache.org/docs/2.4/mod/prefork.html) com o mod_php5. Mesmo não sendo a mais eficiente em 33 | memória, é a mais simples para começar a usar. Essa é provavelmente a melhor escolha se você não quiser entrar muito 34 | profundamente nos aspectos de administração do servidor. Observe que, se você usar o mod_php5, terá que usar o prefork 35 | MPM. 36 | 37 | Alternativamente, se você quiser extrair mais performance e estabilidade do seu Apache então você poderia se 38 | beneficiar do mesmo sistema FPM que o nginx e executar o [worker MPM](http://httpd.apache.org/docs/2.4/mod/worker.htm) 39 | ou o [event MPM](http://httpd.apache.org/docs/2.4/mod/event.html) com o mod_fastcgi ou com o mod_fcgi. Essa 40 | configuração será significativamente mais eficiente em relação a memória e muito mais rápida, mas gera mais trabalho. 41 | 42 | * [Leia mais sobre o Apache](http://httpd.apache.org/) 43 | * [Leia mais sobre os Multi-Processing Modules](http://httpd.apache.org/docs/2.4/mod/mpm_common.html) 44 | * [Leia mais sobre o mod_fastcgi](http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html) 45 | * [Leia mais sobre o mod_fcgid](http://httpd.apache.org/mod_fcgid/) -------------------------------------------------------------------------------- /_posts/12-04-01-Shared-Servers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Servidores Compartilhados 3 | isChild: true 4 | anchor: servidores_compartilhados 5 | --- 6 | 7 | ## Servidores Compartilhados {#servidores_compartilhados_title} 8 | 9 | O PHP tem que agradecer aos servidores compartilhados por sua popularidade. É difícil encontrar uma hospedagem que 10 | não tenha o PHP instalado, mas certifique-se de que seja a última versão. Servidores compartilhados permitem que você 11 | e outros desenvolvedores publiquem sites em uma única máquina. A parte boa é que isso se tornou uma commodity barata. 12 | A parte ruim é que você nunca sabe que tipo de bagunça seus vizinhos vão criar; sobrecarregamento do servidor e 13 | abertura de falhas de segurança são os principais problemas. Evite usar servidores compartilhados se o orçamento de seu 14 | projeto permitir. -------------------------------------------------------------------------------- /_posts/12-05-01-Building-your-Application.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Compilando e Implementando sua Aplicação 3 | isChild: true 4 | anchor: compilando_e_implementando_sua_aplicacao 5 | --- 6 | 7 | ## "Compilando" e Implementando sua Aplicação {#compilando_e_implementando_sua_aplicacao_title} 8 | 9 | Se você se pegar fazendo alterações manuais no seu esquema do banco de dados ou rodando seus testes manualmente antes de 10 | alterar seus arquivos (manualmente), pense duas vezes! A cada tarefa manual adicional necessária para implementar uma 11 | nova versão da sua aplicação as chances de erros fatais são potencialmente maiores, Seja lidando com uma simples 12 | atualização, um processo completo de implementação ou até mesmo uma estratégia de integração contínua, a 13 | [Automação de Compilação](http://en.wikipedia.org/wiki/Build_automation) é sua amiga. 14 | 15 | Entre as tarefas que talvez você deseja automatizar estão: 16 | 17 | * Gerenciamento de Dependências 18 | * Compilação e Compressão de Arquivos 19 | * Execução de Testes 20 | * Criação de Documentação 21 | * Empacotamento 22 | * Implementação 23 | 24 | ### Ferramentas de Automação 25 | 26 | Ferramentas de automação podem ser descritas como uma coleção de scripts que tratam de tarefas comuns da implementação 27 | de software. As ferramentas de automação não são parte da sua aplicação, elas agem na sua aplicação externamente. 28 | 29 | Existem muitas ferramentas de código aberto disponíveis para ajudar você com o processo de automação, algumas são 30 | escritas em PHP, outras não. Isso não deve impedi-lo de usá-las, se elas se ajustarem melhor ao trabalho em questão. 31 | Aqui estão alguns exemplos: 32 | 33 | [Phing](http://www.phing.info/) é o jeito mais fácil de começar com automação de implementação no PHP. Com Phing você 34 | pode controlar os processos de empacotamento, implementação e testes através de um simples arquivo XML. Phing (Que é 35 | baseado em [Apache Ant](http://ant.apache.org/)) fornece um rico conjunto de tarefas geralmente necessárias para 36 | instalar ou atualizar uma aplicação web e pode ser estendido com tarefas adicionais personalizadas, escritas em PHP. 37 | 38 | [Capistrano](https://github.com/capistrano/capistrano/wiki) é um sistema para *programadores intermediarios ou 39 | avançados* que executa comando de forma estruturada e repetitiva em uma ou mais maquinas. Ele é pré-configurado para 40 | implementar aplicações Ruby on Rails, entretanto pessoas estão **implementando com sucesso sistemas em PHP** com ele. 41 | Ter sucesso com uso de Capistrano depende de um conhecimento de trabalho com Ruby e Rails. 42 | 43 | O artigo de Dave Gardner [PHP Deployment com Capistrano](http://www.davegardner.me.uk/blog/2012/02/13/php-deployment-with-capistrano/) 44 | é um bom ponto de partida para desenvolvedores PHP interessando em Capistrano. 45 | 46 | [Chef](http://www.opscode.com/chef/) é mais que um framework de implementação, é um framework de integração bastante 47 | poderoso escrito em Ruby que não consegue apenas implementar sua aplicação mas também construir seu ambiente de servidor 48 | completo em maquinas virtuais. 49 | 50 | Conteúdo sobre Chef para Desenvolvedores PHP: 51 | 52 | * [Serie em 3 partes sobre implementação de uma aplicação LAMP com Chef, Vagrant, e EC2](http://www.jasongrimes.org/2012/06/managing-lamp-environments-with-chef-vagrant-and-ec2-1-of-3/) 53 | * [Chef Cookbook sobre instalação e configuração de PHP 5.3 e do sistema de gerenciamento de pacotes PEAR](https://github.com/opscode-cookbooks/php) 54 | * [Chef - série de video tutoriais por Opscode, os criadores do chef](https://www.youtube.com/playlist?list=PLrmstJpucjzWKt1eWLv88ZFY4R1jW8amR) 55 | 56 | Leitura Adicional: 57 | 58 | * [Automatize seu projeto com Apache Ant](http://net.tutsplus.com/tutorials/other/automate-your-projects-with-apache-ant/) 59 | 60 | ### Integração Contínua 61 | 62 | > Integração Contínua é uma prática de desenvolvimento de software onde membros de um time integram seu trabalho com 63 | > frequência, geralmente essa integração ocorre diariamente - levando a muitas integrações de código por dia. Muitos 64 | > times acreditam que essa abordagem leva a reduções significativas dos problemas de integração e permite que o time 65 | > desenvolva software de forma coesa e rápida. 66 | 67 | *-- Martin Fowler* 68 | 69 | Existem diferentes formas de se implementar integração contínua com PHP. Recentemente o [Travis CI](https://travis-ci.org/) 70 | tem feito um ótimo trabalho ao fazer da integração contínua uma realidade mesmo para pequenos projetos. O Travis CI é um 71 | sistema de integração contínua na nuvem desenvolvido pela comunidade de código livre. Esta integrado com GitHub e oferece 72 | suporte de primeira classe para muitas linguagens incluindo PHP. 73 | 74 | Leitura Adicional: 75 | 76 | * [Integração Contínua com Jenkins](http://jenkins-ci.org/) 77 | * [Integração Contínua com PHPCI](http://www.phptesting.org/) 78 | * [Integração Contínua com Teamcity](http://www.jetbrains.com/teamcity/) -------------------------------------------------------------------------------- /_posts/13-01-01-Virtualization.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Virtualização 3 | anchor: virtualizacao 4 | --- 5 | 6 | ## Virtualização {#virtualizacao_title} 7 | 8 | Executar seu aplicativo em ambientes diferentes de desenvolvimento e produção pode levar a aparecer erros estranhos. 9 | Também é complicado manter diferentes ambientes de desenvolvimento atualizados com a mesma versão de todas as 10 | bibliotecas usadas quando se trabalha com uma equipe de desenvolvedores. 11 | 12 | Se você estiver desenvolvendo em Windows e implantando de Linux (ou qualquer coisa não-Windows) ou estão desenvolvendo 13 | em uma equipe, você deve considerar o uso de uma máquina virtual. 14 | Isso parece complicado, mas além dos ambientes de virtualização amplamente conhecidos como o VMware ou VirtualBox, 15 | existem ferramentas adicionais que podem ajudá-lo a configurar um ambiente virtual em algumas etapas fáceis. -------------------------------------------------------------------------------- /_posts/13-02-01-Vagrant.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vagrant 3 | isChild: true 4 | anchor: vagrant 5 | --- 6 | 7 | ## Vagrant {#vagrant_title} 8 | 9 | O [Vagrant][vagrant] ajuda a construir suas máquinas virtuais em cima de ambientes virtuais conhecidos e a configurar 10 | esses ambientes com base em um único arquivo de configuração. 11 | As máquinas virtuais base (box) podem ser configuradas manualmente, ou você pode usar um software de "provisionamento" 12 | como o [Puppet][puppet] ou o [Chef][chef] para fazer isso por você. Provisionar o box é uma ótima maneira de garantir 13 | que as múltiplas máquinas virtuais sejam configuradas de forma idêntica e que você não necessite manter complicadas 14 | listas de comandos de configuração. Você pode também destruir (destroy) o box base e recriá-lo sem muitos passos 15 | manuais, tornando fácil criar instalações novas. 16 | 17 | O Vagrant cria pastas compartilhadas para compartilhar seu código entre sua máquina e a máquina virtual, assim você 18 | pode criar e editar seus arquivos na sua máquina e então executar seu código dentro da máquina virtual. 19 | 20 | ### Uma pequena ajuda 21 | 22 | Se você precisa de uma pequena ajuda para inciar o uso do Vagrant existem dois serviços que podem ser úteis: 23 | - [Rove][rove]: serviço que permite que você gere configurações típicas do Vagrant, sendo o PHP uma das opções. O 24 | provisionamento é realizado com Chef. 25 | - [Puphpet][puphpet]: interface gráfica simples de configurar máquinas virtuais para o desenvolvimento PHP. **Altamente 26 | focada em PHP**. Além VMs local, ele pode ser usado para implantar em serviços de nuvem também. O provisionamento é 27 | feito com Puppet. 28 | - [Protobox][protobox]: é uma camada em cima do vagrant e uma interface gráfica web para configuração de máquinas 29 | virtuais para o desenvolvimento web. Um único documento YAML controla tudo o que está instalado na máquina virtual. 30 | - [Phansible][phansible]: oferece uma interface que ajuda a gerar Ansible Playbooks para projetos baseados em PHP. 31 | 32 | [vagrant]: http://vagrantup.com/ 33 | [puppet]: http://www.puppetlabs.com/ 34 | [chef]: http://www.opscode.com/ 35 | [rove]: http://rove.io/ 36 | [puphpet]: https://puphpet.com/ 37 | [protobox]: http://getprotobox.com/ 38 | [phansible]: http://phansible.com/ -------------------------------------------------------------------------------- /_posts/13-03-01-Docker.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docker 3 | isChild: true 4 | anchor: docker 5 | --- 6 | 7 | ## Docker {#docker_title} 8 | 9 | Junto ao Vagrant, uma outra maneira fácil de obter um ambiente de desenvolvimento ou produção virtual instalado e 10 | funcionando é o [Docker][docker]. 11 | O Docker ajuda você a fornecer recipientes Linux para todos os tipos de aplicações. 12 | Há muitas imagens Docker úteis que podem fornecer outros grandes serviços sem a necessidade de instalar estes serviços 13 | em sua máquina local, por exemplo, MySQL ou PostgreSQL e muito mais. 14 | Dê uma olhada no [Docker Hub Registry][docker-hub] para procurar uma lista de recipientes pré-construídos disponíveis, 15 | que você pode executar e usar em poucos passos. 16 | 17 | ### Exemplo: Runnning suas aplicações PHP em Docker 18 | 19 | Depois de [instalar o docker][docker-install] em sua máquina, você pode iniciar um apache com suporte a PHP em uma 20 | única etapa. 21 | O comando a seguir irá baixar uma instalação apache totalmente funcional com a última versão do PHP e fornecer o 22 | diretório `/path/to/your/php/files` em `http://localhost:8080`: 23 | 24 | {% highlight console %} 25 | docker run -d --name my-php-webserver -p 8080:80 -v /path/to/your/php/files:/var/www/html/ php:apache 26 | {% endhighlight %} 27 | 28 | Depois de executar o `docker run` seu recipiente estará inicializado e funcionando. 29 | Se você quiser parar (stop) ou iniciar (start) o seu recipiente novamente, você pode usar o atributo `--name` 30 | fornecido e simplesmente executar o `docker stop my-php-webserver` e `docker start my-php-webserver` sem fornecer 31 | novamente os demais parâmetros mencionados acima. 32 | 33 | ### Saiba mais sobre Docker 34 | 35 | Os comandos mencionados acima mostram apenas uma maneira rápida de executar um servidor web apache com suporte a PHP, 36 | mas há muito mais coisas que você pode fazer com Docker. 37 | Uma das coisas mais importantes para os desenvolvedores de PHP é ligar seu servidor web com uma instância de banco de 38 | dados, por exemplo. 39 | Como fazer isso está bem descrito no [Guia do Usuário Docker][docker-doc]. 40 | 41 | * [Docker][docker] 42 | * [Instalação do Docker][docker-install] 43 | * [Imagens Docker no Docker Hub Registry][docker-hub] 44 | * [Guia do Usuário Docker][docker-doc] 45 | 46 | [docker]: http://docker.com/ 47 | [docker-hub]: https://registry.hub.docker.com/ 48 | [docker-install]: https://docs.docker.com/installation/ 49 | [docker-doc]: https://docs.docker.com/userguide/ -------------------------------------------------------------------------------- /_posts/14-01-01-Caching.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cache 3 | anchor: cache 4 | --- 5 | 6 | # Cache {#cache_title} 7 | 8 | O PHP é bem rápido por si só, mas gargalos podem aparecer quando você faz conexões remotas, ou carrega arquivos etc. 9 | Felizmente, existem várias ferramentas disponíveis para acelerar certas partes de sua aplicação, ou para reduzir o 10 | número de vezes que essas tarefas, que tomam tempo, precisem ser executadas. -------------------------------------------------------------------------------- /_posts/14-02-01-Bytecode-Cache.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cache de Bytecode 3 | isChild: true 4 | anchor: cache_de_bytecode 5 | --- 6 | 7 | ## Cache de Bytecode {#cache_de_bytecode_title} 8 | 9 | Quando um arquivo PHP é executado, por baixo dos panos ele primeiro é compilado para bytecode (também conhecido como 10 | opcode) e, só aí, o bytecode é executado. Se o arquivo PHP não foi modificado, o bytecode será sempre o mesmo. Isso 11 | significa que o passo de compilação é um desperdício de recursos de CPU. 12 | 13 | É aqui que entra o cache de Bytecode. Ele previne as compilações redundantes armazenando bytecode na memória e 14 | reutilizando-o em chamadas sucessivas. A configuração do cache de bytecode é feita em questão de minutos, e sua 15 | aplicação irá acelerar de forma significativa. Não existe razão para não utilizá-lo. 16 | 17 | No PHP 5.5 o OPcache foi incluído como um cache de bytecode nativo chamado [OPcache][opcache-book]. Ele também está 18 | disponível para versões anteriores. 19 | 20 | Caches de bytecode populares são: 21 | 22 | * [OPcache][opcache-book] (desde o PHP 5.5) 23 | * [APC](http://php.net/manual/en/book.apc.php) (PHP 5.4 e anteriores) 24 | * [XCache](http://xcache.lighttpd.net/) 25 | * [Zend Optimizer+](http://www.zend.com/products/server/) (parte do pacote Zend Server) 26 | * [WinCache](http://www.iis.net/download/wincacheforphp) (extensão para o MS Windows Server) 27 | 28 | [opcache-book]: http://php.net/manual/en/book.opcache.php -------------------------------------------------------------------------------- /_posts/14-03-01-Object-Caching.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cache de Objetos 3 | isChild: true 4 | anchor: cache_de_objetos 5 | --- 6 | 7 | ## Cache de Objetos {#cache_de_objetos_title} 8 | 9 | Existem momentos onde pode ser benéfico fazer cache de objetos individuais no seu código, como em dados que são 10 | custosos de conseguir ou em chamadas de bancos de dados cujo resultado dificilmente se modifica. Você pode usar um 11 | software de cache de objetos para armazenar esses pedaços de dados na memória, para acessá-los posteriomente de forma 12 | extremamente rápida. Se você guardar esses itens em um data store logo que os recuperar, e depois os enviar 13 | diretamente do cache para as suas requisições posteriores, você conseguirá uma melhora significativa no desempenho 14 | além de reduzir a carga nos seus servidores de banco de dados. 15 | 16 | Muitas das soluções populares de cache de bytecode permitem que você também faça cache de dados personalizados, assim 17 | há ainda mais razões para se beneficiar deles. Tanto o APC, quanto o XCache e o Wincache fornecem APIs para armazenar 18 | dados do seu código PHP na memória cache deles. 19 | 20 | Os sistemas mais usados para cache de objetos em memória são o APC e o memcached. O APC é uma escolha excelente para 21 | cache de objetos, ele inclui uma API simples para adicionar seus próprios dados para seu cache de memória e é muito 22 | fácil de configurar e utilizar. A única limitação real do APC é que ele fica amarrado ao servidor onde ele está 23 | instalado. O memcached por outro lado é instalado como um serviço separado e pode ser acessado através da rede, assim 24 | você pode armazenar objetos em um data store ultra-rápido, em uma localização central, e vários sistemas diferentes 25 | podem acessá-lo. 26 | 27 | Note que se estiver rodando o PHP como uma aplicação (Fast-)CGI dentro do seu servidor web, cada processo do PHP terá 28 | seu próprio cache, ou seja, os dados de APCu não são compartilhados entre diferentes processos. Nesse caso você deve 29 | considerar usar mecached em seu lugar, já que ele não está ligado aos processos do PHP. 30 | 31 | Em uma configuração em rede, o APC geralmente terá um desempenho melhor do que o memcached em termos da velocidade de 32 | acesso, mas o memcached poderá escalar mais rápido e melhor. Se você não planeja ter múltiplo servidores executando 33 | sua aplicação, ou não precisar das funcionalidades extras que o memcached oferece, então o APC provavelmente é sua 34 | melhor opção para cache de objetos. 35 | 36 | Exemplo de lógica usando APC: 37 | 38 | {% highlight php %} 39 | 18 | * @link http://www.phpdoc.org/docs/latest/index.html 19 | * @package helper 20 | */ 21 | class DateTimeHelper 22 | { 23 | /** 24 | * @param mixed $anything Tudo que podemos converter para um objeto \DateTime 25 | * 26 | * @return \DateTime 27 | * @throws \InvalidArgumentException 28 | */ 29 | public function dateTimeFromAnything($anything) 30 | { 31 | $type = gettype($anything); 32 | 33 | switch ($type) { 34 | // Algum código que tenta retornar um objeto \DateTime 35 | } 36 | 37 | throw new \InvalidArgumentException( 38 | "Failed Converting param of type '{$type}' to DateTime object" 39 | ); 40 | } 41 | 42 | /** 43 | * @param mixed $date Tudo que podemos converter para um objeto \DateTime 44 | * 45 | * @return void 46 | */ 47 | public function printISO8601Date($date) 48 | { 49 | echo $this->dateTimeFromAnything($date)->format('c'); 50 | } 51 | 52 | /** 53 | * @param mixed $date Tudo que podemos converter para um objeto \DateTime 54 | */ 55 | public function printRFC2822Date($date) 56 | { 57 | echo $this->dateTimeFromAnything($date)->format('r'); 58 | } 59 | } 60 | {% endhighlight %} 61 | 62 | A documentação para a classe como um todo, em primeiro lugar tem a tag 63 | [@author](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/author.html), esta tag é usada para documentar o 64 | autor do código e pode ser repetido para documentar vários autores. Em segundo lugar é a tag 65 | [@link](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/link.html), usada para conectar-se a um site que 66 | indica uma relação entre o site eo código. Em terceiro lugar, tem a tag 67 | [@package](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/package.html), usada para categorizar o código. 68 | 69 | Dentro da classe, o primeiro método tem uma tag 70 | [@param](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/param.html) usada para documentar o tipo, nome e 71 | descrição do parâmetro sendo passado para o método. Além disso, ele tem as tags 72 | [@return](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/return.html) e 73 | [@throws](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/throws.html) para documentar o tipo de retorno e 74 | todas as exceções que podem ser lançadas respectivamente. 75 | 76 | O segundo e terceiro métodos são muito semelhantes e têm uma única marcação 77 | [@param](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/param.html), assim como o primeiro método. A 78 | diferença de importação entre o segundo eo terceiro método é bloco doc é a inclusão/exclusão da tag 79 | [@return](http://www.phpdoc.org/docs/latest/references/phpdoc/tags/return.html). `@return void` nos informa 80 | explicitamente que não há retorno, historicamente omitir a declaração `@return void` também resulta na mesma ação 81 | (sem retorno). -------------------------------------------------------------------------------- /banners.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Banners para divulgação 4 | description: "Espalhe a palavra! Use estes banners para permitir que novos programadores PHP saibam sobre PHP: Do Jeito 5 | Certo" 6 | --- 7 | 8 | # Banners para divulgação 9 | 10 | Espalhe a palavra com os banners _PHP: Do Jeito Certo_! Mostre à novos programadores PHP onde encontrar boa informação. 11 | 12 | ## Botão 1 (120x90) 13 | 14 |

    PHP: Do Jeito Certo

    15 | 16 | {% highlight html %} 17 | 18 | PHP: Do Jeito Certo 19 | 20 | {% endhighlight %} 21 | 22 | ## Botão 2 (120x60) 23 | 24 |

    PHP: Do Jeito Certo

    25 | 26 | {% highlight html %} 27 | 28 | PHP: Do Jeito Certo 29 | 30 | {% endhighlight %} 31 | 32 | ## Leaderboard (728x90) 33 | 34 |

    PHP: Do Jeito Certo

    35 | 36 | {% highlight html %} 37 | 38 | PHP: Do Jeito Certo 39 | 40 | {% endhighlight %} 41 | 42 | ## Retângulo Grande (386x280) 43 | 44 |

    PHP: Do Jeito Certo

    45 | 46 | {% highlight html %} 47 | 48 | PHP: Do Jeito Certo 49 | 50 | {% endhighlight %} 51 | 52 | ## Retângulo Médio (300x250) 53 | 54 |

    PHP: Do Jeito Certo

    55 | 56 | {% highlight html %} 57 | 58 | PHP: Do Jeito Certo 59 | 60 | {% endhighlight %} 61 | 62 | ## Retângulo (180x150) 63 | 64 |

    PHP: Do Jeito Certo

    65 | 66 | {% highlight html %} 67 | 68 | PHP: Do Jeito Certo 69 | 70 | {% endhighlight %} 71 | 72 | ## Botão Quadrado (125x125) 73 | 74 |

    PHP: Do Jeito Certo

    75 | 76 | {% highlight html %} 77 | 78 | PHP: Do Jeito Certo 79 | 80 | {% endhighlight %} 81 | 82 | ## Retângulo Vertical (240x400) 83 | 84 |

    PHP: Do Jeito Certo

    85 | 86 | {% highlight html %} 87 | 88 | PHP: Do Jeito Certo 89 | 90 | {% endhighlight %} -------------------------------------------------------------------------------- /images/banners/btn1-120x90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/btn1-120x90.png -------------------------------------------------------------------------------- /images/banners/btn2-120x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/btn2-120x60.png -------------------------------------------------------------------------------- /images/banners/leaderboard-728x90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/leaderboard-728x90.png -------------------------------------------------------------------------------- /images/banners/lg-rect-386x280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/lg-rect-386x280.png -------------------------------------------------------------------------------- /images/banners/med-rect-300x250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/med-rect-300x250.png -------------------------------------------------------------------------------- /images/banners/rect-180x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/rect-180x150.png -------------------------------------------------------------------------------- /images/banners/sq-btn-125x125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/sq-btn-125x125.png -------------------------------------------------------------------------------- /images/banners/vert-rect-240x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/banners/vert-rect-240x400.png -------------------------------------------------------------------------------- /images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/favicon.png -------------------------------------------------------------------------------- /images/nmc-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/nmc-logo.gif -------------------------------------------------------------------------------- /images/og-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHPSP/php-the-right-way/5ff7301101b09378f4020dfe3fbf538b41a9dde4/images/og-logo.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | description: "Uma referência rápida de melhores práticas de PHP, renomados padrões de código e links para tutoriais competentes pela Web" 4 | --- 5 | 6 | {% capture welcome_content %}{% include welcome.md %}{% endcapture %} 7 | {{ welcome_content|markdownify }} 8 | 9 | {% capture backtotop %}[Voltar ao topo](#top){:.top}{% endcapture %} 10 | {% for post in site.posts reversed %} 11 | {% if post.isChild != true and loop.first != true %} 12 | {{ backtotop|markdownify }} 13 | {% endif %} 14 |
    15 | {{ post.content }} 16 |
    17 | {% endfor %} 18 | {{ backtotop|markdownify }} 19 | -------------------------------------------------------------------------------- /notas_de_traducao.md: -------------------------------------------------------------------------------- 1 | # Notas de tradução 2 | 3 | ## Traduzir ou não traduzir? 4 | 5 | Este é projeto de caráter didático, portanto, vale a pena traduzir tudo o que for considerado importante. 6 | 7 | ### Exemplos de conteúdos a serem traduzidos: 8 | * Comentários explicativos 9 | * Conteúdo de strings heredocs ou nowdocs quando julgar necessário 10 | * Outros conteúdos que influenciem no entendimento do tópico. 11 | 12 | **Nunca altere o sentido dos textos ou adicione informações que não existam no [repositório oficial](https://github.com/codeguy/php-the-right-way) (exceto notas do tradutor)** 13 | -------------------------------------------------------------------------------- /pages/Functional-Programming.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Programação Funcional em PHP 4 | --- 5 | 6 | # Programação Funcional em PHP 7 | 8 | O PHP suporta funções de primeira classe, o que significa que uma função pode ser atribuída a uma variável. Ambas 9 | definidas pelo usuário e as funções embutidas podem ser referenciadas como uma variável e invocadas dinamicamente. 10 | As Funções podem ser passadas como argumentos para outras funções (um recurso chamado de funções de ordem-superior) 11 | e uma função pode retornar outras funções. 12 | 13 | Recursão, um recurso que permite uma função chamar ela mesma, é suportado pela linguagem, mas a maior parte do código 14 | PHP é focado em iteração. 15 | 16 | Funções Anônimas (com suporte para closures) estão presentes desde a versão 5.3 do PHP (2009). 17 | 18 | No PHP 5.4 foi adicionada a capacidade de atribuir closures no escopo de um objetos e também melhorou o suporte 19 | para funções chamáveis de tal forma podem ser usadas como sinônimo de funções anônimas em quase todos os casos. 20 | 21 | O uso mais comum de funções de ordem superior ocorre na implementação do padrão Estratégia (Strategy). A função embutida 22 | `array_filter` pede a entrada de array (data) e uma função (uma estratégia ou um callback) usada como um filtro para 23 | cada item do array. 24 | 25 | {% highlight php %} 26 | $min 56 | * 57 | * Retorna um único filtro fora da família de filtros "maior que n" 58 | */ 59 | function criteria_greater_than($min) 60 | { 61 | return function($item) use ($min) { 62 | return $item > $min; 63 | }; 64 | } 65 | 66 | $input = array(1, 2, 3, 4, 5, 6); 67 | 68 | // Utiliza array_filter em uma entrada com uma função de filtro selecionada 69 | $output = array_filter($input, criteria_greater_than(3)); 70 | 71 | print_r($output); // itens > 3 72 | {% endhighlight %} 73 | 74 | Cada função de filtro na família aceita apenas elementos maiores que algum valor mínimo. Único filtro retornado pela 75 | `criteria_greater_than` é um closure com o argumento `$min` pelo valor no escopo (dado como um argumento quando 76 | `criteria_greater_than` é chamada). 77 | 78 | A vinculação antecipada é usada por padrão para a importação da variável `$min`dentro da função criada. Para 79 | verdadeiras closures com uma vinculação posterior deve ser usada uma referência quando importar. Imagine um template ou 80 | uma biblioteca de validação, onde o closure é definido para capturar variáveis no escopo e acessá-los mais tarde quando 81 | a função anônima for compilada. 82 | 83 | * [Leia sobre Funções Anônimas][anonymous-functions] 84 | * [Mais detalhes em Closures RFC][closures-rfc] 85 | * [Leia sobre invocar dinamicamente funções com `call_user_func_array`][call-user-func-array] 86 | 87 | [anonymous-functions]: http://php.net/functions.anonymous 88 | [call-user-func-array]: http://php.net/function.call-user-func-array 89 | [closures-rfc]: https://wiki.php.net/rfc/closures -------------------------------------------------------------------------------- /pages/example.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Example Stand-Alone Page 4 | --- 5 | 6 | # Page Title 7 | 8 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 9 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 10 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 11 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 12 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 13 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 14 | 15 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 16 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 17 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 18 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 19 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 20 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 21 | 22 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 23 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 24 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 25 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 26 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 27 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 28 | -------------------------------------------------------------------------------- /scripts/setup.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | // Load contributors 3 | var $contributors = $('#contributors'); 4 | var repo_user = 'PHPSP'; 5 | if ( $contributors.length ) { 6 | var fail = function () { 7 | $contributors.html('

    Este projeto não seria possível sem a ajuda de nossos contribuintes no GitHub.

    '); 8 | }; 9 | $.ajax({ 10 | cache: false, 11 | dataType: 'jsonp', 12 | timeout: 3000, 13 | type: 'GET', 14 | url: 'https://api.github.com/repos/' + repo_user + '/php-the-right-way/contributors' 15 | }).done(function (data) { 16 | if ( data.data && data.data.length ) { 17 | var $ul = $('
      '), dataLength = data.data.length; 18 | for ( var i = 0; i < dataLength; i++ ) { 19 | $ul.append(['
    • ', data.data[i].login, '
    • '].join('')); 20 | } 21 | $contributors.html($ul); 22 | } else { 23 | fail(); 24 | } 25 | }).fail(fail); 26 | } 27 | })(jQuery); 28 | 29 | (function ($) { 30 | //Add current view's highlighting to the navigation 31 | 32 | /** helper for highlighting */ 33 | function highlightNav(navLinks,id) 34 | { 35 | navLinks.filter('[href="/#'+id+'"]').addClass("active"); 36 | } 37 | 38 | $(window).scroll(function() { 39 | //console.log("They see me scrollin, they hatin"); 40 | 41 | //clear highlighting 42 | var navLinks = $('.site-navigation a'); 43 | navLinks.removeClass("active"); 44 | 45 | //calc current viewport 46 | var viewTop = $(window).scrollTop(); 47 | var viewBottom = viewTop + $(window).height(); 48 | 49 | //for all h1 and h2 elements, check if they are visible 50 | //performance tweak: stop each() after the first element is found to be behind view 51 | var previous = ""; 52 | var foundOne = false; 53 | var fallback = ""; 54 | $('h1, h2').each(function(i,e) { 55 | //get element position; 56 | var eTop = $(e).offset().top; 57 | var eBottom = eTop + $(e).height(); 58 | var id=e.id; 59 | id = id.replace("_title", ""); 60 | 61 | if (eTop >= viewTop) { 62 | //if we are passed the view and no heading was highlighted yet, store previous one as fallback 63 | if (! foundOne) { 64 | fallback=previous; 65 | } 66 | if (eBottom <= viewBottom) { 67 | highlightNav(navLinks, id); 68 | foundOne = true; 69 | } else { 70 | return false; //break the each(), the rest is below 71 | } 72 | } 73 | previous=id; 74 | }); 75 | //no h1/h2 is in the viewport, so highlight the last one above 76 | if (! foundOne) { 77 | highlightNav(navLinks, fallback); 78 | } 79 | }); 80 | })(jQuery); -------------------------------------------------------------------------------- /sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | http://br.phptherightway.com/index.html 5 | 2012-07-07T01:00:00-05:00 6 | daily 7 | 1 8 | 9 | 10 | http://br.phptherightway.com/banners.html 11 | 2012-07-08T14:11:00-05:00 12 | weekly 13 | 0.5 14 | 15 | 16 | -------------------------------------------------------------------------------- /styles/all.less: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | NMC Bootstrap 3 | 4 | This LESS file imports all other LESS files. You should compile 5 | and minify this file before site launch. 6 | ========================================================================== */ 7 | 8 | /* Import NMC bootstrap */ 9 | 10 | @import "base/all"; 11 | 12 | /* Import site-specific styles */ 13 | 14 | @import "site/site-header.less"; 15 | @import "site/site-navigation.less"; 16 | @import "site/site-content.less"; 17 | @import "site/site-footer.less"; 18 | 19 | /* Tablets and Smartphones */ 20 | 21 | @media only screen and (max-width : 1024px) { 22 | .build-date{ 23 | text-align: center; 24 | } 25 | .site-header{ 26 | height: 220px; 27 | position: absolute; 28 | top: 20px; 29 | left: 0; 30 | width: 100%; 31 | } 32 | .fork-me img{ 33 | height: 110px; 34 | width: 110px; 35 | } 36 | .site-navigation{ 37 | margin-top: 240px; 38 | padding: 20px; 39 | position: relative; 40 | width: auto; 41 | 42 | ul{ 43 | border: 1px solid #999; 44 | border-bottom: none; 45 | } 46 | li{ 47 | .man; 48 | .pan; 49 | } 50 | a{ 51 | background: #CCC; 52 | display: block; 53 | border-bottom: 1px solid #999; 54 | padding: 10px; 55 | text-decoration: none; 56 | } 57 | ul ul{ 58 | border: none; 59 | .man; 60 | .pan; 61 | } 62 | ul ul a{ 63 | background: transparent; 64 | } 65 | } 66 | .site-content{ 67 | padding: 20px; 68 | } 69 | .top{ 70 | display: inline-block; 71 | float: none; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /styles/base/all.less: -------------------------------------------------------------------------------- 1 | @import "reset"; 2 | @import "prefixer"; 3 | @import "spacing"; 4 | @import "typography"; 5 | @import "idioms"; 6 | @import "grid"; 7 | @import "bars-buttons"; 8 | @import "buttons"; -------------------------------------------------------------------------------- /styles/base/bars-buttons.less: -------------------------------------------------------------------------------- 1 | .button() { 2 | .border-box; 3 | cursor: pointer; 4 | display: inline-block; 5 | .phh; 6 | text-align: center; 7 | font-weight: bold; 8 | } 9 | .button-hover(){ 10 | text-decoration: none; 11 | } 12 | .bar() { 13 | display: block; 14 | .pah; 15 | text-align: center; 16 | font-weight: bold; 17 | } 18 | 19 | /* Sizes */ 20 | 21 | .btn-size(@scale){ 22 | height: @baseline * @scale !important; 23 | padding-bottom: 0 !important; 24 | padding-top: 0 !important; 25 | line-height: @baseline * (@scale * 0.9); 26 | } 27 | .btn-half{ 28 | .btn-size(1); 29 | font-size: 0.8em; 30 | } 31 | .btn-single{ 32 | .btn-size(1.5); 33 | font-size: 1em; 34 | } 35 | .btn-double{ 36 | .btn-size(2); 37 | font-size: 1.1em; 38 | } 39 | 40 | /* Shapes */ 41 | 42 | .bb-shape-square() { 43 | .border-radius(0); 44 | } 45 | .bb-shape-rounded(@rad:3px) { 46 | .border-radius(@rad); 47 | } 48 | .bb-shape-round() { 49 | .border-radius(@baseline); 50 | } 51 | 52 | /* Text */ 53 | 54 | .bb-text-dark(){ 55 | color: #333; 56 | text-shadow: 0 1px 0 #fff; 57 | } 58 | .bb-text-light(){ 59 | color: #fff; 60 | text-shadow: 0 -1px 0 rgba(0,0,0,.3); 61 | } 62 | .bb-text-color(@color){ 63 | 64 | } 65 | 66 | /* Color */ 67 | 68 | .bb-color-plain(@color){ 69 | background: @color; 70 | } 71 | .bb-color-gradient(@color){ 72 | .gradient(@color,lighten(@color,10%),darken(@color,10%)); 73 | } 74 | .bb-color-soft(@color){ 75 | .gradient(@color,lighten(@color,5%),darken(@color,5%)); 76 | } 77 | .bb-color-gloss(@color){ 78 | @topStart: desaturate(lighten(@color,40%),20%); 79 | @topStop: desaturate(lighten(@color,20%),40%); 80 | @bottomStart: desaturate(lighten(@color,10%),30%); 81 | @bottomStop: desaturate(lighten(@color,15%),30%); 82 | .linear-gradient-top(@color,@topStart,0%,@topStop,50%,@bottomStart,50%,@bottomStop,100%); 83 | } 84 | 85 | /* Border */ 86 | 87 | .bb-border-noborder(){ 88 | border: none; 89 | } 90 | .bb-border-plain(@color){ 91 | border: 1px solid darken(@color,10%); 92 | } 93 | .bb-border-contrast(@color){ 94 | border: 1px solid darken(@color,15%); 95 | .box-shadow(inset 0 0 1px 1px lighten(@color,15%)); 96 | } 97 | .bb-border-meta(@color){ 98 | border: 1px solid darken(@color,15%); 99 | .box-shadow(inset 0 2px 1px -1px lighten(@color,20%)); 100 | } 101 | 102 | /* Minimal */ 103 | 104 | .button-minimal(@color) { 105 | .button(); 106 | .bb-shape-rounded(); 107 | .bb-color-plain(@color); 108 | .bb-border-contrast(@color); 109 | .bb-text-dark(); 110 | } 111 | .button-minimal-hover(@color){ 112 | .button-minimal(darken(@color,5%)); 113 | .button-hover(); 114 | } 115 | .button-minimal-active(@color){ 116 | .button-minimal-hover(darken(@color,5%)); 117 | } 118 | .bar-minimal(@color) { 119 | .button-minimal(@color); 120 | .bar(); 121 | } 122 | 123 | /* Clean */ 124 | 125 | .button-clean(@color) { 126 | .button(); 127 | .bb-shape-rounded(); 128 | .bb-color-gradient(@color); 129 | .bb-border-plain(darken(@color,5%)); 130 | .bb-text-dark(); 131 | } 132 | .button-clean-hover(@color){ 133 | .button-clean(darken(@color,5%)); 134 | .button-hover(); 135 | } 136 | .button-clean-active(@color){ 137 | .button-clean-hover(darken(@color,5%)); 138 | } 139 | .bar-clean(@color){ 140 | .button-clean(@color); 141 | .bar(); 142 | } 143 | 144 | /* Soft */ 145 | 146 | .button-soft(@color) { 147 | .button(); 148 | .bb-shape-rounded(); 149 | .bb-color-soft(@color); 150 | .bb-border-meta(darken(@color,5%)); 151 | .bb-text-light(); 152 | } 153 | .button-soft-hover(@color){ 154 | .button-soft(darken(@color,5%)); 155 | .button-hover(); 156 | } 157 | .button-soft-active(@color){ 158 | .button-soft-hover(darken(@color,5%)); 159 | } 160 | .bar-soft(@color){ 161 | .button-soft(@color); 162 | .bar(); 163 | } 164 | 165 | /* Pill */ 166 | 167 | .button-pill(@color) { 168 | .button(); 169 | .bb-shape-round(); 170 | .bb-color-soft(@color); 171 | .bb-border-meta(darken(@color,5%)); 172 | .bb-text-light(); 173 | } 174 | .button-pill-hover(@color){ 175 | .button-pill(darken(@color,5%)); 176 | .button-hover(); 177 | } 178 | .button-pill-active(@color){ 179 | .button-pill-hover(darken(@color,5%)); 180 | } 181 | .bar-pill(@color){ 182 | .button-pill(@color); 183 | .bar(); 184 | } 185 | 186 | /* Gloss */ 187 | 188 | .button-gloss(@color) { 189 | .button(); 190 | .bb-shape-rounded(5px); 191 | .bb-color-gloss(@color); 192 | .bb-border-plain(darken(@color,5%)); 193 | .box-shadow(inset 0 1px 0 0 rgba(255,255,255,.5)); 194 | .bb-text-light(); 195 | } 196 | .button-gloss-hover(@color){ 197 | .button-gloss(darken(@color,5%)); 198 | .box-shadow(inset 0 1px 0 0 rgba(255,255,255,.3)); 199 | .button-hover(); 200 | } 201 | .button-gloss-active(@color){ 202 | .button-gloss-hover(darken(@color,5%)); 203 | .box-shadow(inset 0 0 5px 0 rgba(0,0,0,.3)); 204 | } 205 | .bar-gloss(@color){ 206 | .button-gloss(@color); 207 | .bar(); 208 | } 209 | 210 | @btn-minimal-color: #eee; 211 | .btn-minimal { .button-minimal(@btn-minimal-color); } 212 | .btn-minimal:hover { .button-minimal-hover(@btn-minimal-color); } 213 | .btn-minimal:active { .button-minimal-active(@btn-minimal-color); } 214 | 215 | @btn-clean-color: #eee; 216 | .btn-clean { .button-clean(@btn-clean-color); } 217 | .btn-clean:hover { .button-clean-hover(@btn-clean-color); } 218 | .btn-clean:active { .button-clean-active(@btn-clean-color); } 219 | 220 | @btn-soft-color: #6C84AB; 221 | .btn-soft { .button-soft(@btn-soft-color); } 222 | .btn-soft:hover { .button-soft-hover(@btn-soft-color); } 223 | .btn-soft:active { .button-soft-active(@btn-soft-color); } 224 | 225 | @btn-pill-color: #6C84AB; 226 | .btn-pill { .button-pill(@btn-pill-color); } 227 | .btn-pill:hover { .button-pill-hover(@btn-pill-color); } 228 | .btn-pill:active { .button-pill-active(@btn-pill-color); } 229 | 230 | @btn-gloss-color: #172D6E; 231 | .btn-gloss { .button-gloss(@btn-gloss-color); } 232 | .btn-gloss:hover { .button-gloss-hover(@btn-gloss-color); } 233 | .btn-gloss:active { .button-gloss-active(@btn-gloss-color); } 234 | 235 | 236 | .bar-minimal { .bar-minimal(@btn-minimal-color); } 237 | .bar-clean { .bar-clean(@btn-clean-color); } 238 | .bar-soft { .bar-soft(@btn-soft-color); } 239 | .bar-pill { .bar-pill(@btn-pill-color); } 240 | .bar-gloss { .bar-gloss(@btn-gloss-color); } -------------------------------------------------------------------------------- /styles/base/buttons.less: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Settings 3 | ========================================================================== */ 4 | 5 | @import 'variables.less'; 6 | 7 | /* 8 | @baseline: @baseline; 9 | @button-color: @button-color; 10 | @button-primary-color: @button-primary-color; 11 | @button-info-color: @button-info-color; 12 | @button-success-color: @button-success-color; 13 | @button-warning-color: @button-warning-color; 14 | @button-danger-color: @button-danger-color; 15 | */ 16 | 17 | /* ========================================================================== 18 | Default 19 | ========================================================================== */ 20 | 21 | .btn{ 22 | .btn-s; 23 | background-clip: border-box !important; 24 | background-repeat: repeat-x; 25 | border: 1px solid rgba(0, 0, 0, 0.25); 26 | .border-box; 27 | .border-radius(4px); 28 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 29 | cursor: pointer; 30 | display: inline-block; 31 | .gradient(@button-color, lighten(@button-color, 10%), @button-color); 32 | .phh; 33 | .pvn; 34 | .transition(background-position linear 0.1s); 35 | vertical-align: middle; 36 | color: #333; 37 | font-family: @body-font-family; 38 | text-decoration: none !important; 39 | text-shadow: rgba(255,255,255,0.75) 0 1px 0; 40 | 41 | &:hover{ 42 | background-position: 0 -15px; 43 | } 44 | } 45 | 46 | /* ========================================================================== 47 | Styles 48 | ========================================================================== */ 49 | 50 | .btn-primary, 51 | .btn-info, 52 | .btn-success, 53 | .btn-warning, 54 | .btn-danger{ 55 | color: #FFF !important; 56 | text-shadow: rgba(0,0,0,0.25) 0 -1px 0 !important; 57 | } 58 | .btn-primary{ 59 | .btn; 60 | .gradient(@button-primary-color, lighten(@button-primary-color, 10%), @button-primary-color); 61 | } 62 | .btn-info{ 63 | .btn; 64 | .gradient(@button-info-color, lighten(@button-info-color, 10%), @button-info-color); 65 | } 66 | .btn-success{ 67 | .btn; 68 | .gradient(@button-success-color, lighten(@button-success-color, 10%), @button-success-color); 69 | } 70 | .btn-warning{ 71 | .btn; 72 | .gradient(@button-warning-color, lighten(@button-warning-color, 10%), @button-warning-color); 73 | } 74 | .btn-danger{ 75 | .btn; 76 | .gradient(@button-danger-color, lighten(@button-danger-color, 10%), @button-danger-color); 77 | } 78 | 79 | /* ========================================================================== 80 | Sizes (Half = h, Single = s, Double = d) 81 | ========================================================================== */ 82 | 83 | .btn-h, .btn-half{ 84 | height: @baseline; 85 | font-size: @baseline * 0.6; 86 | line-height: @baseline; 87 | } 88 | .btn-s, .btn-single{ 89 | height: @baseline * 1.5; 90 | font-size: @baseline * 0.75; 91 | line-height: @baseline * 1.5; 92 | } 93 | .btn-d, .btn-double{ 94 | height: @baseline * 2; 95 | font-size: @baseline; 96 | line-height: @baseline * 2; 97 | } -------------------------------------------------------------------------------- /styles/base/grid.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Hybrid Grid Sytem 3 | * 4 | * Blend of the Semantic Grid System and Zurb Foundation with a little Twitter Bootstrap 5 | */ 6 | 7 | /* Settings */ 8 | 9 | @import 'variables.less'; 10 | 11 | /* 12 | @fixed-column-width: 40px; 13 | @fixed-gutter-width: 20px; 14 | @fixed-columns: 12; 15 | 16 | @fluid-column-width: 4.3%; 17 | @fluid-gutter-width: 4.4%; 18 | @fluid-columns: 12; 19 | 20 | @mobile-break-width: 480px; 21 | @mobile-column-width: 8.6%; 22 | @mobile-gutter-width: 8.8%; 23 | @mobile-columns: 6; 24 | */ 25 | 26 | /* Grid */ 27 | 28 | #grid { 29 | 30 | .cols(@cols,@width,@gutter){ 31 | .border-box(); 32 | width: ((@cols * @width) + ((@cols - 1) * @gutter)); 33 | margin-left: @gutter; 34 | position: relative; 35 | display: inline; 36 | float: left; 37 | min-height: 1px; 38 | &:first-child { 39 | margin-left: 0; 40 | } 41 | &:last-child { 42 | float: right; 43 | } 44 | } 45 | 46 | } 47 | 48 | .grid-fixed,.grid-fluid { 49 | .clearfix; 50 | .row { 51 | .border-box(); 52 | display: block; 53 | width: 100%; 54 | margin: 0 auto; 55 | .clearfix; 56 | 57 | .center,.center:last-child { 58 | float: none; 59 | display: block; 60 | margin: 0 auto; 61 | } 62 | } 63 | } 64 | 65 | .grid-fixed { 66 | @total-width: (@fixed-column-width*@fixed-columns) + (@fixed-gutter-width*(@fixed-columns - 1)); 67 | @column-width: @fixed-column-width; 68 | @gutter-width: @fixed-gutter-width; 69 | @columns: @fixed-columns; 70 | width: @total-width; 71 | 72 | /* This is duplicated in both classes. Unavoidable. */ 73 | .colX (@index) when (@index > 0) { 74 | (~".col@{index}") { 75 | #grid > .cols(@index,@column-width,@gutter-width); 76 | } 77 | .colX(@index - 1); 78 | } 79 | .colX (0) {} 80 | .colX(@columns); 81 | 82 | .offsetX (@index) when (@index > 0) { 83 | (~".offset@{index}") { 84 | margin-left: (@index * @column-width) + ((@index + 1) * @gutter-width); 85 | } 86 | .offsetX(@index - 1); 87 | } 88 | .offsetX (0) {} 89 | .offsetX(@columns - 1); 90 | 91 | .pushX (@index) when (@index > 0) { 92 | (~".push@{index}") { 93 | left: @index * (@column-width + @gutter-width); 94 | } 95 | .pushX(@index - 1); 96 | } 97 | .pushX (0) {} 98 | .pushX(@columns - 1); 99 | 100 | .pullX (@index) when (@index > 0) { 101 | (~".pull@{index}") { 102 | right: @index * (@column-width + @gutter-width); 103 | } 104 | .pullX(@index - 1); 105 | } 106 | .pullX (0) {} 107 | .pullX(@columns - 1); 108 | } 109 | 110 | 111 | .grid-fluid { 112 | @total-width: 100%; 113 | @column-width: @fluid-column-width; 114 | @gutter-width: @fluid-gutter-width; 115 | @columns: @fluid-columns; 116 | width: @total-width; 117 | 118 | /* This is duplicated in both classes. Unavoidable. */ 119 | .colX (@index) when (@index > 0) { 120 | (~".col@{index}") { 121 | #grid > .cols(@index,@column-width,@gutter-width); 122 | } 123 | .colX(@index - 1); 124 | } 125 | .colX (0) {} 126 | .colX(@columns); 127 | 128 | .offsetX (@index) when (@index > 0) { 129 | (~".offset@{index}") { 130 | margin-left: (@index * @column-width) + ((@index + 1) * @gutter-width); 131 | } 132 | .offsetX(@index - 1); 133 | } 134 | .offsetX (0) {} 135 | .offsetX(@columns - 1); 136 | 137 | .pushX (@index) when (@index > 0) { 138 | (~".push@{index}") { 139 | left: @index * (@column-width + @gutter-width); 140 | } 141 | .pushX(@index - 1); 142 | } 143 | .pushX (0) {} 144 | .pushX(@columns - 1); 145 | 146 | .pullX (@index) when (@index > 0) { 147 | (~".pull@{index}") { 148 | right: @index * (@column-width + @gutter-width); 149 | } 150 | .pullX(@index - 1); 151 | } 152 | .pullX (0) {} 153 | .pullX(@columns - 1); 154 | } 155 | 156 | 157 | @media all and (max-width: @mobile-break-width) { 158 | 159 | // Reset all columns to full width 160 | .grid-fixed { 161 | .colX (@index) when (@index > 0) { 162 | (~".col@{index}") { 163 | width: 100%; 164 | margin: 0; 165 | left: 0; 166 | right: 0; 167 | } 168 | .colX(@index - 1); 169 | } 170 | .colX (0) {} 171 | .colX(@fixed-columns); 172 | } 173 | .grid-fluid { 174 | .colX (@index) when (@index > 0) { 175 | (~".col@{index}") { 176 | width: 100%; 177 | margin: 0; 178 | left: 0; 179 | right: 0; 180 | } 181 | .colX(@index - 1); 182 | } 183 | .colX (0) {} 184 | .colX(@fluid-columns); 185 | } 186 | 187 | .grid-fixed, .grid-fluid { 188 | @total-width: 100%; 189 | @column-width: @mobile-column-width; 190 | @gutter-width: @mobile-gutter-width; 191 | @columns: @mobile-columns; 192 | width: @total-width; 193 | 194 | .m-colX (@index) when (@index > 0) { 195 | (~".m-col@{index}") { 196 | #grid > .cols(@index,@column-width,@gutter-width); 197 | } 198 | .m-colX(@index - 1); 199 | } 200 | .m-colX (0) {} 201 | .m-colX(@mobile-columns); 202 | 203 | .m-offsetX (@index) when (@index > 0) { 204 | (~".m-offset@{index}") { 205 | margin-left: (@index * @column-width) + ((@index + 1) * @gutter-width); 206 | } 207 | .m-offsetX(@index - 1); 208 | } 209 | .m-offsetX (0) {} 210 | .m-offsetX(@columns - 1); 211 | 212 | .m-pushX (@index) when (@index > 0) { 213 | (~".m-push@{index}") { 214 | left: @index * (@column-width + @gutter-width); 215 | } 216 | .m-pushX(@index - 1); 217 | } 218 | .m-pushX (0) {} 219 | .m-pushX(@columns - 1); 220 | 221 | .m-pullX (@index) when (@index > 0) { 222 | (~".m-pull@{index}") { 223 | right: @index * (@column-width + @gutter-width); 224 | } 225 | .m-pullX(@index - 1); 226 | } 227 | .m-pullX (0) {} 228 | .m-pullX(@columns - 1); 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /styles/base/idioms.less: -------------------------------------------------------------------------------- 1 | /** 2 | * New Media Campaigns Idioms 3 | * 4 | * These are common patterns we use in all of our 5 | * projects. They are consolidated here to keep code DRY. 6 | * 7 | * Listing 8 | * * .no-text, .text-replace 9 | * * .no-list 10 | * * .no-form 11 | * * .fixed-width(@width) 12 | * * .column-width(@width) 13 | * * .column-left(@width) 14 | * * .column-right(@width) 15 | * * .full-size 16 | * * .absolute-default 17 | * * .absolute-fullsize 18 | * * .clearfix 19 | */ 20 | 21 | /* Hides text when using image replacement */ 22 | .no-text, .text-replace{ 23 | overflow: hidden; 24 | text-indent: 100%; 25 | white-space: nowrap; 26 | } 27 | 28 | /* Removes bullets, margin, and padding from list */ 29 | .no-list{ 30 | list-style: none; 31 | margin: 0; 32 | padding: 0; 33 | } 34 | 35 | /* Removes webkit styling from form element */ 36 | .no-form{ 37 | border: none; 38 | margin: 0; 39 | padding: 0; 40 | -webkit-appearance: none; 41 | } 42 | 43 | /* Center a fixed width container */ 44 | .fixed-width(@width) { 45 | margin: 0 auto; 46 | width: @width; 47 | } 48 | 49 | /* Adds left or right columns (e.g. content and sidebar) */ 50 | .column-width(@width){ 51 | display: inline; 52 | width: @width; 53 | } 54 | .column-left(@width){ 55 | .column-width(@width); 56 | float: left; 57 | } 58 | .column-right(@width){ 59 | .column-width(@width); 60 | float: right; 61 | } 62 | 63 | /* Set width and height of element to that of its parent */ 64 | .full-size{ 65 | height: 100%; 66 | width: 100%; 67 | } 68 | 69 | /* Position element absolutely to 0,0 */ 70 | .absolute-default{ 71 | position: absolute; 72 | left: 0; 73 | top: 0; 74 | } 75 | 76 | /* Position element absolutely and set its width and height to that of its parent (useful for slideshows) */ 77 | .absolute-fullsize{ 78 | .absolute-default; 79 | .full-size; 80 | } 81 | 82 | /* The micro clearfix http://nicolasgallagher.com/micro-clearfix-hack/ */ 83 | .clearfix { 84 | *zoom:1; 85 | 86 | &:before, 87 | &:after { 88 | content:""; 89 | display:table; 90 | } 91 | &:after { 92 | clear:both; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /styles/base/reset.less: -------------------------------------------------------------------------------- 1 | /** 2 | * html5doctor.com Reset Stylesheet 3 | * v1.6.1 4 | * Last Updated: 2010-09-17 5 | * Author: Richard Clark - http://richclarkdesign.com 6 | * Twitter: @rich_clark 7 | */ 8 | 9 | html, body, div, span, object, iframe, 10 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 11 | abbr, address, cite, code, 12 | del, dfn, em, img, ins, kbd, q, samp, 13 | small, strong, sub, sup, var, 14 | b, i, 15 | dl, dt, dd, ol, ul, li, 16 | fieldset, form, label, legend, 17 | table, caption, tbody, tfoot, thead, tr, th, td, 18 | article, aside, canvas, details, figcaption, figure, 19 | footer, header, hgroup, menu, nav, section, summary, 20 | time, mark, audio, video { 21 | margin:0; 22 | padding:0; 23 | border:0; 24 | outline:0; 25 | font-size:100%; 26 | vertical-align:baseline; 27 | background:transparent; 28 | } 29 | 30 | body { 31 | line-height:1; 32 | } 33 | 34 | article,aside,details,figcaption,figure, 35 | footer,header,hgroup,menu,nav,section { 36 | display:block; 37 | } 38 | 39 | nav ul { 40 | list-style:none; 41 | } 42 | 43 | blockquote, q { 44 | quotes:none; 45 | } 46 | 47 | blockquote:before, blockquote:after, 48 | q:before, q:after { 49 | content:''; 50 | content:none; 51 | } 52 | 53 | a { 54 | margin:0; 55 | padding:0; 56 | font-size:100%; 57 | vertical-align:baseline; 58 | background:transparent; 59 | } 60 | 61 | /* change colours to suit your needs */ 62 | ins { 63 | background-color:#ff9; 64 | color:#000; 65 | text-decoration:none; 66 | } 67 | 68 | /* change colours to suit your needs */ 69 | mark { 70 | background-color:#ff9; 71 | color:#000; 72 | font-style:italic; 73 | font-weight:bold; 74 | } 75 | 76 | del { 77 | text-decoration: line-through; 78 | } 79 | 80 | abbr[title], dfn[title] { 81 | border-bottom:1px dotted; 82 | cursor:help; 83 | } 84 | 85 | table { 86 | border-collapse:collapse; 87 | border-spacing:0; 88 | } 89 | 90 | /* change border colour to suit your needs */ 91 | hr { 92 | display:block; 93 | height:1px; 94 | border:0; 95 | border-top:1px solid #cccccc; 96 | margin:1em 0; 97 | padding:0; 98 | } 99 | 100 | input, select { 101 | vertical-align:middle; 102 | } -------------------------------------------------------------------------------- /styles/base/spacing.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Spacing 3 | * 4 | * This LESS file defines margins and paddings for block-level 5 | * elements. Helper classes are included for use elsewhere 6 | * in site styles. 7 | */ 8 | 9 | /* Settings */ 10 | 11 | @import 'variables.less'; 12 | 13 | /* 14 | @baseline: @baseline; 15 | */ 16 | 17 | /** 18 | * Spacing 19 | * p, m, lh = padding, margin, line-height 20 | * a, t, r, b, l, h, v = all, top, right, bottom, left, horizontal, vertical 21 | * n, h, s, d = none(0px), half(@baseline / 2), single(@baseline), double(@baseline * 2), none(0px) 22 | */ 23 | 24 | .ptn, .pvn, .pan{ 25 | padding-top: 0px !important 26 | } 27 | .pth, .pvh, .pah{ 28 | padding-top: @baseline / 2 !important 29 | } 30 | .pts, .pvs, .pas{ 31 | padding-top: @baseline !important 32 | } 33 | .ptd, .pvd, .pad{ 34 | padding-top: @baseline * 2 !important 35 | } 36 | .prn, .phn, .pan{ 37 | padding-right: 0px !important 38 | } 39 | .prh, .phh, .pah{ 40 | padding-right: @baseline / 2 !important 41 | } 42 | .prs, .phs, .pas{ 43 | padding-right: @baseline !important 44 | } 45 | .prd, .phd, .pad{ 46 | padding-right: @baseline * 2 !important 47 | } 48 | .pbn, .pvn, .pan{ 49 | padding-bottom: 0px !important 50 | } 51 | .pbh, .pvh, .pah{ 52 | padding-bottom: @baseline / 2 !important 53 | } 54 | .pbs, .pvs, .pas{ 55 | padding-bottom: @baseline !important 56 | } 57 | .pbd, .pvd, .pad{ 58 | padding-bottom: @baseline * 2 !important 59 | } 60 | .pln, .phn, .pan{ 61 | padding-left: 0px !important 62 | } 63 | .plh, .phh, .pah{ 64 | padding-left: @baseline / 2 !important 65 | } 66 | .pls, .phs, .pas{ 67 | padding-left: @baseline !important 68 | } 69 | .pld, .phd, .pad{ 70 | padding-left: @baseline * 2 !important 71 | } 72 | .mtn, .mvn, .man{ 73 | margin-top: 0px !important 74 | } 75 | .mth, .mvh, .mah{ 76 | margin-top: @baseline / 2 !important 77 | } 78 | .mts, .mvs, .mas{ 79 | margin-top: @baseline !important 80 | } 81 | .mtd, .mvd, .mad{ 82 | margin-top: @baseline * 2 !important 83 | } 84 | .mrn, .mhn, .man{ 85 | margin-right: 0px !important 86 | } 87 | .mrh, .mhh, .mah{ 88 | margin-right: @baseline / 2 !important 89 | } 90 | .mrs, .mhs, .mas{ 91 | margin-right: @baseline !important 92 | } 93 | .mrd, .mhd, .mad{ 94 | margin-right: @baseline * 2 !important 95 | } 96 | .mbn, .mvn, .man{ 97 | margin-bottom: 0px !important 98 | } 99 | .mbh, .mvh, .mah{ 100 | margin-bottom: @baseline / 2 !important 101 | } 102 | .mbs, .mvs, .mas{ 103 | margin-bottom: @baseline !important 104 | } 105 | .mbd, .mvd, .mad{ 106 | margin-bottom: @baseline * 2 !important 107 | } 108 | .mln, .mhn, .man{ 109 | margin-left: 0px !important 110 | } 111 | .mlh, .mhh, .mah{ 112 | margin-left: @baseline / 2 !important 113 | } 114 | .mls, .mhs, .mas{ 115 | margin-left: @baseline !important 116 | } 117 | .mld, .mhd, .mad{ 118 | margin-left: @baseline * 2 !important 119 | } 120 | .lhh { 121 | line-height: @baseline / 2 !important; 122 | } 123 | .lhs { 124 | line-height: @baseline !important; 125 | } 126 | .lhd { 127 | line-height: @baseline * 2 !important; 128 | } 129 | .lhn { 130 | line-height: 0px !important; 131 | } -------------------------------------------------------------------------------- /styles/base/typography.less: -------------------------------------------------------------------------------- 1 | /** 2 | * Name Here 3 | * 4 | * @version 1.0 5 | * @package Name Here 6 | * @author New Media Campaigns 7 | * @copyright 2012 New Media Campaigns 8 | * @link http://www.newmediacampaigns.com 9 | * 10 | * Copyright (c) 2012 New Media Campaigns 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is furnished 17 | * to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | */ 30 | 31 | /** 32 | * Typography 33 | * 34 | * This LESS file defines the baseline, color, font-size, and other typographical 35 | * styles for text elements. 36 | */ 37 | 38 | /* Settings */ 39 | 40 | @import 'variables.less'; 41 | 42 | /* 43 | @baseline: @baseline; 44 | 45 | @body-color: @body-color; 46 | @body-font-family: @body-font-family; 47 | @body-font-size: @body-font-size; 48 | @body-accent-color: @body-accent-color; 49 | 50 | @header-color: @header-clor; 51 | @header-font-family: @header-font-family; 52 | @header-font-weight: @header-font-weight; 53 | */ 54 | 55 | /* Base */ 56 | 57 | html, body { 58 | font-family: @body-font-family; 59 | color: @body-color; 60 | font-size: @body-font-size; 61 | .lhs; 62 | } 63 | 64 | /* Block-level */ 65 | 66 | h1, h2, h3, h4, h5, h6, ul, ol, dl, p, blockquote, table, form, pre{ 67 | .mbs; 68 | } 69 | 70 | /* Headers */ 71 | 72 | .all-headers{ 73 | color: @header-color; 74 | font-family: @header-font-family; 75 | font-weight: @header-font-weight; 76 | } 77 | h1, .alpha{ 78 | .all-headers; 79 | font-size: @body-font-size * 2.5; 80 | .lhd; 81 | } 82 | h2, .beta{ 83 | .all-headers; 84 | font-size: @body-font-size * 1.75; 85 | .lhd; 86 | } 87 | h3, .gamma{ 88 | .all-headers; 89 | font-size: @body-font-size * 1.2; 90 | .lhd; 91 | .mbn; 92 | } 93 | h4, .delta{ 94 | .all-headers; 95 | font-size: @body-font-size * 1; 96 | .lhd; 97 | .mbn; 98 | } 99 | h5, .epsilon{ 100 | .all-headers; 101 | font-size: @body-font-size * 1; 102 | .lhs; 103 | .mbn 104 | } 105 | h6, .zeta{ 106 | .all-headers; 107 | font-size: @body-font-size * 1; 108 | .lhs; 109 | .mbn; 110 | } 111 | 112 | /* Headers (above scale) */ 113 | 114 | .giga{ 115 | .all-headers; 116 | font-size: @body-font-size * 6; 117 | line-height: @baseline * 4; 118 | } 119 | .mega{ 120 | .all-headers; 121 | font-size: @body-font-size * 5; 122 | line-height: @baseline * 3; 123 | } 124 | .kilo{ 125 | .all-headers; 126 | font-size: @body-font-size * 4; 127 | line-height: @baseline * 3; 128 | } 129 | 130 | /* Headers (below scale) */ 131 | 132 | .milli{ 133 | .all-headers; 134 | font-size: @body-font-size * 0.8; 135 | } 136 | 137 | /* Text */ 138 | 139 | a{ 140 | color: @body-accent-color; 141 | } 142 | a:link{ 143 | text-decoration: underline; 144 | } 145 | a:visited{ 146 | 147 | } 148 | a:hover{ 149 | text-decoration: none; 150 | } 151 | a:active{ 152 | 153 | } 154 | a:focus{ 155 | 156 | } 157 | small { 158 | font-size: 80%; 159 | } 160 | sup, sub { 161 | font-size: 80%; 162 | .lhn; 163 | } 164 | sup { 165 | vertical-align: super; 166 | } 167 | sub { 168 | vertical-align: sub; 169 | } 170 | 171 | .lead{ 172 | color: darken(@body-color, 20%); 173 | font-size: @baseline * 0.8; 174 | } 175 | 176 | blockquote{ 177 | border-left: 5px solid fade(#000, 10%); 178 | .mhs; 179 | .pls; 180 | color: lighten(@body-color, 20%); 181 | font-size: @baseline * 0.8; 182 | font-style: italic; 183 | 184 | :last-child{ 185 | .mbn; 186 | } 187 | small{ 188 | color: fade(#000, 50%); 189 | font-size: @baseline * 0.7; 190 | font-style: normal; 191 | } 192 | } 193 | pre, code, kbd{ 194 | background: #F8F8F8; 195 | border: 1px solid #EAEAEA; 196 | .border-radius(3px); 197 | margin: 0 2px; 198 | padding: 0 5px; 199 | font-family: Consolas, "Courier New", Courier, mono; 200 | font-size: @body-font-size * 0.9; 201 | color: @body-color; 202 | word-wrap: break-word; 203 | } 204 | pre{ 205 | .mhs; 206 | .pah; 207 | 208 | code{ 209 | border: none; 210 | .man; 211 | .pan; 212 | } 213 | } 214 | a code{ 215 | background: none; 216 | border: none; 217 | .pan; 218 | .man; 219 | } 220 | strong{ 221 | font-weight: bold; 222 | } 223 | em{ 224 | font-style: italic; 225 | } 226 | ol, ul, dl{ 227 | .mls; 228 | .pls; 229 | ol,ul { 230 | .mbn; 231 | } 232 | } 233 | dt{ 234 | font-weight: bold; 235 | } 236 | dd{ 237 | .mls; 238 | } 239 | 240 | .table{ 241 | border-collapse: collapse; 242 | border-spacing: 0; 243 | width: 100%; 244 | } 245 | .table th, .table td{ 246 | border-top: 1px solid fade(#000, 10%); 247 | padding: 8px; 248 | text-align: left; 249 | } 250 | .table thead th{ 251 | vertical-align: bottom; 252 | font-weight: bold; 253 | } 254 | .table thead tr:first-child th{ 255 | border-top: none; 256 | } 257 | .table-bordered{ 258 | border: 1px solid fade(#000, 10%); 259 | border-collapse: separate; 260 | border-left: none; 261 | .border-radius(4px); 262 | 263 | th, td{ 264 | border-left: 1px solid fade(#000, 10%); 265 | } 266 | thead:last-child tr:last-child th:first-child, 267 | tbody:last-child tr:last-child td:first-child{ 268 | .border-radius(0 0 0 4px); 269 | } 270 | } 271 | .table-striped{ 272 | tbody tr:nth-child(odd) td{ 273 | background: fade(@body-accent-color, 4%); 274 | } 275 | } 276 | 277 | /* ========================================================================== 278 | Alerts 279 | ========================================================================== */ 280 | 281 | .alert{ 282 | background: #FCF8E3; 283 | border: 1px solid #FBEED5; 284 | .border-radius(4px); 285 | .mbs; 286 | .pah; 287 | color: #C09853; 288 | } 289 | .alert-success{ 290 | .alert; 291 | background-color: #DFF0D8; 292 | border-color: #D6E9C6; 293 | color: #468847; 294 | } 295 | .alert-error{ 296 | .alert; 297 | background-color: #F2DEDE; 298 | border-color: #EED3D7; 299 | color: #B94A48; 300 | } 301 | .alert-info{ 302 | .alert; 303 | background-color: #D9EDF7; 304 | border-color: #BCE8F1; 305 | color: #3A87AD; 306 | } 307 | 308 | /* ========================================================================== 309 | Forms 310 | ========================================================================== */ 311 | 312 | label{ 313 | display: block; 314 | font-weight: bold; 315 | 316 | .req{ 317 | color: @body-accent-color; 318 | font-weight: bold; 319 | } 320 | } 321 | input.text, 322 | textarea, 323 | select, 324 | .radio-group, 325 | .checkbox-group{ 326 | .mbs; 327 | } 328 | input.text, textarea{ 329 | .no-form; 330 | background: #EEE; 331 | border: 1px solid #CCC; 332 | .border-box; 333 | .border-radius(4px); 334 | .inner-shadow(fade(#000, 10%) 0 1px 3px); 335 | height: @baseline * 1.5; 336 | .pah; 337 | width: 100%; 338 | } 339 | textarea{ 340 | height: @baseline * 6; 341 | } 342 | select{ 343 | min-width: 30%; 344 | } 345 | .checkbox-group label, 346 | .radio-group label{ 347 | font-weight: normal; 348 | } 349 | .error{ 350 | background-color: #F2DEDE !important; 351 | border-color: red !important; 352 | outline-color: red !important; 353 | color: red !important; 354 | } 355 | -------------------------------------------------------------------------------- /styles/base/variables.less: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Spacing 3 | ========================================================================== */ 4 | 5 | @baseline: 20px; 6 | 7 | /* ========================================================================== 8 | Typography 9 | ========================================================================== */ 10 | 11 | @body-color: #555; 12 | @body-font-family: "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, "Lucida Grande", sans-serif; 13 | @body-font-size: 14px; 14 | @body-accent-color: #f00; 15 | 16 | @header-color: #000; 17 | @header-font-family: "Helvetica Neue", "HelveticaNeue", Helvetica, Arial, "Lucida Grande", sans-serif; 18 | @header-font-weight: bold; 19 | 20 | /* ========================================================================== 21 | Grid 22 | ========================================================================== */ 23 | 24 | @fixed-column-width: 40px; 25 | @fixed-gutter-width: 20px; 26 | @fixed-columns: 12; 27 | 28 | @fluid-column-width: 4.3%; 29 | @fluid-gutter-width: 4.4%; 30 | @fluid-columns: 12; 31 | 32 | @mobile-break-width: 480px; 33 | @mobile-column-width: 20%; 34 | @mobile-gutter-width: 6.6666%; 35 | @mobile-columns: 4; 36 | 37 | /* ========================================================================== 38 | Buttons 39 | ========================================================================== */ 40 | 41 | @button-color: #DDD; 42 | @button-primary-color: #0055CC; 43 | @button-info-color: #2F96B4; 44 | @button-success-color: #51A351; 45 | @button-warning-color: #FAA732; 46 | @button-danger-color: #BD362F; 47 | 48 | /* ========================================================================== 49 | Site Variables 50 | ========================================================================== */ 51 | 52 | @import "../site/variables"; -------------------------------------------------------------------------------- /styles/print.css: -------------------------------------------------------------------------------- 1 | body, .site-title, h1, h2, h3{ 2 | font-family: 'Georgia' !important; 3 | } 4 | 5 | 6 | nav.site-navigation, a.fork-me, a.top{ 7 | display:none; 8 | } 9 | 10 | div.site-content{ 11 | padding: 20px 40px 40px 20px; 12 | } -------------------------------------------------------------------------------- /styles/site/site-content.less: -------------------------------------------------------------------------------- 1 | .site-content{ 2 | padding: 20px 40px 40px 320px; 3 | 4 | h1{ 5 | clear: both; 6 | } 7 | } 8 | .interior-site-content{ 9 | .pad; 10 | } 11 | .top{ 12 | background: #333; 13 | display: inline-block; 14 | float: right; 15 | margin-right: -40px; 16 | padding: 4px 8px; 17 | color: #FFF; 18 | font-size: 12px; 19 | text-decoration: none !important; 20 | } 21 | -------------------------------------------------------------------------------- /styles/site/site-footer.less: -------------------------------------------------------------------------------- 1 | .site-footer{ 2 | clear: both; 3 | .ptd; 4 | font-size: 13px; 5 | text-align: center; 6 | } 7 | .site-footer img{ 8 | margin-left: 2px; 9 | position: relative; 10 | top: -2px; 11 | vertical-align: middle; 12 | } 13 | .site-footer ul{ 14 | list-style: none; 15 | .mhn; 16 | .phn; 17 | } 18 | -------------------------------------------------------------------------------- /styles/site/site-header.less: -------------------------------------------------------------------------------- 1 | .site-header{ 2 | position: relative; 3 | z-index: 1; 4 | text-align: center; 5 | } 6 | .site-title{ 7 | .mbn; 8 | font-family: 'Alfa Slab One'; 9 | font-size: @baseline * 4; 10 | font-weight: normal !important; 11 | line-height: @baseline * 5 !important; 12 | 13 | a{ 14 | text-decoration: none; 15 | } 16 | } 17 | .site-slogan{ 18 | font-weight: normal; 19 | } 20 | .fork-me, .fork-me img{ 21 | position: absolute; 22 | top: 0; 23 | right: 0; 24 | } 25 | .fork-me{ 26 | z-index: 2; 27 | } 28 | 29 | .interior-site-header{ 30 | background: #EEE; 31 | .inner-shadow(fade(#000, 7%) 0 0 40px); 32 | .pas; 33 | text-align: center; 34 | 35 | .site-title{ 36 | font-size: @baseline * 2; 37 | line-height: @baseline * 2 !important; 38 | } 39 | .site-slogan{ 40 | .mbs; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /styles/site/site-navigation.less: -------------------------------------------------------------------------------- 1 | .site-navigation{ 2 | background: #EEE; 3 | .inner-shadow(fade(#000, 7%) 0 0 40px); 4 | .pas; 5 | position: fixed; 6 | top: 0; 7 | bottom: 0; 8 | overflow: auto; 9 | width: 240px; 10 | } 11 | .build-date{ 12 | .mbs; 13 | color: #AAA; 14 | font-family: Helvetica, Arial, sans-serif; 15 | font-size: 11px; 16 | } 17 | .site-navigation ul{ 18 | .man; 19 | .pan; 20 | .no-list; 21 | font-size: 16px; 22 | } 23 | .site-navigation > ul > li{ 24 | margin-bottom: 10px; 25 | } 26 | .site-navigation a{ 27 | text-decoration: underline; 28 | 29 | &:hover{ 30 | text-decoration: none; 31 | } 32 | } 33 | .site-navigation a.active{ 34 | background-color: #ff9; 35 | } 36 | .site-navigation ul ul{ 37 | .mls; 38 | .pth; 39 | font-size: 12px; 40 | 41 | a{ 42 | text-decoration: none; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /styles/site/variables.less: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Spacing 3 | ========================================================================== */ 4 | 5 | @baseline: 20px; 6 | 7 | /* ========================================================================== 8 | Typography 9 | ========================================================================== */ 10 | 11 | @body-color: #666; 12 | @body-font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; 13 | @body-font-size: 14px; 14 | @body-accent-color: #000; 15 | 16 | @header-color: #111; 17 | @header-font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; 18 | @header-font-weight: 700; 19 | 20 | /* ========================================================================== 21 | Grid 22 | ========================================================================== */ 23 | 24 | @fixed-column-width: 60px; 25 | @fixed-gutter-width: 20px; 26 | @fixed-columns: 12; 27 | 28 | @fluid-column-width: 4.3%; 29 | @fluid-gutter-width: 4.4%; 30 | @fluid-columns: 12; 31 | 32 | @mobile-break-width: 480px; 33 | @mobile-column-width: 20%; 34 | @mobile-gutter-width: 6.6666%; 35 | @mobile-columns: 4; 36 | 37 | /* ========================================================================== 38 | Buttons 39 | ========================================================================== */ 40 | 41 | @button-color: #DDD; 42 | @button-primary-color: #0055CC; 43 | @button-info-color: #2F96B4; 44 | @button-success-color: #51A351; 45 | @button-warning-color: #FAA732; 46 | @button-danger-color: #BD362F; 47 | -------------------------------------------------------------------------------- /styles/syntax.css: -------------------------------------------------------------------------------- 1 | .highlight { background: #ffffff; } 2 | .highlight .c { color: #999988; font-style: italic } /* Comment */ 3 | .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ 4 | .highlight .k { font-weight: bold } /* Keyword */ 5 | .highlight .o { font-weight: bold } /* Operator */ 6 | .highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ 10 | .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ 11 | .highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ 12 | .highlight .ge { font-style: italic } /* Generic.Emph */ 13 | .highlight .gr { color: #aa0000 } /* Generic.Error */ 14 | .highlight .gh { color: #999999 } /* Generic.Heading */ 15 | .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ 16 | .highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ 17 | .highlight .go { color: #888888 } /* Generic.Output */ 18 | .highlight .gp { color: #555555 } /* Generic.Prompt */ 19 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 20 | .highlight .gu { color: #aaaaaa } /* Generic.Subheading */ 21 | .highlight .gt { color: #aa0000 } /* Generic.Traceback */ 22 | .highlight .kc { font-weight: bold } /* Keyword.Constant */ 23 | .highlight .kd { font-weight: bold } /* Keyword.Declaration */ 24 | .highlight .kp { font-weight: bold } /* Keyword.Pseudo */ 25 | .highlight .kr { font-weight: bold } /* Keyword.Reserved */ 26 | .highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */ 27 | .highlight .m { color: #009999 } /* Literal.Number */ 28 | .highlight .s { color: #d14 } /* Literal.String */ 29 | .highlight .na { color: #008080 } /* Name.Attribute */ 30 | .highlight .nb { color: #0086B3 } /* Name.Builtin */ 31 | .highlight .nc { color: #445588; font-weight: bold } /* Name.Class */ 32 | .highlight .no { color: #008080 } /* Name.Constant */ 33 | .highlight .ni { color: #800080 } /* Name.Entity */ 34 | .highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */ 35 | .highlight .nf { color: #990000; font-weight: bold } /* Name.Function */ 36 | .highlight .nn { color: #555555 } /* Name.Namespace */ 37 | .highlight .nt { color: #000080 } /* Name.Tag */ 38 | .highlight .nv { color: #008080 } /* Name.Variable */ 39 | .highlight .ow { font-weight: bold } /* Operator.Word */ 40 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 41 | .highlight .mf { color: #009999 } /* Literal.Number.Float */ 42 | .highlight .mh { color: #009999 } /* Literal.Number.Hex */ 43 | .highlight .mi { color: #009999 } /* Literal.Number.Integer */ 44 | .highlight .mo { color: #009999 } /* Literal.Number.Oct */ 45 | .highlight .sb { color: #d14 } /* Literal.String.Backtick */ 46 | .highlight .sc { color: #d14 } /* Literal.String.Char */ 47 | .highlight .sd { color: #d14 } /* Literal.String.Doc */ 48 | .highlight .s2 { color: #d14 } /* Literal.String.Double */ 49 | .highlight .se { color: #d14 } /* Literal.String.Escape */ 50 | .highlight .sh { color: #d14 } /* Literal.String.Heredoc */ 51 | .highlight .si { color: #d14 } /* Literal.String.Interpol */ 52 | .highlight .sx { color: #d14 } /* Literal.String.Other */ 53 | .highlight .sr { color: #009926 } /* Literal.String.Regex */ 54 | .highlight .s1 { color: #d14 } /* Literal.String.Single */ 55 | .highlight .ss { color: #990073 } /* Literal.String.Symbol */ 56 | .highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */ 57 | .highlight .vc { color: #008080 } /* Name.Variable.Class */ 58 | .highlight .vg { color: #008080 } /* Name.Variable.Global */ 59 | .highlight .vi { color: #008080 } /* Name.Variable.Instance */ 60 | .highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /vagrant.md: -------------------------------------------------------------------------------- 1 | # Contribuir com o projeto utilizando o Vagrant 2 | 3 | ### Instalar o vagrant 4 | * Instale [Vagrant](http://www.vagrantup.com/) e [VirtualBox](https://www.virtualbox.org/) 5 | * Execute o comando `vagrant up` no diretório do projeto 6 | 7 | ### Gerar o build do projeto e visualizar localmente 8 | * Realize as alterações 9 | * Para criar o build: 10 | * Execute `vagrant ssh -c 'cd /vagrant && jekyll build'` 11 | * Para visualizar as alterações: 12 | * Execute `vagrant ssh -c 'cd /vagrant && jekyll serve'` 13 | * Acesse [visualize localmente](http://localhost:4000) --------------------------------------------------------------------------------