parent
a9995970f3
commit
f89f6ae772
Binary file not shown.
@ -0,0 +1,3 @@ |
||||
About Data Transfer Objects, etc...: |
||||
|
||||
https://chatgpt.com/share/6956d98b-3d5c-8001-8139-a8598747b111 |
||||
@ -0,0 +1,62 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Gang of Four Design Patterns</title> |
||||
</head> |
||||
<body> |
||||
<h1>23 Classic Gang of Four Design Patterns</h1> |
||||
|
||||
<p style="font-size: small;">Generated by ChatGPT:</p> |
||||
|
||||
<h2>Creational Patterns (deal with object creation)</h2> |
||||
<ol> |
||||
<li><strong>Singleton</strong> - Ensures a class has only one instance and provides a global point of access to it.</li> |
||||
<li><strong>Factory Method</strong> - Defines an interface for creating objects but lets subclasses decide which class to instantiate.</li> |
||||
<li><strong>Abstract Factory</strong> - Provides an interface for creating families of related objects without specifying their concrete classes.</li> |
||||
<li><strong>Builder</strong> - Separates the construction of a complex object from its representation, allowing the same construction process to create different representations.</li> |
||||
<li><strong>Prototype</strong> - Creates new objects by copying an existing object (prototype) rather than creating from scratch.</li> |
||||
</ol> |
||||
|
||||
<h2>Structural Patterns (deal with object composition)</h2> |
||||
<ol start="6"> |
||||
<li><strong>Adapter</strong> - Converts the interface of one class into another interface that clients expect, enabling incompatible classes to work together.</li> |
||||
<li><strong>Bridge</strong> - Decouples an abstraction from its implementation so they can vary independently, preventing a permanent binding between them.</li> |
||||
<li><strong>Composite</strong> - Composes objects into tree structures to represent part-whole hierarchies, letting clients treat individual objects and compositions uniformly.</li> |
||||
<li><strong>Decorator</strong> - Attaches additional responsibilities to an object dynamically, providing a flexible alternative to subclassing for extending functionality.</li> |
||||
<li><strong>Facade</strong> - Provides a unified, simplified interface to a complex subsystem, making it easier to use.</li> |
||||
<li><strong>Flyweight</strong> - Minimizes memory usage by sharing as much data as possible with similar objects; used when large numbers of objects are needed.</li> |
||||
<li><strong>Proxy</strong> - Provides a surrogate or placeholder for another object to control access to it, useful for lazy initialization, access control, or logging.</li> |
||||
</ol> |
||||
|
||||
<h2>Behavioral Patterns (deal with object interaction and responsibility)</h2> |
||||
<ol start="13"> |
||||
<li><strong>Chain of Responsibility</strong> - Passes a request along a chain of handlers, where each handler decides either to process the request or pass it to the next handler.</li> |
||||
<li><strong>Command</strong> - Encapsulates a request as an object, thereby allowing parameterization of clients with different requests and supporting undoable operations.</li> |
||||
<li><strong>Interpreter</strong> - Defines a grammatical representation for a language and an interpreter to evaluate sentences in that language.</li> |
||||
<li><strong>Iterator</strong> - Provides a way to access elements of an aggregate object sequentially without exposing its underlying representation.</li> |
||||
<li><strong>Mediator</strong> - Defines an object that encapsulates how a set of objects interact, promoting loose coupling by preventing objects from referring to each other explicitly.</li> |
||||
<li><strong>Memento</strong> - Captures and externalizes an object's internal state without violating encapsulation, so the object can be restored to this state later.</li> |
||||
<li><strong>Observer</strong> - Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.</li> |
||||
<li><strong>State</strong> - Allows an object to alter its behavior when its internal state changes, appearing to change its class.</li> |
||||
<li><strong>Strategy</strong> - Defines a family of algorithms, encapsulates each one, and makes them interchangeable, letting the algorithm vary independently from clients.</li> |
||||
<li><strong>Template Method</strong> - Defines the skeleton of an algorithm in a method, deferring some steps to subclasses, letting subclasses redefine certain steps without changing the algorithm's structure.</li> |
||||
<li><strong>Visitor</strong> - Represents an operation to be performed on elements of an object structure, letting you define new operations without changing the classes of the elements.</li> |
||||
</ol> |
||||
|
||||
<p>These patterns provide proven solutions to common software design problems, promoting code reuse, flexibility, and maintainability in object-oriented systems.</p> |
||||
|
||||
<h2>Links to more external resources not mine...</h2> |
||||
|
||||
<blockquote style="position: relative; font-style: italic; margin: 10px 0 0; padding: 10px 12px; border-left: 3px solid #60a5fa; border-radius: 10px;"> |
||||
<p>I'm not affiliated with nor profit from these Books, they are just here for your and my convenience.</p> |
||||
<p>Modern PHP 8 Design Patterns Online Version: <a href="https://designpatternsphp.readthedocs.io/en/latest/">https://designpatternsphp.readthedocs.io/en/latest/</a></p> |
||||
<p>PDF Version: <a href="https://designpatternsphp.readthedocs.io/_/downloads/en/latest/pdf/">https://designpatternsphp.readthedocs.io/_/downloads/en/latest/pdf/</a></p> |
||||
<p>Nice Book for sale: Buy Dive Into DESIGN PATTERNS An Ebook on design patterns and the principles behind them: <a href="https://refactoring.guru/design-patterns/book">https://refactoring.guru/design-patterns/book</a></p> |
||||
<p>PHP Code from the Book above: <a href="https://refactoring.guru/design-patterns/php">https://refactoring.guru/design-patterns/php</a>, If you liked it; Please support them by buying the book above...</p> |
||||
<p>"The Gang of 4 book" - Design Patterns: Elements of Reusable Object-Oriented Software By Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Published Oct 31, 1994. Buy here it: <a href="https://www.informit.com/store/design-patterns-elements-of-reusable-object-oriented-9780201633610">https://www.informit.com/store/design-patterns-elements-of-reusable-object-oriented-9780201633610</a></p> |
||||
<p><a href="https://www.informit.com/imprint/series_detail.aspx?st=61147">More on The Addison-Wesley Professional Computing Series</a></p> |
||||
</blockquote> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,154 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
|
||||
namespace App\Log; |
||||
|
||||
use Psr\Log\LoggerInterface; |
||||
use Psr\Log\LogLevel; |
||||
use Psr\Log\InvalidArgumentException; |
||||
|
||||
final class Logger implements LoggerInterface |
||||
{ |
||||
private $handle = false; |
||||
|
||||
public function __construct( |
||||
string $filename = 'system', |
||||
int $maxCount = 1000 |
||||
) { |
||||
if (str_contains($filename, '..')) { |
||||
return; |
||||
} |
||||
|
||||
$logDir = BaseDir . '/protected/logs'; |
||||
|
||||
if (!is_dir($logDir)) { |
||||
mkdir($logDir, 0775, true); |
||||
} |
||||
|
||||
$filename = preg_replace('/[^A-Za-z0-9_]/', '', $filename); |
||||
$file = $logDir . '/' . $filename . '.log.txt'; |
||||
|
||||
if ($maxCount > 1 && $this->getLines($file) > $maxCount) { |
||||
@unlink($file); |
||||
} |
||||
|
||||
if (file_put_contents($file, "\n", FILE_APPEND) === false) { |
||||
return; |
||||
} |
||||
|
||||
@chmod($file, 0660); |
||||
@chgrp($file, 'www-data'); |
||||
|
||||
if (!is_writable($file)) { |
||||
return; |
||||
} |
||||
|
||||
$this->handle = fopen($file, 'ab'); |
||||
} |
||||
|
||||
/* ---------------- PSR-3 Core ---------------- */ |
||||
|
||||
public function log($level, $message, array $context = []): void |
||||
{ |
||||
if (!is_string($level)) { |
||||
throw new InvalidArgumentException('Log level must be a string'); |
||||
} |
||||
|
||||
if (!$this->handle || !is_resource($this->handle)) { |
||||
return; |
||||
} |
||||
|
||||
$message = $this->interpolate((string)$message, $context); |
||||
|
||||
$time = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); |
||||
fwrite( |
||||
$this->handle, |
||||
sprintf("[%s] %s: %s\n", $time, strtoupper($level), $message) |
||||
); |
||||
} |
||||
|
||||
/* ---------------- Level Methods ---------------- */ |
||||
|
||||
public function emergency($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::EMERGENCY, $message, $context); |
||||
} |
||||
|
||||
public function alert($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::ALERT, $message, $context); |
||||
} |
||||
|
||||
public function critical($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::CRITICAL, $message, $context); |
||||
} |
||||
|
||||
public function error($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::ERROR, $message, $context); |
||||
} |
||||
|
||||
public function warning($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::WARNING, $message, $context); |
||||
} |
||||
|
||||
public function notice($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::NOTICE, $message, $context); |
||||
} |
||||
|
||||
public function info($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::INFO, $message, $context); |
||||
} |
||||
|
||||
public function debug($message, array $context = []): void |
||||
{ |
||||
$this->log(LogLevel::DEBUG, $message, $context); |
||||
} |
||||
|
||||
/* ---------------- Helpers ---------------- */ |
||||
|
||||
private function interpolate(string $message, array $context): string |
||||
{ |
||||
$replace = []; |
||||
|
||||
foreach ($context as $key => $value) { |
||||
if (is_scalar($value) || $value instanceof \Stringable) { |
||||
$replace['{' . $key . '}'] = (string)$value; |
||||
} |
||||
} |
||||
|
||||
return strtr($message, $replace); |
||||
} |
||||
|
||||
private function getLines(string $file): int |
||||
{ |
||||
if (!file_exists($file)) { |
||||
return 0; |
||||
} |
||||
|
||||
$lines = 0; |
||||
$fh = fopen($file, 'rb'); |
||||
|
||||
if (!$fh) { |
||||
return 0; |
||||
} |
||||
|
||||
while (!feof($fh)) { |
||||
$lines += substr_count(fread($fh, 8192), "\n"); |
||||
} |
||||
|
||||
fclose($fh); |
||||
return $lines; |
||||
} |
||||
|
||||
public function __destruct() |
||||
{ |
||||
if ($this->handle && is_resource($this->handle)) { |
||||
fclose($this->handle); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue