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