├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── public └── index.php └── src ├── Annotations └── Route.php ├── Container.php ├── Controller ├── IndexController.php └── PostController.php ├── Format ├── BaseFormat.php ├── FormatInterface.php ├── FromStringInterface.php ├── JSON.php ├── NamedFormatInterface.php ├── XML.php └── YAML.php ├── Kernel.php ├── Serializer.php └── Service └── Serializer.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Piotr Jura - Udemy Instructor

3 |

Piotr Jura Udemy Courses

4 |

Fado Code Camp

5 |
6 | 7 |

8 | High-quality, comprehensive courses for web developers. 9 |

10 | 11 |

12 | About the Instructor · 13 | Courses · 14 | Contact & Links · 15 | This Course Resources 16 |

17 |
18 | 19 | ## About the Instructor 20 | 21 | I am Piotr Jura, a seasoned web developer and a passionate Udemy instructor. With years of experience in JavaScript, TypeScript, Node, PHP, MySQL, Vue, React, and more, I bring practical, real-world knowledge to my students. 22 | 23 | ## Courses 24 | 25 | - [Master Nuxt 3 - Full-Stack Complete Guide](https://www.udemy.com/course/master-nuxt-full-stack-complete-guide/?referralCode=4EBA58BFBD39A31A9BE9) 26 | - [Symfony 6 Framework Hands-On 2023](https://www.udemy.com/course/symfony-framework-hands-on/?referralCode=6750F64C057515A5F787) 27 | - [Vue 3 Mastery: Firebase & More - Learn by Doing!](https://www.udemy.com/course/vuejs-course/?referralCode=26DAD96DAB47B4602DA3) 28 | - [Master NestJS - Node.js Framework 2023](https://www.udemy.com/course/master-nestjs-the-javascript-nodejs-framework/?referralCode=C8A3F83982053A5E44C0) 29 | - [Master Laravel with GraphQL, Vue.js, and Tailwind](https://www.udemy.com/course/master-laravel-with-graphql-vuejs-and-tailwind/?referralCode=CE3B5297B3614EFA884A) 30 | - [Master Laravel, Vue 3 & Inertia Full Stack 2023](https://www.udemy.com/course/master-laravel-6-with-vuejs-fullstack-development/?referralCode=4A6CED7AA1583CB709D6) 31 | - [Master Laravel 10 for Beginners & Intermediate 2023](https://www.udemy.com/course/laravel-beginner-fundamentals/?referralCode=E86A873AC47FB438D79C) 32 | - [Symfony API Platform with React Full Stack Masterclass](https://www.udemy.com/course/symfony-api-platform-reactjs-full-stack-masterclass/?referralCode=D2C29D1C641BB0CDBCD4) 33 | 34 | ## Contact and Links 35 | 36 | - **Blog:** [Fado Code Camp](https://fadocodecamp.com/) 37 | - **LinkedIn:** [Follow Me on LinkedIn](https://www.linkedin.com/in/piotr-j-24250b257/) 38 | - **GitHub:** You are here! Give me a follow! 39 | - **Twitter:** [@piotr_jura](https://twitter.com/piotr_jura) 40 | 41 | ## Course Resources 42 | 43 | Coming up! 44 | 45 | --- 46 | 47 |

48 | Explore, Learn, and Grow with My Comprehensive Web Development Courses! 49 |

50 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-basics/php-7", 3 | "require": { 4 | "php": ">=7.0.0", 5 | "doctrine/annotations": "^1.6" 6 | }, 7 | "autoload": { 8 | "psr-4": { 9 | "App\\": "src/" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /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#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "889ff602972becd32e10b63298e1b076", 8 | "packages": [ 9 | { 10 | "name": "doctrine/annotations", 11 | "version": "v1.6.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/doctrine/annotations.git", 15 | "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", 20 | "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "doctrine/lexer": "1.*", 25 | "php": "^7.1" 26 | }, 27 | "require-dev": { 28 | "doctrine/cache": "1.*", 29 | "phpunit/phpunit": "^6.4" 30 | }, 31 | "type": "library", 32 | "extra": { 33 | "branch-alias": { 34 | "dev-master": "1.6.x-dev" 35 | } 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Roman Borschel", 49 | "email": "roman@code-factory.org" 50 | }, 51 | { 52 | "name": "Benjamin Eberlei", 53 | "email": "kontakt@beberlei.de" 54 | }, 55 | { 56 | "name": "Guilherme Blanco", 57 | "email": "guilhermeblanco@gmail.com" 58 | }, 59 | { 60 | "name": "Jonathan Wage", 61 | "email": "jonwage@gmail.com" 62 | }, 63 | { 64 | "name": "Johannes Schmitt", 65 | "email": "schmittjoh@gmail.com" 66 | } 67 | ], 68 | "description": "Docblock Annotations Parser", 69 | "homepage": "http://www.doctrine-project.org", 70 | "keywords": [ 71 | "annotations", 72 | "docblock", 73 | "parser" 74 | ], 75 | "time": "2017-12-06T07:11:42+00:00" 76 | }, 77 | { 78 | "name": "doctrine/lexer", 79 | "version": "v1.0.1", 80 | "source": { 81 | "type": "git", 82 | "url": "https://github.com/doctrine/lexer.git", 83 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" 84 | }, 85 | "dist": { 86 | "type": "zip", 87 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", 88 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", 89 | "shasum": "" 90 | }, 91 | "require": { 92 | "php": ">=5.3.2" 93 | }, 94 | "type": "library", 95 | "extra": { 96 | "branch-alias": { 97 | "dev-master": "1.0.x-dev" 98 | } 99 | }, 100 | "autoload": { 101 | "psr-0": { 102 | "Doctrine\\Common\\Lexer\\": "lib/" 103 | } 104 | }, 105 | "notification-url": "https://packagist.org/downloads/", 106 | "license": [ 107 | "MIT" 108 | ], 109 | "authors": [ 110 | { 111 | "name": "Roman Borschel", 112 | "email": "roman@code-factory.org" 113 | }, 114 | { 115 | "name": "Guilherme Blanco", 116 | "email": "guilhermeblanco@gmail.com" 117 | }, 118 | { 119 | "name": "Johannes Schmitt", 120 | "email": "schmittjoh@gmail.com" 121 | } 122 | ], 123 | "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", 124 | "homepage": "http://www.doctrine-project.org", 125 | "keywords": [ 126 | "lexer", 127 | "parser" 128 | ], 129 | "time": "2014-09-09T13:34:57+00:00" 130 | } 131 | ], 132 | "packages-dev": [], 133 | "aliases": [], 134 | "minimum-stability": "stable", 135 | "stability-flags": [], 136 | "prefer-stable": false, 137 | "prefer-lowest": false, 138 | "platform": { 139 | "php": ">=7.0.0" 140 | }, 141 | "platform-dev": [] 142 | } 143 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | boot(); 11 | $kernel->handleRequest(); -------------------------------------------------------------------------------- /src/Annotations/Route.php: -------------------------------------------------------------------------------- 1 | services[$name] = $closure; 16 | 17 | if ($alias) { 18 | $this->addAlias($alias, $name); 19 | } 20 | } 21 | 22 | public function addAlias(string $alias, string $service): void 23 | { 24 | $this->aliases[$alias] = $service; 25 | } 26 | 27 | public function hasService(string $name): bool 28 | { 29 | return isset($this->services[$name]); 30 | } 31 | 32 | public function hasAlias(string $name): bool 33 | { 34 | return isset($this->aliases[$name]); 35 | } 36 | 37 | public function getService(string $name) 38 | { 39 | if (!$this->hasService($name)) { 40 | return null; 41 | } 42 | 43 | if ($this->services[$name] instanceof \Closure) { 44 | $this->services[$name] = $this->services[$name](); 45 | } 46 | 47 | return $this->services[$name]; 48 | } 49 | 50 | public function getAlias(string $name) 51 | { 52 | return $this->getService($this->aliases[$name]); 53 | } 54 | 55 | public function getServices(): array 56 | { 57 | return [ 58 | 'services' => array_keys($this->services), 59 | 'aliases' => $this->aliases 60 | ]; 61 | } 62 | 63 | public function loadServices(string $namespace, ?\Closure $callback = null): void 64 | { 65 | $baseDir = __DIR__ . '/'; 66 | 67 | $actualDirectory = str_replace('\\', '/', $namespace); 68 | $actualDirectory = $baseDir . substr( 69 | $actualDirectory, 70 | strpos($actualDirectory, '/') + 1 71 | ); 72 | 73 | $files = array_filter(scandir($actualDirectory), function ($file) { 74 | return $file !== '.' && $file !== '..'; 75 | }); 76 | 77 | foreach($files as $file) { 78 | $class = new \ReflectionClass( 79 | $namespace . '\\' . basename($file, '.php') 80 | ); 81 | $serviceName = $class->getName(); 82 | 83 | $constructor = $class->getConstructor(); 84 | $arguments = $constructor->getParameters(); 85 | 86 | // Parameters to inject into service constructor 87 | $serviceParameters = []; 88 | 89 | foreach ($arguments as $argument) { 90 | $type = (string)$argument->getType(); 91 | 92 | if ($this->hasService($type) || $this->hasAlias($type)) { 93 | $serviceParameters[] = $this->getService($type) 94 | ?? $this->getAlias($type); 95 | } else { 96 | $serviceParameters[] = function() use ($type) { 97 | return $this->getService($type) 98 | ?? $this->getAlias($type); 99 | }; 100 | } 101 | } 102 | 103 | $this->addService($serviceName, function () use ($serviceName, $serviceParameters) { 104 | foreach ($serviceParameters as &$serviceParameter) { 105 | if ($serviceParameter instanceof \Closure) { 106 | $serviceParameter = $serviceParameter(); 107 | } 108 | } 109 | 110 | return new $serviceName(...$serviceParameters); 111 | }); 112 | 113 | if ($callback) { 114 | $callback($serviceName, $class); 115 | } 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /src/Controller/IndexController.php: -------------------------------------------------------------------------------- 1 | serializer = $serializer; 15 | } 16 | 17 | /** 18 | * @Route(route="/") 19 | */ 20 | public function index() 21 | { 22 | return $this->serializer->serialize([ 23 | 'Action' => 'Index', 24 | 'Time' => time() 25 | ]); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Controller/PostController.php: -------------------------------------------------------------------------------- 1 | serializer = $serializer; 15 | } 16 | 17 | /** 18 | * @Route(route="/") 19 | */ 20 | public function index() 21 | { 22 | return $this->serializer->serialize([ 23 | 'Action' => 'Post', 24 | 'Time' => time() 25 | ]); 26 | } 27 | 28 | /** 29 | * @Route(route="/one") 30 | */ 31 | public function one() 32 | { 33 | return $this->serializer->serialize([ 34 | 'Action' => 'PostOne', 35 | 'Time' => time() 36 | ]); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Format/BaseFormat.php: -------------------------------------------------------------------------------- 1 | data; 11 | } 12 | 13 | public function setData(array $data): void 14 | { 15 | $this->data = $data; 16 | } 17 | 18 | public abstract function convert(): string; 19 | 20 | public function __toString() 21 | { 22 | return $this->convert(); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Format/FormatInterface.php: -------------------------------------------------------------------------------- 1 | data); 13 | } 14 | 15 | public function convertFromString($string) 16 | { 17 | return json_decode($string, true); 18 | } 19 | 20 | public function getName(): string 21 | { 22 | return 'JSON'; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Format/NamedFormatInterface.php: -------------------------------------------------------------------------------- 1 | data as $key => $value) { 13 | $result .= '<'.$key.'>'.$value.''; 14 | } 15 | 16 | return htmlspecialchars($result); 17 | } 18 | 19 | public function getName(): string 20 | { 21 | return 'XML'; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Format/YAML.php: -------------------------------------------------------------------------------- 1 | data as $key => $value) { 13 | $result .= $key.': '.$value."\n"; 14 | } 15 | 16 | return htmlspecialchars($result); 17 | } 18 | 19 | public function getName(): string 20 | { 21 | return 'YAML'; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Kernel.php: -------------------------------------------------------------------------------- 1 | container = new Container(); 20 | } 21 | 22 | public function getContainer(): Container 23 | { 24 | return $this->container; 25 | } 26 | 27 | public function boot() 28 | { 29 | $this->bootContainer($this->container); 30 | 31 | return $this; 32 | } 33 | 34 | private function bootContainer(Container $container) 35 | { 36 | $container->addService('format.json', function() use ($container) { 37 | return new JSON(); 38 | }); 39 | 40 | $container->addService('format.xml', function() use ($container) { 41 | return new XML(); 42 | }); 43 | 44 | $container->addService('format', function() use ($container) { 45 | return $container->getService('format.json'); 46 | }, FormatInterface::class); 47 | 48 | $container->loadServices('App\\Service'); 49 | 50 | AnnotationRegistry::registerLoader('class_exists'); 51 | $reader = new AnnotationReader(); 52 | 53 | $routes = []; 54 | 55 | $container->loadServices( 56 | 'App\\Controller', 57 | function (string $serviceName, \ReflectionClass $class) use ($reader, &$routes) { 58 | $route = $reader->getClassAnnotation($class, Route::class); 59 | 60 | if (!$route) { 61 | return; 62 | } 63 | 64 | $baseRoute = $route->route; 65 | 66 | foreach ($class->getMethods() as $method) { 67 | $route = $reader->getMethodAnnotation($method, Route::class); 68 | 69 | if (!$route) { 70 | continue; 71 | } 72 | 73 | $routes[str_replace('//', '/', $baseRoute . $route->route)] = [ 74 | 'service' => $serviceName, 75 | 'method' => $method->getName() 76 | ]; 77 | } 78 | } 79 | ); 80 | 81 | $this->routes = $routes; 82 | } 83 | 84 | public function handleRequest() 85 | { 86 | $uri = $_SERVER['REQUEST_URI']; 87 | 88 | // var_dump($uri); 89 | 90 | if (isset($this->routes[$uri])) { 91 | $route = $this->routes[$uri]; 92 | $response = $this->container->getService($route['service']) 93 | ->{$route['method']}(); 94 | echo $response; 95 | die; 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/Serializer.php: -------------------------------------------------------------------------------- 1 | format = $format; 12 | } 13 | 14 | public function serialize($data): string { 15 | $this->format->setData($data); 16 | 17 | return $this->format->convert(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Service/Serializer.php: -------------------------------------------------------------------------------- 1 | format = $format; 12 | } 13 | 14 | public function serialize($data): string { 15 | $this->format->setData($data); 16 | 17 | return $this->format->convert(); 18 | } 19 | } --------------------------------------------------------------------------------