Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP für Fortgeschrittene

Avatar for Oliver Klee Oliver Klee
September 06, 2018

PHP für Fortgeschrittene

Avatar for Oliver Klee

Oliver Klee

September 06, 2018
Tweet

More Decks by Oliver Klee

Other Decks in Technology

Transcript

  1. composer.json "autoload": { "psr-4": { "OliverKlee\\GeosShop\\": "Classes/" } }, „autoload-dev“:

    { "psr-4": { „OliverKlee\\GeosShop\\Tests\\“: „Tests/" } } \OliverKlee\GeosShop\Domain\Model\Product Classes/Domain/Model/Product.php \OliverKlee\GeosShop\Tests\Unit\Domain\Model\ProductTest Tests/Unit/Domain/Model/ProductTest.php
  2. Antipattern: Early Returns public static function cmpIP($baseIP, $list) { $list

    = trim($list); if ($list === '') { return false; } if ($list === '*') { return true; } if (strpos($baseIP, ':') !== false && self::validIPv6($baseIP)) { return self::cmpIPv6($baseIP, $list); } return self::cmpIPv4($baseIP, $list); }
  3. public static function getUrl($url, $includeHeader = 0, $requestHeaders = null,

    &$report = null) { if (isset($report)) { $report['error'] = 0; $report['message'] = ''; } // Looks like it's an external file, use Guzzle by default if (preg_match('/^(?:http|ftp)s?|s(?:ftp|cp):/', $url)) { /** @var RequestFactory $requestFactory */ $requestFactory = static::makeInstance(RequestFactory::class); if (is_array($requestHeaders)) { // Check is $requestHeaders is an associative array or not if (count(array_filter(array_keys($requestHeaders), 'is_string')) === 0) { trigger_error('Request headers as colon-separated string are deprecated, use an associative array instead.', E_USER_DEPRECATED); // Convert cURL style lines of headers to Guzzle key/value(s) pairs. $requestHeaders = static::splitHeaderLines($requestHeaders); } $configuration = ['headers' => $requestHeaders]; } else { $configuration = []; } $includeHeader = (int)$includeHeader; $method = $includeHeader === 2 ? 'HEAD' : 'GET'; try { if (isset($report)) { $report['lib'] = 'GuzzleHttp'; } $response = $requestFactory->request($url, $method, $configuration); } catch (RequestException $exception) { if (isset($report)) { $report['error'] = $exception->getCode() ?: 1518707554; $report['message'] = $exception->getMessage(); $report['exception'] = $exception;
  4. } catch (RequestException $exception) { if (isset($report)) { $report['error'] =

    $exception->getCode() ?: 1518707554; $report['message'] = $exception->getMessage(); $report['exception'] = $exception; } return false; } $content = ''; // Add the headers to the output if ($includeHeader) { $parsedURL = parse_url($url); $content = $method . ' ' . ($parsedURL['path'] ?? '/') . (!empty($parsedURL['query']) ? '?' . $parsedURL['query'] : '') . ' HTTP/ 1.0' . CRLF . 'Host: ' . $parsedURL['host'] . CRLF . 'Connection: close' . CRLF; if (is_array($requestHeaders)) { $content .= implode(CRLF, $requestHeaders) . CRLF; } foreach ($response->getHeaders() as $headerName => $headerValues) { $content .= $headerName . ': ' . implode(', ', $headerValues) . CRLF; } // Headers are separated from the body with two CRLFs $content .= CRLF; } $content .= $response->getBody()->getContents(); if (isset($report)) { if ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) { $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif (empty($content)) {
  5. if (isset($report)) { if ($response->getStatusCode() >= 300 && $response->getStatusCode() <

    400) { $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif (empty($content)) { $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif ($includeHeader) { // Set only for $includeHeader to work exactly like PHP variant $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); } } } else { if (isset($report)) { $report['lib'] = 'file'; } $content = @file_get_contents($url); if ($content === false && isset($report)) { $report['error'] = -1; $report['message'] = 'Couldn\'t get URL: ' . $url; } } return $content; }
  6. public static function getUrl($url, $includeHeader = 0, $requestHeaders = null,

    &$report = null) { if (isset($report)) { $report['error'] = 0; $report['message'] = ''; } // Looks like it's an external file, use Guzzle by default if (preg_match('/^(?:http|ftp)s?|s(?:ftp|cp):/', $url)) { /** @var RequestFactory $requestFactory */ $requestFactory = static::makeInstance(RequestFactory::class); if (is_array($requestHeaders)) { // Check is $requestHeaders is an associative array or not if (count(array_filter(array_keys($requestHeaders), 'is_string')) === 0) { trigger_error('Request headers as colon-separated string are deprecated, use an associative array instead.', E_USER_DEPRECATED); // Convert cURL style lines of headers to Guzzle key/value(s) pairs. $requestHeaders = static::splitHeaderLines($requestHeaders); } $configuration = ['headers' => $requestHeaders]; } else { $configuration = []; } $includeHeader = (int)$includeHeader; $method = $includeHeader === 2 ? 'HEAD' : 'GET'; try { if (isset($report)) { $report['lib'] = 'GuzzleHttp'; } $response = $requestFactory->request($url, $method, $configuration); } catch (RequestException $exception) { if (isset($report)) { $report['error'] = $exception->getCode() ?: 1518707554; $report['message'] = $exception->getMessage(); $report['exception'] = $exception;
  7. } catch (RequestException $exception) { if (isset($report)) { $report['error'] =

    $exception->getCode() ?: 1518707554; $report['message'] = $exception->getMessage(); $report['exception'] = $exception; } return false; } $content = ''; // Add the headers to the output if ($includeHeader) { $parsedURL = parse_url($url); $content = $method . ' ' . ($parsedURL['path'] ?? '/') . (!empty($parsedURL['query']) ? '?' . $parsedURL['query'] : '') . ' HTTP/ 1.0' . CRLF . 'Host: ' . $parsedURL['host'] . CRLF . 'Connection: close' . CRLF; if (is_array($requestHeaders)) { $content .= implode(CRLF, $requestHeaders) . CRLF; } foreach ($response->getHeaders() as $headerName => $headerValues) { $content .= $headerName . ': ' . implode(', ', $headerValues) . CRLF; } // Headers are separated from the body with two CRLFs $content .= CRLF; } $content .= $response->getBody()->getContents(); if (isset($report)) { if ($response->getStatusCode() >= 300 && $response->getStatusCode() < 400) { $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif (empty($content)) {
  8. if (isset($report)) { if ($response->getStatusCode() >= 300 && $response->getStatusCode() <

    400) { $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif (empty($content)) { $report['error'] = $response->getStatusCode(); $report['message'] = $response->getReasonPhrase(); } elseif ($includeHeader) { // Set only for $includeHeader to work exactly like PHP variant $report['http_code'] = $response->getStatusCode(); $report['content_type'] = $response->getHeaderLine('Content-Type'); } } } else { if (isset($report)) { $report['lib'] = 'file'; } $content = @file_get_contents($url); if ($content === false && isset($report)) { $report['error'] = -1; $report['message'] = 'Couldn\'t get URL: ' . $url; } } return $content; }
  9. Pattern: Guard-Clauses public static function fixed_lgd_cs($string, $chars, $appendString = '...')

    { if ((int)$chars === 0 || mb_strlen($string, 'utf-8') <= abs($chars)) { return $string; } if ($chars > 0) { $string = mb_substr($string, 0, $chars, 'utf-8') . $appendString; } else { $string = $appendString . mb_substr($string, $chars, mb_strlen($string, 'utf-8'), 'utf-8'); } return $string; }
  10. Codemetrik:
 zyklomatische Komplexität public static function fixed_lgd_cs($string, $chars, $appendString =

    '...') { if ((int)$chars === 0 || mb_strlen($string, 'utf-8') <= abs($chars)) { return $string; } if ($chars > 0) { $string = mb_substr($string, 0, $chars, 'utf-8') . $appendString; } else { $string = $appendString . mb_substr($string, $chars, mb_strlen($string, 'utf-8'), 'utf-8'); } return $string; } 1 2 3
  11. Codemetrik:
 Npath-Komplexität public static function fixed_lgd_cs($string, $chars, $appendString = '...')

    { if ((int)$chars === 0 || mb_strlen($string, 'utf-8') <= abs($chars)) { return $string; } if ($chars > 0) { $string = mb_substr($string, 0, $chars, 'utf-8') . $appendString; } else { $string = $appendString . mb_substr($string, $chars, mb_strlen($string, 'utf-8'), 'utf-8'); } return $string; } 1 2 3
  12. Codemetrik:
 Npath-Komplexität public static function writeFile($file, $content, $changePermissions = false)

    { if (!@is_file($file)) { $changePermissions = true; } if ($fd = fopen($file, 'wb')) { $res = fwrite($fd, $content); fclose($fd); if ($res === false) { return false; } // Change the permissions only if the file has just been created if ($changePermissions) { static::fixPermissions($file); } return true; } return false; } 1 2 4 6 8
  13. Design-by-Contract (light) /** * Generate code from tokens between given

    indexes. * * @param int $start start index, must be >= 0 * @param int $end end index, must be > $start * * @return string code, will not be empty */ public function generatePartialCode(int $start, int $end) Nachbedingungen Vorbedingungen
  14. Liskovsches Substitutionsprinzip (Ersetzbarkeitsprinzip) „Wo eine Instanz einer Klasse benutzt wird,

    muss auch eine Instanz einer Unterklasse benutzt werden können, ohne dass dadurch Fehler auftreten.“