├── public ├── index.php ├── css │ └── style.css ├── package-lock.json └── package.json ├── src ├── Model │ ├── UserModel.php │ ├── Factory │ │ ├── PdoFactory.php │ │ └── ModelFactory.php │ ├── PdoDb.php │ └── MainModel.php ├── View │ ├── layout │ │ ├── navbar.twig │ │ ├── footer.twig │ │ └── layout.twig │ └── home.twig ├── Controller │ ├── HomeController.php │ └── MainController.php └── Router.php ├── .gitignore ├── .htaccess ├── config ├── db.php └── db.sql ├── LICENSE.md ├── composer.json ├── README.md └── composer.lock /public/index.php: -------------------------------------------------------------------------------- 1 | run(); 7 | -------------------------------------------------------------------------------- /src/Model/UserModel.php: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymLinks -Multiviews 3 | 4 | RewriteEngine on 5 | RewriteBase / 6 | 7 | # Force https 8 | RewriteCond %{REQUEST_SCHEME} =http 9 | RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 10 | 11 | # Force non-www 12 | RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] 13 | RewriteRule ^(.*)$ https://%1/$1 [NE,R=301,L] 14 | 15 | # Remove public/ 16 | RewriteCond %{REQUEST_URI} !/public/ [NC] 17 | RewriteRule ^(.*?)/?$ public/$1 [L] 18 | -------------------------------------------------------------------------------- /config/db.php: -------------------------------------------------------------------------------- 1 | PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 13 | -------------------------------------------------------------------------------- /public/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-mvc", 3 | "description": "Instructional Template to start a Web Application with a PHP MVC Architecture", 4 | "keywords": [ 5 | "pedagogic", 6 | "template", 7 | "web", 8 | "application", 9 | "php", 10 | "mvc" 11 | ], 12 | "license": "MIT", 13 | "main": "index.php", 14 | "homepage": "https://philippebeck.net", 15 | "repository": "github:philippebeck/php-mvc", 16 | "bugs": "https://github.com/philippebeck/php-mvc/issues", 17 | "dependencies": { 18 | "@fortawesome/fontawesome-free": "^5.13.1" 19 | }, 20 | "author": { 21 | "name": "Philippe Beck", 22 | "email": "philippe@philippebeck.net", 23 | "url": "https://philippebeck.net" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Controller/HomeController.php: -------------------------------------------------------------------------------- 1 | listData(); 27 | 28 | return $this->twig->render("home.twig", ["allUsers" => $allUsers]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/View/layout/footer.twig: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /src/Model/Factory/PdoFactory.php: -------------------------------------------------------------------------------- 1 | exec("SET NAMES UTF8"); 31 | } 32 | 33 | return self::$pdo; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Model/Factory/ModelFactory.php: -------------------------------------------------------------------------------- 1 | twig = new Environment(new FilesystemLoader("../src/View"), array("cache" => false)); 27 | } 28 | 29 | /** 30 | * Redirects to another URL 31 | * @param string $page 32 | * @param array $params 33 | */ 34 | public function redirect(string $page, array $params = []) 35 | { 36 | $params["access"] = $page; 37 | header("Location: index.php?" . http_build_query($params)); 38 | 39 | exit; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /config/db.sql: -------------------------------------------------------------------------------- 1 | -- WARNING : Don't forget to add the file name inside the .gitignore file when you add sensible datas here (like passwords) 2 | 3 | -- For Development only ! (Depends on your online server architecture) 4 | DROP DATABASE IF EXISTS `php_mvc`; 5 | CREATE DATABASE `php_mvc` CHARACTER SET utf8; 6 | 7 | -- Needs to be replaced in Production with the db name of the online server 8 | USE `php_mvc`; 9 | 10 | -- Creates the table User 11 | CREATE TABLE `User` 12 | ( 13 | `id` SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, 14 | `name` VARCHAR(50) NOT NULL, 15 | `image` VARCHAR(50) UNIQUE, 16 | `email` VARCHAR(100) NOT NULL UNIQUE, 17 | `pass` VARCHAR(60) NOT NULL 18 | ) 19 | ENGINE=INNODB DEFAULT CHARSET=utf8; 20 | 21 | -- Inserts the User data 22 | -- WARNING : Never store real passwords in a commit file 23 | INSERT INTO `User` 24 | (`name`, `image`, `email`, `pass`) 25 | VALUES 26 | ('John', 'john.jpg', 'john@doe.com', 'john465'), 27 | ('Jane', 'jane.jpg', 'jane@doe.com', 'jane465'); 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Philippe Beck 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 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "philippebeck/php-mvc", 3 | "version": "1.1.0", 4 | "type": "project", 5 | "description": "Instructional Template to start a Web Application with a PHP MVC Architecture", 6 | "keywords": [ 7 | "pedagogic", 8 | "template", 9 | "web", 10 | "application", 11 | "php", 12 | "mvc" 13 | ], 14 | "homepage": "https://php-mvc.philippebeck.net", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Philippe Beck", 19 | "email": "philippe@philippebeck.net", 20 | "homepage": "https://philippebeck.net", 21 | "role": "Lead Developer" 22 | } 23 | ], 24 | "autoload": { 25 | "psr-4": { 26 | "App\\": "src/" 27 | } 28 | }, 29 | "require": { 30 | "php": "7.3", 31 | "twig/twig": "^3.0.3" 32 | }, 33 | "config": { 34 | "platform": { 35 | "php": "7.3" 36 | } 37 | }, 38 | "support": { 39 | "email": "admin@philippebeck.net", 40 | "issues": "https://github.com/philippebeck/php-mvc/issues", 41 | "wiki": "https://github.com/philippebeck/php-mvc/wiki", 42 | "source": "https://github.com/philippebeck/php-mvc" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/View/home.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layout/layout.twig' %} 2 | 3 | {% block title %}Home{% endblock %} 4 | 5 | {% block description %}Homepage of the PHP-MVC project{% endblock %} 6 | 7 | {% block main %} 8 |
9 |
10 |

Introduction

11 | 12 |

This project is a pedagogic template to start a Web application with a PHP MVC architecture...

13 |

You will find the documentation here...

14 |

Don't hesitate to send issues or pull requests, I will watch them with interest...

15 |
16 | 17 |
18 |

Demonstration

19 | 20 |

The example users are :

21 | 28 |
29 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /src/Model/PdoDb.php: -------------------------------------------------------------------------------- 1 | pdo = $pdo; 28 | } 29 | 30 | /** 31 | * Returns a unique result from the Database 32 | * @param string $query 33 | * @param array $params 34 | * @return mixed 35 | */ 36 | public function getData(string $query, array $params = []) 37 | { 38 | $PDOStatement = $this->pdo->prepare($query); 39 | $PDOStatement->execute($params); 40 | 41 | return $PDOStatement->fetch(); 42 | } 43 | 44 | /** 45 | * Returns many results from the Database 46 | * @param string $query 47 | * @param array $params 48 | * @return array|mixed 49 | */ 50 | public function getAllData(string $query, array $params = []) 51 | { 52 | $PDOStatement = $this->pdo->prepare($query); 53 | $PDOStatement->execute($params); 54 | 55 | return $PDOStatement->fetchAll(); 56 | } 57 | 58 | /** 59 | * Executes an action to the Database 60 | * @param string $query 61 | * @param array $params 62 | * @return bool|mixed 63 | */ 64 | public function setData(string $query, array $params = []) 65 | { 66 | $PDOStatement = $this->pdo->prepare($query); 67 | 68 | return $PDOStatement->execute($params); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/View/layout/layout.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ block('title') }} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {{ include('layout/navbar.twig') }} 40 | 41 |
42 |

{{ block('title') }}

43 |
44 | 45 | {% block main %}{% endblock %} 46 | 47 | {{ include('layout/footer.twig') }} 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Router.php: -------------------------------------------------------------------------------- 1 | parseUrl(); 46 | $this->setController(); 47 | $this->setMethod(); 48 | } 49 | 50 | /** 51 | * Parses the URL to get the Controller & his Method 52 | */ 53 | public function parseUrl() 54 | { 55 | $access = filter_input(INPUT_GET, "access"); 56 | 57 | if (!isset($access)) { 58 | $access = "home"; 59 | } 60 | 61 | $access = explode("!", $access); 62 | $this->controller = $access[0]; 63 | $this->method = count($access) == 1 ? "default" : $access[1]; 64 | } 65 | 66 | /** 67 | * Sets the requested Controller 68 | */ 69 | public function setController() 70 | { 71 | $this->controller = ucfirst(strtolower($this->controller)) . "Controller"; 72 | $this->controller = self::DEFAULT_PATH . $this->controller; 73 | 74 | if (!class_exists($this->controller)) { 75 | $this->controller = self::DEFAULT_PATH . self::DEFAULT_CONTROLLER; 76 | } 77 | } 78 | 79 | /** 80 | * Sets the requested Method 81 | */ 82 | public function setMethod() 83 | { 84 | $this->method = strtolower($this->method) . "Method"; 85 | 86 | if (!method_exists($this->controller, $this->method)) { 87 | $this->method = self::DEFAULT_METHOD; 88 | } 89 | } 90 | 91 | /** 92 | * Creates the Controller object & calls the Method on it 93 | */ 94 | public function run() 95 | { 96 | $this->controller = new $this->controller(); 97 | $response = call_user_func([$this->controller, $this->method]); 98 | 99 | echo filter_var($response); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Model/MainModel.php: -------------------------------------------------------------------------------- 1 | database = $database; 32 | $model = explode("\\", get_class($this)); 33 | $this->table = ucfirst(str_replace("Model", "", array_pop($model))); 34 | } 35 | 36 | /** 37 | * Lists all Datas from the id or another key 38 | * @param string $value 39 | * @param string $key 40 | * @return array|mixed 41 | */ 42 | public function listData(string $value = null, string $key = null) 43 | { 44 | if (isset($key)) { 45 | $query = "SELECT * FROM " . $this->table . " WHERE " . $key . " = ?"; 46 | 47 | return $this->database->getAllData($query, [$value]); 48 | } 49 | $query = "SELECT * FROM " . $this->table; 50 | 51 | return $this->database->getAllData($query); 52 | } 53 | 54 | /** 55 | * Creates a new Data entry 56 | * @param array $data 57 | */ 58 | public function createData(array $data) 59 | { 60 | $keys = implode(", ", array_keys($data)); 61 | $values = implode("', '", $data); 62 | $query = "INSERT INTO " . $this->table . " (" . $keys . ") VALUES ('" . $values . "')"; 63 | 64 | $this->database->setData($query); 65 | } 66 | 67 | /** 68 | * Reads Data from its id or another key 69 | * @param string $value 70 | * @param string|null $key 71 | * @return mixed 72 | */ 73 | public function readData(string $value, string $key = null) 74 | { 75 | if (isset($key)) { 76 | $query = "SELECT * FROM " . $this->table . " WHERE " . $key . " = ?"; 77 | } else { 78 | $query = "SELECT * FROM " . $this->table . " WHERE id = ?"; 79 | } 80 | 81 | return $this->database->getData($query, [$value]); 82 | } 83 | 84 | /** 85 | * Updates Data from its id or another key 86 | * @param string $value 87 | * @param array $data 88 | * @param string|null $key 89 | */ 90 | public function updateData(string $value, array $data, string $key = null) 91 | { 92 | $set = null; 93 | 94 | foreach ($data as $dataKey => $dataValue) { 95 | $set .= $dataKey . " = '" . $dataValue . "', "; 96 | } 97 | 98 | $set = substr_replace($set, "", -2); 99 | 100 | if (isset($key)) { 101 | $query = "UPDATE " . $this->table . " SET " . $set . " WHERE " . $key . " = ?"; 102 | } else { 103 | $query = "UPDATE " . $this->table . " SET " . $set . " WHERE id = ?"; 104 | } 105 | 106 | $this->database->setData($query, [$value]); 107 | } 108 | 109 | /** 110 | * Deletes Data from its id or another key 111 | * @param string $value 112 | * @param string|null $key 113 | */ 114 | public function deleteData(string $value, string $key = null) 115 | { 116 | if (isset($key)) { 117 | $query = "DELETE FROM " . $this->table . " WHERE " . $key . " = ?"; 118 | } else { 119 | $query = "DELETE FROM " . $this->table . " WHERE id = ?"; 120 | } 121 | 122 | $this->database->setData($query, [$value]); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP-MVC 2 | 3 | Instructional Template to start a Web Application with a PHP MVC Architecture 4 | 5 | ## Overview 6 | 7 | This project is a pedagogic template to start a Web application with a PHP MVC architecture... 8 | 9 | Issues presents what steps are necessary to build it. 10 | 11 | Wiki presents the procedure to create your own PHP MVC application with this example. 12 | 13 | ## Summary 14 | 15 | - [Download](#download) 16 | - [Support](#support) 17 | - [Open-Source](#open-source) 18 | - [Documentation](#documentation) 19 | - [Issues](#issues) 20 | - [Pull Requests](#pull-requests) 21 | - [Contributing](#contributing) 22 | - [Versioning](#versioning) 23 | - [Creator](#creator) 24 | - [Copyright](#copyright) 25 | 26 | --- 27 | 28 | ## Download 29 | 30 | [Latest Release](https://github.com/philippebeck/php-mvc/releases) 31 | 32 | `git clone https://github.com/philippebeck/php-mvc.git` 33 | 34 | [![Repo Size](https://img.shields.io/github/repo-size/philippebeck/php-mvc.svg?label=Repo+Size)](https://github.com/philippebeck/php-mvc/tree/master) 35 | 36 | --- 37 | 38 | ## Support 39 | 40 | php-mvc has no continuous support ! 41 | 42 | [![Project Maintained](https://img.shields.io/maintenance/no/2020.svg?label=Maintained)](https://github.com/philippebeck/php-mvc) 43 | [![GitHub Last Commit](https://img.shields.io/github/last-commit/philippebeck/php-mvc.svg?label=Last+Commit)](https://github.com/philippebeck/php-mvc/commits/master) 44 | 45 | --- 46 | 47 | ## Open-Source 48 | 49 | [![GitHub Stars](https://img.shields.io/github/stars/philippebeck/php-mvc.svg?label=GitHub+:+php-mvc+|+Stars)](https://github.com/philippebeck/php-mvc) 50 | 51 | --- 52 | 53 | ## Documentation 54 | 55 | Documentation is available ! 56 | 57 | [![WebSite Status](https://img.shields.io/website-up-down-green-red/https/github.com/philippebeck/php-mvc/wiki.svg?label=Documentation)](https://github.com/philippebeck/php-mvc/wiki) 58 | 59 | --- 60 | 61 | ## Issues 62 | 63 | Issues can be created here 64 | 65 | [![GitHub Open Issues](https://img.shields.io/github/issues/philippebeck/php-mvc.svg?label=Issues)](https://github.com/philippebeck/php-mvc/issues) 66 | 67 | --- 68 | 69 | ## Pull Requests 70 | 71 | And Pull Requests can be created there 72 | 73 | [![GitHub Open Pull Requests](https://img.shields.io/github/issues-pr/philippebeck/php-mvc.svg?label=Pull+Requests)](https://github.com/philippebeck/php-mvc/pulls) 74 | 75 | --- 76 | 77 | ## Contributing 78 | 79 | php-mvc needs you if you like it : sends pull requests on GitHub to improve it !! 80 | 81 | [![GitHub Contributors](https://img.shields.io/github/contributors/philippebeck/php-mvc.svg?label=Contributors)](https://github.com/philippebeck/php-mvc/graphs/contributors) 82 | 83 | --- 84 | 85 | ## Versioning 86 | 87 | php-mvc is maintained under the [Semantic Versioning 2.0.0](https://semver.org) 88 | 89 | [![GitHub Version](https://img.shields.io/github/tag/philippebeck/php-mvc.svg?label=Version)](https://github.com/philippebeck/php-mvc/blob/master/composer.json) 90 | 91 | --- 92 | 93 | ## Creator 94 | 95 | Philippe Beck 96 | 97 | [![WebSite Status](https://img.shields.io/website-up-down-green-red/https/philippebeck.net.svg?label=https://philippebeck.net)](https://philippebeck.net) 98 | [![GitHub Followers](https://img.shields.io/github/followers/philippebeck.svg?label=GitHub+:+philippebeck+|+Followers)](https://github.com/philippebeck) 99 | [![Twitter Follow](https://badgen.net/twitter/follow/philippepjbeck)](https://twitter.com/philippepjbeck) 100 | 101 | --- 102 | 103 | ## Copyright 104 | 105 | Code released under the MIT License 106 | 107 | [![GitHub License](https://img.shields.io/github/license/philippebeck/php-mvc.svg?label=License)](https://github.com/philippebeck/php-mvc/blob/master/LICENSE) 108 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "f38893f72f8687f562c2436cca7971f4", 8 | "packages": [ 9 | { 10 | "name": "symfony/polyfill-ctype", 11 | "version": "v1.17.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/symfony/polyfill-ctype.git", 15 | "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", 20 | "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.3" 25 | }, 26 | "suggest": { 27 | "ext-ctype": "For best performance" 28 | }, 29 | "type": "library", 30 | "extra": { 31 | "branch-alias": { 32 | "dev-master": "1.17-dev" 33 | } 34 | }, 35 | "autoload": { 36 | "psr-4": { 37 | "Symfony\\Polyfill\\Ctype\\": "" 38 | }, 39 | "files": [ 40 | "bootstrap.php" 41 | ] 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Gert de Pagter", 50 | "email": "BackEndTea@gmail.com" 51 | }, 52 | { 53 | "name": "Symfony Community", 54 | "homepage": "https://symfony.com/contributors" 55 | } 56 | ], 57 | "description": "Symfony polyfill for ctype functions", 58 | "homepage": "https://symfony.com", 59 | "keywords": [ 60 | "compatibility", 61 | "ctype", 62 | "polyfill", 63 | "portable" 64 | ], 65 | "funding": [ 66 | { 67 | "url": "https://symfony.com/sponsor", 68 | "type": "custom" 69 | }, 70 | { 71 | "url": "https://github.com/fabpot", 72 | "type": "github" 73 | }, 74 | { 75 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 76 | "type": "tidelift" 77 | } 78 | ], 79 | "time": "2020-05-12T16:14:59+00:00" 80 | }, 81 | { 82 | "name": "symfony/polyfill-mbstring", 83 | "version": "v1.17.0", 84 | "source": { 85 | "type": "git", 86 | "url": "https://github.com/symfony/polyfill-mbstring.git", 87 | "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" 88 | }, 89 | "dist": { 90 | "type": "zip", 91 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", 92 | "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", 93 | "shasum": "" 94 | }, 95 | "require": { 96 | "php": ">=5.3.3" 97 | }, 98 | "suggest": { 99 | "ext-mbstring": "For best performance" 100 | }, 101 | "type": "library", 102 | "extra": { 103 | "branch-alias": { 104 | "dev-master": "1.17-dev" 105 | } 106 | }, 107 | "autoload": { 108 | "psr-4": { 109 | "Symfony\\Polyfill\\Mbstring\\": "" 110 | }, 111 | "files": [ 112 | "bootstrap.php" 113 | ] 114 | }, 115 | "notification-url": "https://packagist.org/downloads/", 116 | "license": [ 117 | "MIT" 118 | ], 119 | "authors": [ 120 | { 121 | "name": "Nicolas Grekas", 122 | "email": "p@tchwork.com" 123 | }, 124 | { 125 | "name": "Symfony Community", 126 | "homepage": "https://symfony.com/contributors" 127 | } 128 | ], 129 | "description": "Symfony polyfill for the Mbstring extension", 130 | "homepage": "https://symfony.com", 131 | "keywords": [ 132 | "compatibility", 133 | "mbstring", 134 | "polyfill", 135 | "portable", 136 | "shim" 137 | ], 138 | "funding": [ 139 | { 140 | "url": "https://symfony.com/sponsor", 141 | "type": "custom" 142 | }, 143 | { 144 | "url": "https://github.com/fabpot", 145 | "type": "github" 146 | }, 147 | { 148 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 149 | "type": "tidelift" 150 | } 151 | ], 152 | "time": "2020-05-12T16:47:27+00:00" 153 | }, 154 | { 155 | "name": "twig/twig", 156 | "version": "v3.0.3", 157 | "source": { 158 | "type": "git", 159 | "url": "https://github.com/twigphp/Twig.git", 160 | "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2" 161 | }, 162 | "dist": { 163 | "type": "zip", 164 | "url": "https://api.github.com/repos/twigphp/Twig/zipball/3b88ccd180a6b61ebb517aea3b1a8906762a1dc2", 165 | "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2", 166 | "shasum": "" 167 | }, 168 | "require": { 169 | "php": "^7.2.5", 170 | "symfony/polyfill-ctype": "^1.8", 171 | "symfony/polyfill-mbstring": "^1.3" 172 | }, 173 | "require-dev": { 174 | "psr/container": "^1.0", 175 | "symfony/phpunit-bridge": "^4.4|^5.0" 176 | }, 177 | "type": "library", 178 | "extra": { 179 | "branch-alias": { 180 | "dev-master": "3.0-dev" 181 | } 182 | }, 183 | "autoload": { 184 | "psr-4": { 185 | "Twig\\": "src/" 186 | } 187 | }, 188 | "notification-url": "https://packagist.org/downloads/", 189 | "license": [ 190 | "BSD-3-Clause" 191 | ], 192 | "authors": [ 193 | { 194 | "name": "Fabien Potencier", 195 | "email": "fabien@symfony.com", 196 | "homepage": "http://fabien.potencier.org", 197 | "role": "Lead Developer" 198 | }, 199 | { 200 | "name": "Twig Team", 201 | "role": "Contributors" 202 | }, 203 | { 204 | "name": "Armin Ronacher", 205 | "email": "armin.ronacher@active-4.com", 206 | "role": "Project Founder" 207 | } 208 | ], 209 | "description": "Twig, the flexible, fast, and secure template language for PHP", 210 | "homepage": "https://twig.symfony.com", 211 | "keywords": [ 212 | "templating" 213 | ], 214 | "time": "2020-02-11T15:33:47+00:00" 215 | } 216 | ], 217 | "packages-dev": [], 218 | "aliases": [], 219 | "minimum-stability": "stable", 220 | "stability-flags": [], 221 | "prefer-stable": false, 222 | "prefer-lowest": false, 223 | "platform": { 224 | "php": "7.3" 225 | }, 226 | "platform-dev": [], 227 | "platform-overrides": { 228 | "php": "7.3" 229 | }, 230 | "plugin-api-version": "1.1.0" 231 | } 232 | --------------------------------------------------------------------------------