├── .gitattributes ├── .gitignore ├── Chapter 1 ├── composer.json ├── index.php ├── src │ ├── Animal.php │ ├── Book.php │ ├── Cat.php │ └── Dog.php └── vendor │ ├── autoload.php │ └── composer │ ├── ClassLoader.php │ ├── LICENSE │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ └── installed.json ├── Chapter 2 ├── ApacheProxyPass │ └── vhost.conf └── BlindFaith │ ├── HorrendouslyInsecure.php │ └── better.php ├── Chapter 3 ├── .idea │ ├── .name │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── php.xml │ ├── phpBook3.iml │ └── workspace.xml ├── Abstract │ ├── SFToyFactory.php │ ├── ToyFactory.php │ ├── UKToyFactory.php │ └── index.php ├── Builder │ ├── Pizza.php │ ├── PizzaBuilder.php │ └── index.php ├── FactoryMethod │ ├── CourierNotifierFactory.php │ ├── ElectronicNotifierFactory.php │ ├── Email.php │ ├── Notifier.php │ ├── NotifierFactory.php │ ├── Post.php │ ├── SMS.php │ └── index.php ├── LazyLoader │ ├── Burger.php │ ├── BurgerLazyLoader.php │ └── index.php ├── Prototype │ ├── Student.php │ └── index.php └── SimpleFactory │ ├── Email.php │ ├── Notifier.php │ ├── NotifierFactory.php │ ├── SMS.php │ └── index.php ├── Chapter 4 ├── .idea │ ├── .name │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── php.xml │ ├── phpBook4.iml │ └── workspace.xml ├── Bridge │ ├── Device.php │ ├── InstantMessenger.php │ ├── Messenger.php │ ├── Phone.php │ ├── SMS.php │ ├── Tablet.php │ ├── Transmitter.php │ └── index.php ├── ClassAdapter │ ├── ATM.php │ ├── ATMWithPhoneTopUp.php │ └── index.php ├── Composite │ ├── Music.php │ ├── Playlist.php │ ├── Song.php │ └── index.php ├── Decorator │ ├── Book.php │ ├── EBook.php │ ├── PrintBook.php │ └── index.php ├── Flyweight │ ├── Circle.php │ ├── Shape.php │ ├── ShapeFactory.php │ └── index.php ├── ObjectAdapter │ ├── Insurance.php │ ├── InsuranceMarketCompare.php │ ├── MarketCompare.php │ └── index.php └── Proxy │ ├── AnimalFeeder.php │ ├── AnimalFeederProxy.php │ ├── AnimalFeeders │ ├── Cat.php │ └── Dog.php │ └── index.php ├── Chapter 5 ├── ChainOfResponsibility │ ├── AssociatePurchaser.php │ ├── BoardPurchaser.php │ ├── DirectorPurchaser.php │ ├── ManagerPurchaser.php │ ├── Purchaser.php │ └── index.php ├── Generator │ └── index.php ├── Iterator │ ├── index.php │ └── time.php ├── Observer │ ├── Feed.php │ ├── Reader.php │ └── index.php ├── Specification │ ├── EmployeeIsEngineer.php │ ├── EmployeeSpecification.php │ └── index.php ├── Strategy │ ├── Cube.php │ ├── Power.php │ ├── RaiseNumber.php │ ├── Square.php │ └── index.php └── Template │ ├── MeatballPasta.php │ ├── Pasta.php │ ├── VeganPasta.php │ └── index.php ├── Chapter 6 ├── GettingStarted │ ├── composer.json │ ├── recieve.php │ └── send.php └── PubSub │ ├── composer.json │ ├── recieve.php │ └── send.php ├── Chapter 7 ├── assignmentsToParameters │ ├── After.php │ └── Before.php ├── extractMethod │ ├── after │ │ ├── Dice.php │ │ └── index.php │ └── before │ │ ├── LegacyDice.php │ │ └── index.php ├── indecentExposure │ ├── after │ │ └── Human.php │ └── before │ │ └── Human.php ├── primativeObsession │ ├── after │ │ ├── Employee.php │ │ └── Salary.php │ ├── before │ │ └── Salary.php │ └── repairedFeatureEnvy │ │ └── Employee.php └── switch │ ├── after.php │ └── before.php ├── README.md └── geocodedData.Rdata /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /Chapter 1/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "autoload": { 3 | "psr-4": { 4 | "IcyApril\\ChapterOne\\": "src/" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter 1/index.php: -------------------------------------------------------------------------------- 1 | new \IcyApril\ChapterOne\Cat(), 14 | 'oscar' => new \IcyApril\ChapterOne\Dog(), 15 | 'snowflake' => new \IcyApril\ChapterOne\Cat() 16 | ); 17 | 18 | foreach ($pets as $pet) { 19 | echo $pet->talk(false); 20 | $pet->walk(1); 21 | } -------------------------------------------------------------------------------- /Chapter 1/src/Animal.php: -------------------------------------------------------------------------------- 1 | 0) { 19 | return true; 20 | } else { 21 | return false; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Chapter 1/src/Book.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see http://www.php-fig.org/psr/psr-0/ 41 | * @see http://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | private $classMapAuthoritative = false; 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-4 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if ($file === null && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if ($file === null) { 337 | // Remember that this class does not exist. 338 | return $this->classMap[$class] = false; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * Scope isolated include. 407 | * 408 | * Prevents access to $this/self from included files. 409 | */ 410 | function includeFile($file) 411 | { 412 | include $file; 413 | } 414 | -------------------------------------------------------------------------------- /Chapter 1/vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2015 Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /Chapter 1/vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter 1/vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter 1/vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /Chapter 2/ApacheProxyPass/vhost.conf: -------------------------------------------------------------------------------- 1 | 2 | ServerName test.local 3 | DocumentRoot /var/www/html/ 4 | ProxyPass /api http://api.local 5 | ProxyPassReverse /api http://api.local 6 | -------------------------------------------------------------------------------- /Chapter 2/BlindFaith/HorrendouslyInsecure.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Chapter 3/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter 3/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter 3/.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter 3/.idea/phpBook3.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter 3/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 177 | 178 | 179 | 180 | 181 | true 182 | 183 | 184 | 185 | 186 | 187 | 188 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 224 | 225 | 226 | 227 | 230 | 231 | 234 | 235 | 238 | 239 | 240 | 241 | 244 | 245 | 248 | 249 | 252 | 253 | 254 | 255 | 258 | 259 | 262 | 263 | 264 | 265 | 268 | 269 | 272 | 273 | 276 | 277 | 278 | 279 | 282 | 283 | 286 | 287 | 290 | 291 | 292 | 293 | 296 | 297 | 300 | 301 | 304 | 305 | 306 | 307 | 310 | 311 | 314 | 315 | 318 | 319 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 1457306077665 413 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 447 | 450 | 451 | 452 | 454 | 455 | 456 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | -------------------------------------------------------------------------------- /Chapter 3/Abstract/SFToyFactory.php: -------------------------------------------------------------------------------- 1 | makeMaze()); 19 | echo "\n"; 20 | var_dump($sanFraciscoFactory->makePuzzle()); 21 | echo "\n"; 22 | 23 | require_once('UKToyFactory.php'); 24 | require_once('Toys/UKMazeToy.php'); 25 | require_once('Toys/UKPuzzleToy.php'); 26 | 27 | $britishToyFactory = new UKToyFactory(); 28 | var_dump($britishToyFactory->makeMaze()); 29 | echo "\n"; 30 | var_dump($britishToyFactory->makePuzzle()); 31 | echo "\n"; -------------------------------------------------------------------------------- /Chapter 3/Builder/Pizza.php: -------------------------------------------------------------------------------- 1 | size = $builder->size; 19 | $this->cheese = $builder->cheese; 20 | $this->pepperoni = $builder->pepperoni; 21 | $this->bacon = $builder->bacon; 22 | } 23 | 24 | public function show() 25 | { 26 | $recipe = $this->size . " inch pizza with the following toppings: "; 27 | $recipe .= $this->cheese ? "cheese, " : ""; 28 | $recipe .= $this->pepperoni ? "pepperoni, " : ""; 29 | $recipe .= $this->bacon ? "bacon, " : ""; 30 | 31 | return $recipe; 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Chapter 3/Builder/PizzaBuilder.php: -------------------------------------------------------------------------------- 1 | size = $size; 18 | } 19 | 20 | public function cheese(bool $present): PizzaBuilder 21 | { 22 | $this->cheese = $present; 23 | return $this; 24 | } 25 | 26 | public function pepperoni(bool $present): PizzaBuilder 27 | { 28 | $this->pepperoni = $present; 29 | return $this; 30 | } 31 | 32 | public function bacon(bool $present): PizzaBuilder 33 | { 34 | $this->bacon = $present; 35 | return $this; 36 | } 37 | 38 | public function build() 39 | { 40 | return $this; 41 | } 42 | } -------------------------------------------------------------------------------- /Chapter 3/Builder/index.php: -------------------------------------------------------------------------------- 1 | cheese(true) 13 | ->pepperoni(true) 14 | ->bacon(true) 15 | ->build(); 16 | 17 | 18 | $order = new Pizza($pizzaRecipe); 19 | echo $order->show(); -------------------------------------------------------------------------------- /Chapter 3/FactoryMethod/CourierNotifierFactory.php: -------------------------------------------------------------------------------- 1 | from = $from; 19 | } else { 20 | $this->from = "Anonymous"; 21 | } 22 | } 23 | 24 | public function validateTo(): bool 25 | { 26 | $isEmail = filter_var($this->to, FILTER_VALIDATE_EMAIL); 27 | 28 | return $isEmail ? true : false; 29 | 30 | } 31 | 32 | public function sendNotification(): string 33 | { 34 | if ($this->validateTo() === false) { 35 | throw new Exception("Invalid email address."); 36 | } 37 | 38 | $notificationType = get_class($this); 39 | return "This is a " . $notificationType . " to " . $this->to . " from " . $this->from . "."; 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter 3/FactoryMethod/Notifier.php: -------------------------------------------------------------------------------- 1 | to = $to; 15 | } 16 | 17 | abstract public function validateTo(): bool; 18 | 19 | abstract public function sendNotification(): string; 20 | 21 | } -------------------------------------------------------------------------------- /Chapter 3/FactoryMethod/NotifierFactory.php: -------------------------------------------------------------------------------- 1 | to); 13 | if (count($address) !== 2) { 14 | return false; 15 | } 16 | 17 | return true; 18 | } 19 | 20 | public function sendNotification(): string 21 | { 22 | 23 | if ($this->validateTo() === false) { 24 | throw new Exception("Invalid address."); 25 | } 26 | 27 | $notificationType = get_class($this); 28 | return "This is a " . $notificationType . " to " . $this->to . "."; 29 | } 30 | } -------------------------------------------------------------------------------- /Chapter 3/FactoryMethod/SMS.php: -------------------------------------------------------------------------------- 1 | to); 14 | 15 | return $isPhone ? true : false; 16 | 17 | } 18 | 19 | public function sendNotification(): string 20 | { 21 | 22 | if ($this->validateTo() === false) { 23 | throw new Exception("Invalid phone number."); 24 | } 25 | 26 | $notificationType = get_class($this); 27 | return "This is a " . $notificationType . " to " . $this->to . "."; 28 | } 29 | } -------------------------------------------------------------------------------- /Chapter 3/FactoryMethod/index.php: -------------------------------------------------------------------------------- 1 | sendNotification(); 15 | 16 | echo "\n"; 17 | 18 | require_once('Email.php'); 19 | $email = ElectronicNotifierFactory::getNotifier("Email", "test@example.com"); 20 | echo $email->sendNotification(); 21 | 22 | echo "\n"; 23 | 24 | require_once('CourierNotifierFactory.php'); 25 | 26 | require_once('Post.php'); 27 | $post = CourierNotifierFactory::getNotifier("Post", "10 Downing Street, SW1A 2AA"); 28 | echo $post->sendNotification(); -------------------------------------------------------------------------------- /Chapter 3/LazyLoader/Burger.php: -------------------------------------------------------------------------------- 1 | cheese = $cheese; 17 | $this->chips = $chips; 18 | 19 | $this->price = rand(1, 2.50) + ($cheese ? 0.5 : 0) + ($chips ? 1 : 0); 20 | } 21 | 22 | public function getPrice(): int 23 | { 24 | return $this->price; 25 | } 26 | } -------------------------------------------------------------------------------- /Chapter 3/LazyLoader/BurgerLazyLoader.php: -------------------------------------------------------------------------------- 1 | getPrice(); 13 | 14 | echo "\n"; 15 | echo "Instances in lazy loader: ".BurgerLazyLoader::getBurgerCount(); 16 | echo "\n"; 17 | 18 | $burger = BurgerLazyLoader::getBurger(true, false); 19 | echo "Burger with cheese and no fries costs: £".$burger->getPrice(); 20 | 21 | echo "\n"; 22 | echo "Instances in lazy loader: ".BurgerLazyLoader::getBurgerCount(); 23 | echo "\n"; 24 | 25 | $burger = BurgerLazyLoader::getBurger(true, true); 26 | echo "Burger with cheese and fries costs: £".$burger->getPrice(); 27 | 28 | echo "\n"; 29 | echo "Instances in lazy loader: ".BurgerLazyLoader::getBurgerCount(); 30 | echo "\n"; -------------------------------------------------------------------------------- /Chapter 3/Prototype/Student.php: -------------------------------------------------------------------------------- 1 | name = $name; 18 | } 19 | 20 | public function setYear(int $year) 21 | { 22 | $this->year = $year; 23 | } 24 | 25 | public function setGrade(string $grade) 26 | { 27 | $this->grade = $grade; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /Chapter 3/Prototype/index.php: -------------------------------------------------------------------------------- 1 | setName('Dave'); 13 | $prototypeStudent->setYear(2); 14 | $prototypeStudent->setGrade('A*'); 15 | 16 | var_dump($prototypeStudent); 17 | 18 | $theLesserChild = clone $prototypeStudent; 19 | $theLesserChild->setName('Mike'); 20 | $theLesserChild->setGrade('B'); 21 | 22 | var_dump($theLesserChild); 23 | 24 | $theChildProdigy = clone $prototypeStudent; 25 | $theChildProdigy->setName('Bob'); 26 | $theChildProdigy->setYear(3); 27 | $theChildProdigy->setGrade('A'); 28 | 29 | $theChildProdigy->danceSkills = "Outstanding"; 30 | $theChildProdigy->dance = function (string $style) { 31 | return "Dancing $style style."; 32 | }; 33 | 34 | var_dump($theChildProdigy); 35 | var_dump($theChildProdigy->dance->__invoke('Pogo')); 36 | -------------------------------------------------------------------------------- /Chapter 3/SimpleFactory/Email.php: -------------------------------------------------------------------------------- 1 | from = $from; 19 | } else { 20 | $this->from = "Anonymous"; 21 | } 22 | } 23 | 24 | public function validateTo(): bool 25 | { 26 | $isEmail = filter_var($this->to, FILTER_VALIDATE_EMAIL); 27 | 28 | return $isEmail ? true : false; 29 | 30 | } 31 | 32 | public function sendNotification(): string 33 | { 34 | if ($this->validateTo() === false) { 35 | throw new Exception("Invalid email address."); 36 | } 37 | 38 | $notificationType = get_class($this); 39 | return "This is a " . $notificationType . " to " . $this->to . " from " . $this->from . "."; 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter 3/SimpleFactory/Notifier.php: -------------------------------------------------------------------------------- 1 | to = $to; 15 | } 16 | 17 | abstract public function validateTo(): bool; 18 | 19 | abstract public function sendNotification(): string; 20 | 21 | } -------------------------------------------------------------------------------- /Chapter 3/SimpleFactory/NotifierFactory.php: -------------------------------------------------------------------------------- 1 | to); 14 | 15 | return $isPhone ? true : false; 16 | 17 | } 18 | 19 | public function sendNotification(): string 20 | { 21 | 22 | if ($this->validateTo() === false) { 23 | throw new Exception("Invalid phone number."); 24 | } 25 | 26 | $notificationType = get_class($this); 27 | return "This is a " . $notificationType . " to " . $this->to . "."; 28 | } 29 | } -------------------------------------------------------------------------------- /Chapter 3/SimpleFactory/index.php: -------------------------------------------------------------------------------- 1 | sendNotification(); 14 | 15 | echo "\n"; 16 | 17 | require_once('Email.php'); 18 | $email = NotifierFactory::getNotifier("Email", "test@example.com"); 19 | echo $email->sendNotification(); -------------------------------------------------------------------------------- /Chapter 4/.idea/.name: -------------------------------------------------------------------------------- 1 | phpBook4 -------------------------------------------------------------------------------- /Chapter 4/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Chapter 4/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter 4/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter 4/.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter 4/.idea/phpBook4.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter 4/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 89 | 90 | 91 | 92 | 93 | true 94 | 95 | 96 | 97 | 98 | 99 | 100 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 137 | 138 | 139 | 140 | 143 | 144 | 147 | 148 | 149 | 150 | 153 | 154 | 157 | 158 | 161 | 162 | 163 | 164 | 167 | 168 | 171 | 172 | 175 | 176 | 177 | 178 | 181 | 182 | 185 | 186 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 1458844602848 276 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 315 | 318 | 319 | 320 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | -------------------------------------------------------------------------------- /Chapter 4/Bridge/Device.php: -------------------------------------------------------------------------------- 1 | sender = $sender; 15 | } 16 | } -------------------------------------------------------------------------------- /Chapter 4/Bridge/InstantMessenger.php: -------------------------------------------------------------------------------- 1 | sender->send($body); 15 | } 16 | } -------------------------------------------------------------------------------- /Chapter 4/Bridge/SMS.php: -------------------------------------------------------------------------------- 1 | sender->send($body); 15 | } 16 | } -------------------------------------------------------------------------------- /Chapter 4/Bridge/Transmitter.php: -------------------------------------------------------------------------------- 1 | setSender(new SMS()); 23 | 24 | $phone->send("Hello there!"); -------------------------------------------------------------------------------- /Chapter 4/ClassAdapter/ATM.php: -------------------------------------------------------------------------------- 1 | balance = $balance; 15 | } 16 | 17 | public function withdraw(float $amount): float 18 | { 19 | if ($this->reduceBalance($amount) === true) { 20 | return $amount; 21 | } else { 22 | throw new Exception("Couldn't withdraw money."); 23 | } 24 | } 25 | 26 | protected function reduceBalance(float $amount): bool 27 | { 28 | if ($amount >= $this->balance) { 29 | return false; 30 | } 31 | 32 | $this->balance = ($this->balance - $amount); 33 | return true; 34 | } 35 | 36 | public function getBalance(): float 37 | { 38 | return $this->balance; 39 | } 40 | } -------------------------------------------------------------------------------- /Chapter 4/ClassAdapter/ATMWithPhoneTopUp.php: -------------------------------------------------------------------------------- 1 | reduceBalance($amount) === true) { 13 | return $this->generateTopUpCode($amount, $time); 14 | } else { 15 | throw new Exception("Couldn't withdraw money."); 16 | } 17 | } 18 | 19 | private function generateTopUpCode(float $amount, int $time): string 20 | { 21 | return $amount . $time . rand(0, 10000); 22 | } 23 | } -------------------------------------------------------------------------------- /Chapter 4/ClassAdapter/index.php: -------------------------------------------------------------------------------- 1 | withdraw(50); 12 | echo $atm->getBalance(); 13 | echo "\n"; 14 | 15 | require_once('ATMWithPhoneTopUp.php'); 16 | 17 | $adaptedATM = new ATMWithPhoneTopUp(500.00); 18 | echo "Top-up code: " . $adaptedATM->getTopUp(50, time()); 19 | echo "\n"; 20 | echo $adaptedATM->getBalance(); -------------------------------------------------------------------------------- /Chapter 4/Composite/Music.php: -------------------------------------------------------------------------------- 1 | songs[spl_object_hash($content)] = $content; 16 | return true; 17 | } 18 | 19 | public function removeItem(Music $content): bool 20 | { 21 | unset($this->songs[spl_object_hash($content)]); 22 | return true; 23 | } 24 | 25 | public function play() 26 | { 27 | foreach ($this->songs as $content) { 28 | $content->play(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 4/Composite/Song.php: -------------------------------------------------------------------------------- 1 | id = uniqid(); 17 | $this->name = $name; 18 | } 19 | 20 | public function play() 21 | { 22 | printf("Playing song #%s, %s.\n", $this->id, $this->name); 23 | } 24 | } -------------------------------------------------------------------------------- /Chapter 4/Composite/index.php: -------------------------------------------------------------------------------- 1 | addSong($songOne); 19 | $playlistTwo->addSong($songTwo); 20 | $playlistThree->addSong($songThree); 21 | $playlistOne->addSong($playlistTwo); 22 | $playlistOne->addSong($playlistThree); 23 | $playlistOne->play(); 24 | -------------------------------------------------------------------------------- /Chapter 4/Decorator/Book.php: -------------------------------------------------------------------------------- 1 | title = $title; 18 | $this->author = $author; 19 | $this->contents = $contents; 20 | } 21 | 22 | public function getTitle(): string 23 | { 24 | return $this->contents; 25 | } 26 | 27 | public function getAuthor(): string 28 | { 29 | return $this->author; 30 | } 31 | 32 | public function getContents(): string 33 | { 34 | return $this->contents; 35 | } 36 | } -------------------------------------------------------------------------------- /Chapter 4/Decorator/PrintBook.php: -------------------------------------------------------------------------------- 1 | eBook = new EBook($title, $author, $contents); 16 | } 17 | 18 | public function getTitle(): string 19 | { 20 | return $this->eBook->getTitle(); 21 | } 22 | 23 | public function getAuthor(): string 24 | { 25 | return $this->eBook->getAuthor(); 26 | } 27 | 28 | public function getContents(): string 29 | { 30 | return $this->eBook->getContents(); 31 | } 32 | 33 | public function getText(): string 34 | { 35 | $contents = $this->eBook->getTitle() . " by " . $this->eBook->getAuthor(); 36 | $contents .= "\n"; 37 | $contents .= $this->eBook->getContents(); 38 | 39 | return $contents; 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter 4/Decorator/index.php: -------------------------------------------------------------------------------- 1 | getText(); -------------------------------------------------------------------------------- /Chapter 4/Flyweight/Circle.php: -------------------------------------------------------------------------------- 1 | colour = $colour; 19 | } 20 | 21 | public function setX(int $x) 22 | { 23 | $this->x = $x; 24 | } 25 | 26 | public function setY(int $y) 27 | { 28 | $this->y = $y; 29 | } 30 | 31 | public function setRadius(int $radius) 32 | { 33 | $this->radius = $radius; 34 | } 35 | 36 | public function draw() 37 | { 38 | echo "Drawing circle which is " . $this->colour . " at [" . $this->x . ", " . $this->y . "] of radius " . $this->radius . "."; 39 | echo "\n"; 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter 4/Flyweight/Shape.php: -------------------------------------------------------------------------------- 1 | shapeMap[$circle])) { 17 | echo "Creating a ".$colour." circle."; 18 | echo "\n"; 19 | $this->shapeMap[$circle] = new Circle($colour); 20 | } 21 | 22 | return $this->shapeMap[$circle]; 23 | } 24 | } -------------------------------------------------------------------------------- /Chapter 4/Flyweight/index.php: -------------------------------------------------------------------------------- 1 | getCircle($randomColour); 20 | $circle->setX(rand(0, 100)); 21 | $circle->setY(rand(0, 100)); 22 | $circle->setRadius(100); 23 | 24 | $circle->draw(); 25 | } -------------------------------------------------------------------------------- /Chapter 4/ObjectAdapter/Insurance.php: -------------------------------------------------------------------------------- 1 | = $limit) { 16 | throw New Exception('Excess must be less than premium.'); 17 | } 18 | 19 | $this->limit = $limit; 20 | $this->excess = $excess; 21 | } 22 | 23 | public function monthlyPremium(): float 24 | { 25 | return ($this->limit-$this->excess)/200; 26 | } 27 | 28 | public function annualPremium(): float 29 | { 30 | return $this->monthlyPremium()*11.5; 31 | } 32 | } -------------------------------------------------------------------------------- /Chapter 4/ObjectAdapter/InsuranceMarketCompare.php: -------------------------------------------------------------------------------- 1 | premium = new Insurance($limit, $excess); 15 | } 16 | 17 | public function getAnnualPremium(): float 18 | { 19 | return $this->premium->annualPremium(); 20 | } 21 | 22 | public function getMonthlyPremium(): float 23 | { 24 | return $this->premium->monthlyPremium(); 25 | } 26 | } -------------------------------------------------------------------------------- /Chapter 4/ObjectAdapter/MarketCompare.php: -------------------------------------------------------------------------------- 1 | monthlyPremium(); 12 | echo "\n"; 13 | 14 | require_once('MarketCompare.php'); 15 | require_once('InsuranceMarketCompare.php'); 16 | 17 | $quote = new InsuranceMarketCompare(10000, 250); 18 | echo $quote->getMonthlyPremium(); 19 | echo "\n"; 20 | echo $quote->getAnnualPremium(); -------------------------------------------------------------------------------- /Chapter 4/Proxy/AnimalFeeder.php: -------------------------------------------------------------------------------- 1 | instance = new $class($name); 19 | } 20 | 21 | public function __call($name, $arguments) 22 | { 23 | return call_user_func_array([$this->instance, $name], $arguments); 24 | } 25 | } -------------------------------------------------------------------------------- /Chapter 4/Proxy/AnimalFeeders/Cat.php: -------------------------------------------------------------------------------- 1 | petName = $petName; 18 | } 19 | 20 | public function dropFood(int $hungerLevel, bool $water = false): string 21 | { 22 | return $this->selectFood($hungerLevel) . ($water ? ' with water' : ''); 23 | } 24 | 25 | public function displayFood(int $hungerLevel): string 26 | { 27 | return $this->selectFood($hungerLevel); 28 | } 29 | 30 | protected function selectFood(int $hungerLevel): string 31 | { 32 | switch ($hungerLevel) { 33 | case 0: 34 | return 'lamb'; 35 | break; 36 | case 1: 37 | return 'chicken'; 38 | break; 39 | case 3: 40 | return 'tuna'; 41 | break; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Chapter 4/Proxy/AnimalFeeders/Dog.php: -------------------------------------------------------------------------------- 1 | 10) { 17 | throw new \Exception('Name too long.'); 18 | } 19 | 20 | $this->petName = $petName; 21 | } 22 | 23 | public function dropFood(int $hungerLevel, bool $water = false): string 24 | { 25 | return $this->selectFood($hungerLevel) . ($water ? ' with water' : ''); 26 | } 27 | 28 | public function displayFood(int $hungerLevel): string 29 | { 30 | return $this->selectFood($hungerLevel); 31 | } 32 | 33 | protected function selectFood(int $hungerLevel): string 34 | { 35 | if ($hungerLevel == 3) { 36 | return "chicken and vegetables"; 37 | } elseif (date('H') < 10) { 38 | return "turkey and beef"; 39 | } else { 40 | return "chicken and rice"; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Chapter 4/Proxy/index.php: -------------------------------------------------------------------------------- 1 | displayFood(1); 15 | echo "\n"; 16 | echo $felix->dropFood(1, true); 17 | echo "\n"; 18 | 19 | require_once('AnimalFeeders/Dog.php'); 20 | $brian = new \IcyApril\PetShop\AnimalFeederProxy('Dog', 'Brian'); 21 | echo $brian->displayFood(1); 22 | echo "\n"; 23 | echo $brian->dropFood(1, true); -------------------------------------------------------------------------------- /Chapter 5/ChainOfResponsibility/AssociatePurchaser.php: -------------------------------------------------------------------------------- 1 | nextPurchaser = $nextPurchaser; 14 | return true; 15 | } 16 | 17 | public function buy($price): bool 18 | { 19 | if ($price < 100) { 20 | var_dump("Associate purchased"); 21 | return true; 22 | } else { 23 | if (isset($this->nextPurchaser)) { 24 | return $this->nextPurchaser->buy($price); 25 | } else { 26 | var_dump("Could not buy"); 27 | return false; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 5/ChainOfResponsibility/BoardPurchaser.php: -------------------------------------------------------------------------------- 1 | nextPurchaser = $nextPurchaser; 14 | return true; 15 | } 16 | 17 | public function buy($price): bool 18 | { 19 | if ($price < 100000) { 20 | var_dump("Board purchased"); 21 | return true; 22 | } else { 23 | if (isset($this->nextPurchaser)) { 24 | return $this->nextPurchaser->buy($price); 25 | } else { 26 | var_dump("Could not buy"); 27 | return false; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 5/ChainOfResponsibility/DirectorPurchaser.php: -------------------------------------------------------------------------------- 1 | nextPurchaser = $nextPurchaser; 14 | return true; 15 | } 16 | 17 | public function buy($price): bool 18 | { 19 | if ($price < 10000) { 20 | var_dump("Director purchased"); 21 | return true; 22 | } else { 23 | if (isset($this->nextPurchaser)) { 24 | return $this->nextPurchaser->buy($price); 25 | } else { 26 | var_dump("Could not buy"); 27 | return false; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 5/ChainOfResponsibility/ManagerPurchaser.php: -------------------------------------------------------------------------------- 1 | nextPurchaser = $nextPurchaser; 14 | return true; 15 | } 16 | 17 | public function buy($price): bool 18 | { 19 | if ($price < 500) { 20 | var_dump("Manager purchased"); 21 | return true; 22 | } else { 23 | if (isset($this->nextPurchaser)) { 24 | return $this->nextPurchaser->buy($price); 25 | } else { 26 | var_dump("Could not buy"); 27 | return false; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter 5/ChainOfResponsibility/Purchaser.php: -------------------------------------------------------------------------------- 1 | setNextPurchaser($manager); 21 | $manager->setNextPurchaser($director); 22 | $director->setNextPurchaser($board); 23 | 24 | $associate->buy(11000); -------------------------------------------------------------------------------- /Chapter 5/Generator/index.php: -------------------------------------------------------------------------------- 1 | pow($i, 2); 12 | } 13 | } 14 | 15 | foreach (squaredNumbers(1, 5) as $key => $number) { 16 | var_dump([$key, $number]); 17 | } -------------------------------------------------------------------------------- /Chapter 5/Iterator/index.php: -------------------------------------------------------------------------------- 1 | position = 0; 20 | } 21 | 22 | function rewind() 23 | { 24 | var_dump(__METHOD__); 25 | $this->position = 0; 26 | } 27 | 28 | function current() 29 | { 30 | var_dump(__METHOD__); 31 | 32 | return $this->array[$this->position]; 33 | } 34 | 35 | function key() 36 | { 37 | var_dump(__METHOD__); 38 | 39 | return $this->position; 40 | } 41 | 42 | function next() 43 | { 44 | var_dump(__METHOD__); 45 | ++$this->position; 46 | } 47 | 48 | function valid() 49 | { 50 | var_dump(__METHOD__); 51 | 52 | return isset($this->array[$this->position]); 53 | } 54 | } 55 | 56 | $it = new myIterator; 57 | 58 | foreach ($it as $key => $value) { 59 | var_dump($key, $value); 60 | echo "\n"; 61 | } -------------------------------------------------------------------------------- /Chapter 5/Iterator/time.php: -------------------------------------------------------------------------------- 1 | weekAgo = $time - 604800; 15 | $this->yesterday = $time - 86400; 16 | $this->now = $time; 17 | $this->tomorrow = $time + 86400; 18 | $this->nextWeek = $time + 604800; 19 | } 20 | 21 | public function getIterator() 22 | { 23 | return new ArrayIterator($this); 24 | } 25 | } 26 | 27 | $time = new timeIterator(time()); 28 | 29 | foreach ($time as $key => $value) { 30 | var_dump($key, $value); 31 | echo "\n"; 32 | } -------------------------------------------------------------------------------- /Chapter 5/Observer/Feed.php: -------------------------------------------------------------------------------- 1 | name = $name; 21 | } 22 | 23 | /** 24 | * Add observer to Feed. 25 | * @param SplObserver $observer 26 | * @return null 27 | */ 28 | public function attach(SplObserver $observer) 29 | { 30 | $observerHash = spl_object_hash($observer); 31 | $this->observers[$observerHash] = $observer; 32 | } 33 | 34 | /** 35 | * Detach observer from Feed. 36 | * @param SplObserver $observer 37 | */ 38 | public function detach(SplObserver $observer) 39 | { 40 | $observerHash = spl_object_hash($observer); 41 | unset($this->observers[$observerHash]); 42 | } 43 | 44 | /** 45 | * Send a news alert and then run the notify method. 46 | * @param $content 47 | */ 48 | public function breakOutNews($content) 49 | { 50 | $this->content = $content; 51 | $this->notify(); 52 | } 53 | 54 | /** 55 | * Get contents of the feed. 56 | * @return string 57 | */ 58 | public function getContent() 59 | { 60 | return $this->content . " on ". $this->name . "."; 61 | } 62 | 63 | /** 64 | * Iterate through observers and run their update methods. 65 | */ 66 | public function notify() 67 | { 68 | foreach ($this->observers as $value) { 69 | $value->update($this); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Chapter 5/Observer/Reader.php: -------------------------------------------------------------------------------- 1 | name = $name; 15 | } 16 | 17 | public function update(\SplSubject $subject) 18 | { 19 | echo $this->name . ' is reading the article ' . $subject->getContent() . ' '; 20 | } 21 | } -------------------------------------------------------------------------------- /Chapter 5/Observer/index.php: -------------------------------------------------------------------------------- 1 | attach($allen); 19 | $newspaper->attach($jim); 20 | $newspaper->attach($linda); 21 | 22 | //remove reader 23 | $newspaper->detach($linda); 24 | 25 | //set break outs 26 | $newspaper->breakOutNews('PHP Design Patterns'); -------------------------------------------------------------------------------- /Chapter 5/Specification/EmployeeIsEngineer.php: -------------------------------------------------------------------------------- 1 | department === "Engineering") { 14 | return true; 15 | } 16 | 17 | return false; 18 | } 19 | } -------------------------------------------------------------------------------- /Chapter 5/Specification/EmployeeSpecification.php: -------------------------------------------------------------------------------- 1 | title = "Developer"; 16 | $workers['A']->department = "Engineering"; 17 | $workers['A']->salary = 50000; 18 | 19 | $workers['B'] = new StdClass(); 20 | $workers['B']->title = "Data Analyst"; 21 | $workers['B']->department = "Engineering"; 22 | $workers['B']->salary = 30000; 23 | 24 | $workers['C'] = new StdClass(); 25 | $workers['C']->title = "Personal Assistant"; 26 | $workers['C']->department = "CEO"; 27 | $workers['C']->salary = 25000; 28 | 29 | $isEngineer = new EmployeeIsEngineer(); 30 | 31 | foreach ($workers as $id => $worker) { 32 | if ($isEngineer->isSatisfiedBy($worker)) { 33 | var_dump($id); 34 | } 35 | } -------------------------------------------------------------------------------- /Chapter 5/Strategy/Cube.php: -------------------------------------------------------------------------------- 1 | strategy = $strategy; 14 | } 15 | 16 | public function raise(int $number) 17 | { 18 | return $this->strategy->raise($number); 19 | } 20 | } -------------------------------------------------------------------------------- /Chapter 5/Strategy/Square.php: -------------------------------------------------------------------------------- 1 | raise($number)); -------------------------------------------------------------------------------- /Chapter 5/Template/MeatballPasta.php: -------------------------------------------------------------------------------- 1 | cheese = $cheese; 14 | } 15 | 16 | public function cook() 17 | { 18 | 19 | var_dump('Cooked pasta.'); 20 | 21 | $this->boilPasta(); 22 | $this->addSauce(); 23 | $this->addMeat(); 24 | 25 | if ($this->cheese) { 26 | $this->addCheese(); 27 | } 28 | } 29 | 30 | public function boilPasta(): bool 31 | { 32 | return true; 33 | } 34 | 35 | 36 | public abstract function addSauce(): bool; 37 | 38 | public abstract function addMeat(): bool; 39 | 40 | public abstract function addCheese(): bool; 41 | 42 | } -------------------------------------------------------------------------------- /Chapter 5/Template/VeganPasta.php: -------------------------------------------------------------------------------- 1 | cook(); 15 | 16 | var_dump(""); 17 | var_dump("Vegan pasta"); 18 | require_once('VeganPasta.php'); 19 | 20 | $dish = new VeganPasta(true); 21 | $dish->cook(); -------------------------------------------------------------------------------- /Chapter 6/GettingStarted/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php-amqplib/php-amqplib": "2.5.*" 4 | } 5 | } -------------------------------------------------------------------------------- /Chapter 6/GettingStarted/recieve.php: -------------------------------------------------------------------------------- 1 | channel(); 15 | 16 | $channel->queue_declare( 17 | 'sayHello', // queue name 18 | false, // passive 19 | false, // durable 20 | false, // exclusive 21 | false // autodelete 22 | ); 23 | 24 | $callback = function ($msg) { 25 | echo "Received: " . $msg->body . PHP_EOL; 26 | }; 27 | 28 | $channel->basic_consume( 29 | 'sayHello', // queue 30 | '', // consumer tag 31 | false, // no local 32 | true, // no ack 33 | false, // exclusive 34 | false, // no wait 35 | $callback // callback 36 | ); 37 | 38 | while (count($channel->callbacks)) { 39 | $channel->wait(); 40 | } -------------------------------------------------------------------------------- /Chapter 6/GettingStarted/send.php: -------------------------------------------------------------------------------- 1 | channel(); 15 | 16 | $channel->queue_declare( 17 | 'sayHello', // queue name 18 | false, // passive 19 | true, // durable 20 | false, // exclusive 21 | false // autodelete 22 | ); 23 | 24 | $msg = new AMQPMessage("Hello world!"); 25 | 26 | $channel->basic_publish( 27 | $msg, // message 28 | '', // exchange 29 | 'sayHello' // routing key 30 | ); 31 | 32 | $channel->close(); 33 | $connection->close(); 34 | 35 | echo "Sent hello world message." . PHP_EOL; -------------------------------------------------------------------------------- /Chapter 6/PubSub/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php-amqplib/php-amqplib": "2.5.*" 4 | } 5 | } -------------------------------------------------------------------------------- /Chapter 6/PubSub/recieve.php: -------------------------------------------------------------------------------- 1 | channel(); 15 | 16 | $channel->exchange_declare( 17 | 'helloHello', // exchange 18 | 'fanout', // exchange type 19 | false, // passive 20 | false, // durable 21 | false // auto-delete 22 | ); 23 | 24 | $callback = function ($msg) { 25 | echo "Received: " . $msg->body . PHP_EOL; 26 | }; 27 | 28 | list($queueName, ,) = $channel->queue_declare("", false, false, true, false); 29 | 30 | $channel->queue_bind($queueName, 'helloHello'); 31 | 32 | $channel->basic_consume($queueName, '', false, true, false, false, $callback); 33 | 34 | while (count($channel->callbacks)) { 35 | $channel->wait(); 36 | } 37 | 38 | $channel->close(); 39 | $connection->close(); -------------------------------------------------------------------------------- /Chapter 6/PubSub/send.php: -------------------------------------------------------------------------------- 1 | channel(); 15 | 16 | $channel->exchange_declare( 17 | 'helloHello', // exchange 18 | 'fanout', // exchange type 19 | false, // passive 20 | false, // durable 21 | false // auto-delete 22 | ); 23 | 24 | $msg = new AMQPMessage("Hello world!"); 25 | 26 | $channel->basic_publish( 27 | $msg, // message 28 | 'helloHello' // exchange 29 | ); 30 | 31 | $channel->close(); 32 | $connection->close(); 33 | 34 | echo "Sent hello world message." . PHP_EOL; -------------------------------------------------------------------------------- /Chapter 7/assignmentsToParameters/After.php: -------------------------------------------------------------------------------- 1 | numberToRomanNumeral($rand); 20 | } 21 | 22 | /** 23 | * Convert a number between 1 and 6 to a Roman Numeral. 24 | * 25 | * @param int $number 26 | * 27 | * @return string 28 | * @throws Exception 29 | */ 30 | public function numberToRomanNumeral(int $number): string 31 | { 32 | if (($number < 1) || ($number > 6)) { 33 | throw new Exception('Number out of range.'); 34 | } 35 | 36 | switch ($number) { 37 | case 5: 38 | $randString = "V"; 39 | break; 40 | case 6: 41 | $randString = "VI"; 42 | break; 43 | default: 44 | $randString = str_repeat("I", $number); 45 | break; 46 | } 47 | 48 | return $randString; 49 | } 50 | } -------------------------------------------------------------------------------- /Chapter 7/extractMethod/after/index.php: -------------------------------------------------------------------------------- 1 | roll()); -------------------------------------------------------------------------------- /Chapter 7/extractMethod/before/LegacyDice.php: -------------------------------------------------------------------------------- 1 | roll()); -------------------------------------------------------------------------------- /Chapter 7/indecentExposure/after/Human.php: -------------------------------------------------------------------------------- 1 | name = $name; 19 | $this->dateOfBirth = $dateOfBirth; 20 | } 21 | 22 | public function setWeight(double $weight) 23 | { 24 | $this->weight = $weight; 25 | } 26 | 27 | public function getWeight(): double 28 | { 29 | return $this->weight; 30 | } 31 | 32 | public function setHeight(double $height) 33 | { 34 | $this->height = $height; 35 | } 36 | 37 | public function getHeight(): double 38 | { 39 | return $this->height; 40 | } 41 | } -------------------------------------------------------------------------------- /Chapter 7/indecentExposure/before/Human.php: -------------------------------------------------------------------------------- 1 | name = $name; 19 | $this->baseSalary = $baseSalary; 20 | } 21 | 22 | public function getBaseSalary(): float 23 | { 24 | return $this->baseSalary; 25 | } 26 | 27 | public function setCommission(float $percentage) 28 | { 29 | $this->commission = $percentage; 30 | } 31 | 32 | public function getCommission(): float 33 | { 34 | return $this->commission; 35 | } 36 | 37 | public function setPension(float $rate) 38 | { 39 | $this->pension = $rate; 40 | } 41 | 42 | public function getPension(): float 43 | { 44 | return $this->commission; 45 | } 46 | } -------------------------------------------------------------------------------- /Chapter 7/primativeObsession/after/Salary.php: -------------------------------------------------------------------------------- 1 | employee = $employee; 16 | } 17 | 18 | public function calculate(float $sales): float 19 | { 20 | $base = $this->employee->getBaseSalary(); 21 | $commission = $this->employee->getCommission() * $sales; 22 | $deducation = $base * $this->employee->getPension(); 23 | 24 | return $commission + $base - $deducation; 25 | } 26 | } -------------------------------------------------------------------------------- /Chapter 7/primativeObsession/before/Salary.php: -------------------------------------------------------------------------------- 1 | baseSalary = $baseSalary; 18 | $this->commission = $commission; 19 | $this->pension = $pension; 20 | } 21 | 22 | public function calculate(float $sales): float 23 | { 24 | $base = $this->baseSalary; 25 | $commission = $this->commission * $sales; 26 | $deducation = $base * $this->pension; 27 | 28 | return $commission + $base - $deducation; 29 | } 30 | } -------------------------------------------------------------------------------- /Chapter 7/primativeObsession/repairedFeatureEnvy/Employee.php: -------------------------------------------------------------------------------- 1 | name = $name; 19 | $this->baseSalary = $baseSalary; 20 | } 21 | 22 | public function setCommission(float $percentage) 23 | { 24 | $this->commission = $percentage; 25 | } 26 | 27 | public function setPension(float $rate) 28 | { 29 | $this->pension = $rate; 30 | } 31 | 32 | public function calculate(float $sales): float 33 | { 34 | $base = $this->baseSalary; 35 | $commission = $this->commission * $sales; 36 | $deducation = $base * $this->pension; 37 | 38 | return $commission + $base - $deducation; 39 | } 40 | } -------------------------------------------------------------------------------- /Chapter 7/switch/after.php: -------------------------------------------------------------------------------- 1 | output = $outputType; 45 | } 46 | 47 | public function loadOutput(array $data) 48 | { 49 | return $this->output->load($data); 50 | } 51 | } 52 | 53 | $client = new OutputClient(new JSON()); 54 | echo $client->loadOutput(array(1, 2)); 55 | -------------------------------------------------------------------------------- /Chapter 7/switch/before.php: -------------------------------------------------------------------------------- 1 | load(array(1, 2)); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Mastering PHP Design Patterns 5 | 6 | Mastering PHP Design Patterns by Packt. It contains all the supporting project 7 | files necessary to work through the book from start to finish. 8 | 9 | ## Instructions and Navigation 10 | 11 | This is the code repository for [Mastering PHP Design Patterns][m-php-dp], published by Packt. 12 | There is no additional code files for the last Chapter (How to Write Better Code) as it covers mostly the best practices with no need of additional code files 13 | 14 | ## Description 15 | 16 | Mastering PHP Design Patterns goes beyond traditional design patterns as envisaged by the Gang of Four and details the practices that passionate PHP developers need to be successful as software engineers or leads on detailed PHP projects. 17 | This book will introduce you to the core knowledge required to understand project management techniques, why the majority software development projects fail, and why you can make yours a success. 18 | All of the code is organized into folders chapter-wise. The code will look like the following: 19 | ``` 20 | require_once('vendor/autoload.php'); 21 | new \IcyApril\ChapterOne\Book(); 22 | $pets = array( 23 | 'felix' => new \IcyApril\ChapterOne\Cat(), 24 | 'oscar' => new \IcyApril\ChapterOne\Dog(), 25 | 'snowflake' => new \IcyApril\ChapterOne\Cat() 26 | ); 27 | foreach ($pets as $pet) { 28 | echo $pet->talk(false); 29 | $pet->walk(1); 30 | } 31 | ``` 32 | 33 | ## Related PHP/Design Patterns Products: 34 | 35 | - [TypeScript Design Patterns][typescript-design-patterns] 36 | - [PHP Team Development][php-team-development] 37 | - [Learning PHP 7][learning-php7] 38 | 39 | [m-php-dp]: https://www.packtpub.com/application-development/mastering-php-design-patterns?utm_source=github&utm_medium=repository&utm_campaign=9781785880544 40 | [typescript-design-patterns]: https://www.packtpub.com/application-development/typescript-design-patterns?utm_source=github&utm_medium=repository&utm_campaign=9781785280832 41 | [typescript-design-patterns]: https://www.packtpub.com/application-development/typescript-design-patterns?utm_source=github&utm_medium=repository&utm_campaign=9781785280832 42 | [php-team-development]: https://www.packtpub.com/web-development/php-team-development?utm_source=github&utm_medium=repository&utm_campaign=9781785880544 43 | [learning-php7]: https://www.packtpub.com/application-development/learning-php-7?utm_source=github&utm_medium=repository&utm_campaign=9781785880544 44 | ### Download a free PDF 45 | 46 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
47 |

https://packt.link/free-ebook/9781785887130

-------------------------------------------------------------------------------- /geocodedData.Rdata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Mastering-PHP-Design-Patterns/9d2aa52de9a02c1deae04b9e6e75da531a0d2adf/geocodedData.Rdata --------------------------------------------------------------------------------