├── .env.sample ├── .gitignore ├── LICENSE ├── README.md ├── app └── index.php ├── bootstrap ├── constants.php ├── environment.php ├── error.php ├── function.php └── index.php ├── composer.json ├── docker-compose.yml.sample ├── essentials ├── Base64.php ├── Encode.php ├── File.php ├── Hash.php ├── Http.php ├── Proxy.php ├── Regex.php ├── Text.php ├── Url.php ├── Utils │ └── Instance.php └── ePHP.php └── public_html ├── .htaccess └── index.php /.env.sample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phpzm/ePHP/6b9fdb917336baf61e6e5289e1cd6cc135d1b95f/.env.sample -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.env 3 | /docker-compose.yml 4 | /vendor 5 | /composer.phar 6 | 7 | *.cache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Grupo de PHP da Zona da Mata 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Essentials PHP (ePHP) 2 | 3 | O `Essentials PHP` é um conjunto simples de funções, classes e configurações básicas para simplificar a vida do desenvolvedor. 4 | 5 | Você pode aplicar o `Essentials PHP` à qualquer projeto PHP que você tenha. Veremos mais pra frente as vantagens que você pode obter com isso. 6 | 7 | ## Motivação 8 | 9 | Existe hoje uma lacuna muito grande entre usar o PHP diretamente ou adotar algum framework. Não há entre estes dois pontos um meio termo acessível e o que eu tenho visto por ai é o uso do PHP sem o mínimo de segurança e/ou organização quando não se usa um FW (framework) - embora a simples adoção do FW também não garanta totalmente qualidade nem segurança para o projeto. o ePHP entra nesse meio, e entrega uma forma simples e de qualidade para usar o PHP sem muitas firulas e com a opção de mexer no seu fluxo de trabalho só à medida que você precisar. 10 | 11 | A ideia é eliminar do desenvolvimento com PHP acessos diretos a arquivos e o famoso `include db.inc.php`. O PHP já deixou isso para trás, mas falta ferramentas para auxiliar os dev's a seguirem adiante também. 12 | 13 | ## Por onde começar 14 | 15 | Faça download do [arquivo]( https://github.com/phpzm/essentials/archive/master.zip) que contém a estrutura do projeto. 16 | 17 | Em seguida crie uma pasta para o projeto e descompacte o arquivo que você baixou dentro dela. 18 | 19 | Agora é a vez de baixar o Composer. Vá até o [site do composer](https://getcomposer.org/download) role até o final da página e escolha uma versão compatível com a sua versão do PHP. Faça o download do arquivo para a pasta que você criou. Neste momento a versão estável mais atual é a [1.5.6](https://getcomposer.org/download/1.5.6/composer.phar) e ela é compatível com o PHP 7.1 que estou usando : ) 20 | 21 | O próximo passo é abrir uma janela de terminal nesse diretório e dar o comando `php composer.phar install` 22 | 23 | Pronto! Agora você já está pronto para rodar o projeto. 24 | 25 | #### Rodando o "Hello World!" 26 | 27 | Você pode optar por: 28 | - Usar o servidor embutido no PHP: use o comando `php -S localhost:8080 -t public_html/` para iniciar o projeto; 29 | 30 | - Usar o Nginx através do docker-compose: crie uma cópia do `docker-compose.yml.sample` removendo o `.sample` do fim do nome do arquivo. Feito isso basta rodar `docker-compose up`. 31 | 32 | - Usar o que já está acostumado: seguindo por aqui imagino que você saiba onde colocar os arquivos e como acessar eles 33 | 34 | Qualquer um dois dois primeiros caminhos vão te levar a acessar o "Hello World!" em [http://localhost:8080](http://localhost:8080), e, obviamente, você pode mudar essas configurações. Caso tenha optado por usar o que já está acostumado a URL de acesso será no formato que você está familiarizado. 35 | 36 | ## Pra que isso tudo gente?! 37 | 38 | A ideia do ePHP é entregar facilidatores para o desenvolvedor. Separamos alguns tópicos a serem tratados que o projeto visa a resolver de forma rápida e muito simples. 39 | 40 | - Acesso centralizado: Um dos objetivos mais importantes deste projeto é remover da raiz do web server a aplicação. Utilizando alguns recursos disponibilizados é possível colocar toda a aplicação "legada" a ser protegida dentro da pasta `app` e configurar como os arquivos serão acessados. Com esta modificação de segurança seu projeto já começa a ter um nível diferenciado de segurança. 41 | 42 | - Super Globais: O segundo ponto a ser tocado é abstrair o acesso às super globais entregando funções que estão disponíveis em qualquer parte do projeto. Usando esses recursos você consegue limpar as entradas do usuário de acordo com o tipo de dado informado e minimiza muito o impacto de falhas de segurança que explorem combinações de valores de entrada para "zuar" com a sua aplicação. O acesso aos dados usa os mecanismos do [filter_input](http://php.net/filter_input) garantido a higienização dos valores recebidos. Além disso também é possível dar suporte a receber dados em formato JSON (payload) através da mesma função que é usada para os dados enviados via POST. 43 | 44 | - Construção de comandos SQL: Você provavelmente está acostumado a criar comandos SQL e concatenar strings com `$_GET` e `$_POST`, mas essa prática vai pulverizar pelo seu código possíveis falhas de segurança. Para contornar isso você leva um construtir de comandos SQL na faixa que usa os famosos `Prepared Statements` para criar as instruções deixando seu código mais limpo e menos desprotegido. 45 | 46 | -------------------------------------------------------------------------------- /app/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Demo 4 | 6 | 8 | 9 | 10 |
11 |
12 |

', Url::host(), Url::path(), '', ' from ', address()); ?>

13 |
14 |
15 |
16 |
17 |
18 | 19 |
20 | 21 |
22 |
23 |
24 |

25 | 26 | 29 | 30 |

31 |
32 |
33 |

34 | 35 |

36 |
37 |
38 |

39 | 43 |

44 |
45 |
46 |

47 | 51 | 55 |

56 |
57 |
58 | 59 |
60 | 71 |
72 |
73 |
74 |

75 | 76 |

77 |
78 |
79 |
80 | 81 | -------------------------------------------------------------------------------- /bootstrap/constants.php: -------------------------------------------------------------------------------- 1 | $property)) { 137 | /** @noinspection PhpVariableVariableInspection */ 138 | return $value->$property; 139 | } 140 | return $default; 141 | } 142 | } 143 | 144 | /** 145 | * @SuppressWarnings("ExitExpression") 146 | */ 147 | if (!function_exists('stop')) { 148 | /** 149 | * @param array ...$arguments 150 | */ 151 | function stop(...$arguments) 152 | { 153 | ob_start(); 154 | if (count($arguments) === 1) { 155 | $arguments = $arguments[0]; 156 | } 157 | echo json_encode($arguments); 158 | $contents = ob_get_contents(); 159 | ob_end_clean(); 160 | out($contents); 161 | die; 162 | } 163 | } 164 | 165 | if (!function_exists('guid')) { 166 | /** 167 | * @param bool $brackets 168 | * @return string 169 | */ 170 | function guid($brackets = false) 171 | { 172 | mt_srand((double)microtime() * 10000); 173 | 174 | $char = strtoupper(md5(uniqid(rand(), true))); 175 | $hyphen = chr(45); 176 | $uuid = substr($char, 0, 8) . $hyphen . substr($char, 8, 4) . $hyphen . substr($char, 12, 4) . $hyphen . 177 | substr($char, 16, 4) . $hyphen . substr($char, 20, 12); 178 | if ($brackets) { 179 | $uuid = chr(123) . $uuid . chr(125); 180 | } 181 | 182 | return $uuid; 183 | } 184 | } 185 | 186 | if (!function_exists('error_message')) { 187 | /** 188 | * @param Throwable $error 189 | * @return string 190 | */ 191 | function error_message(Throwable $error) 192 | { 193 | $pieces = []; 194 | $line = function ($message, $file, $line) { 195 | $file = str_replace(dirname(__DIR__, 2), '', $file); 196 | return $message . ' on ' . $file . ' in ' . $line; 197 | }; 198 | 199 | $pieces[] = $line($error->getMessage(), $error->getFile(), $error->getLine()); 200 | 201 | if (method_exists($error, 'getDetails')) { 202 | $pieces[] = '~'; 203 | $pieces[] = json_encode($error->getDetails(), JSON_PRETTY_PRINT); 204 | } 205 | if (is_array($error->getTrace())) { 206 | $pieces[] = '~'; 207 | foreach ($error->getTrace() as $item) { 208 | $class = get($item, 'class'); 209 | $function = get($item, 'function'); 210 | $pieces[] = $line("`{$class}::{$function}`", get($item, 'file'), get($item, 'line')); 211 | } 212 | } 213 | return implode(PHP_EOL, $pieces); 214 | } 215 | } 216 | 217 | if (!function_exists('search')) { 218 | /** 219 | * @param array $context 220 | * @param array|string $path 221 | * @param mixed $default (null) 222 | * @return mixed|null 223 | */ 224 | function search(array $context, $path, $default = null) 225 | { 226 | if (!is_array($path)) { 227 | $path = explode('.', $path); 228 | } 229 | foreach ($path as $piece) { 230 | if (!is_array($context) || !array_key_exists($piece, $context)) { 231 | return $default; 232 | } 233 | $context = $context[$piece]; 234 | } 235 | return $context; 236 | } 237 | } 238 | 239 | if (!function_exists('read')) { 240 | /** 241 | * @param string $prompt 242 | * @param string $options 243 | * @return string 244 | */ 245 | function read($prompt = '$ ', $options = '') 246 | { 247 | if ($options) { 248 | $prompt = "{$prompt} {$options}\$ "; 249 | } 250 | $reader = function () use ($prompt) { 251 | return readline("{$prompt}"); 252 | }; 253 | if (PHP_OS === 'WINNT') { 254 | $reader = function () use ($prompt) { 255 | echo $prompt; 256 | return stream_get_line(STDIN, 1024, PHP_EOL); 257 | }; 258 | } 259 | $line = $reader(); 260 | readline_add_history($line); 261 | 262 | return trim($line); 263 | } 264 | } 265 | 266 | if (!function_exists('type')) { 267 | /** 268 | * @param mixed $value 269 | * @param string $type 270 | * @return bool 271 | */ 272 | function type($value, string $type) 273 | { 274 | return gettype($value) === $type; 275 | } 276 | } 277 | 278 | /** 279 | * @SuppressWarnings("SuperGlobals") 280 | */ 281 | if (!function_exists('address')) { 282 | /** 283 | * @return string 284 | */ 285 | function address() 286 | { 287 | $sources = ['REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP']; 288 | foreach ($sources as $source) { 289 | if (isset($_SERVER[$source])) { 290 | return $_SERVER[$source]; 291 | } 292 | } 293 | return 'x.x.x.x'; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /bootstrap/index.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'name' => 'base64_encode', 17 | ], 18 | 'decode' => [ 19 | 'name' => 'base64_decode', 20 | ], 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /essentials/Encode.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'name' => 'ord', 17 | ], 18 | 'soundex' => [ 19 | 'name' => 'soundex', 20 | ], 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /essentials/File.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'name' => 'file_put_contens', 19 | ], 20 | /** @link http://php.net/manual/en/function.file-get-contents.php */ 21 | 'read' => [ 22 | 'name' => 'file_get_contens', 23 | ], 24 | /** @link http://php.net/manual/en/function.file-exists.php */ 25 | 'exists' => [ 26 | 'name' => 'file_exists', 27 | ], 28 | ]; 29 | } 30 | -------------------------------------------------------------------------------- /essentials/Hash.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'name' => 'md5', 17 | ], 18 | 'sha1' => [ 19 | 'name' => 'sha1', 20 | ], 21 | ]; 22 | } -------------------------------------------------------------------------------- /essentials/Http.php: -------------------------------------------------------------------------------- 1 | [ 15 | 'name' => 'preg_split', // $pattern, $subject, $limit = -1, $flags = 0 16 | ], 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /essentials/Text.php: -------------------------------------------------------------------------------- 1 | [ 32 | 'name' => 'strlen', 33 | ], 34 | 'replace' => [ 35 | 'name' => 'str_replace', 36 | 'arguments' => [1, 2, 0], 37 | ], 38 | 'first' => [ 39 | 'name' => 'strpos', 40 | ], 41 | 'last' => [ 42 | 'name' => 'strrchr', 43 | ], 44 | 'upper' => [ 45 | 'name' => 'strtoupper', 46 | ], 47 | 'lower' => [ 48 | 'name' => 'strtolower', 49 | ], 50 | 'capitalize' => [ 51 | 'name' => 'ucwords', 52 | ], 53 | 'unCapitalize' => [ 54 | 'name' => 'lcfirst', 55 | ], 56 | 'split' => [ 57 | 'name' => 'explode', 58 | ], 59 | 'join' => [ 60 | 'name' => 'implode', 61 | ], 62 | 'levenshtein' => [ 63 | 'name' => 'levenshtein', 64 | ], 65 | 'substring' => [ 66 | 'name' => 'substr', 67 | ], 68 | 'trim' => [ 69 | 'name' => 'trim', 70 | ], 71 | 'wrap' => [ 72 | 'name' => 'wordwrap', 73 | ], 74 | 'compare' => [ 75 | 'name' => 'strcmp', 76 | ], 77 | 'divide' => [ 78 | 'name' => 'str_split', 79 | ], 80 | 'shuffle' => [ 81 | 'name' => 'str_shuffle', 82 | ], 83 | 'repeat' => [ 84 | 'name' => 'str_repeat', 85 | ], 86 | ]; 87 | } 88 | -------------------------------------------------------------------------------- /essentials/Url.php: -------------------------------------------------------------------------------- 1 | compile(dirname(__DIR__) . '/app/' . $app); 13 | if (is_null($compiled)) { 14 | /** @noinspection PhpVoidFunctionResultUsedInspection */ 15 | return out('Whoops'); 16 | } 17 | out($compiled); 18 | } catch (Throwable $error) { 19 | echo $error->getMessage(); 20 | } 21 | --------------------------------------------------------------------------------