| AmirHossein | – Telegram
| AmirHossein |
591 subscribers
44 photos
8 videos
2 files
73 links
نوشته‌های یک برنامه‌نویس ناشی

🫂 @StartUnity
Download Telegram
#magic_method #oop #php
مجیک متد __clone() :
این متد برای ایجاد نسخه ای کپی از یک شئ استفاده می‌شود. وقتی از عملگر کلون (clone) استفاده می‌کنید، تابع __clone() در کلاس مربوطه اجرا می‌شود و می‌توانید تنظیمات مورد نیاز برای نسخه کپی را انجام دهید.
مثال :
class Fruit {
public $name;
public $color;

public function __clone() {
$this->name = 'cloned fruit name';
$this->color = 'cloned fruit color';
}
}

$firstFruit = new Fruit();
$firstFruit->name = 'banana';
$firstFruit->color = 'red';

$clonedFruit = clone $firstFruit;

var_dump($firstFruit);

var_dump($clonedFruit);

Result:

object(Fruit)#1 (2) {
["name"]=>
string(6) "banana"
["color"]=>
string(3) "red"
}
object(Fruit)#2 (2) {
["name"]=>
string(17) "cloned fruit name"
["color"]=>
string(18) "cloned fruit color"
}

در مثال بالا یک شئ از Fruit با دو ویژگی name و color ساخته ایم و سپس یک clone از آن گرفته ایم، زمان استفاده از عملگر clone متد __clone() فراخوانی می شود و شئ جدید را با ویژگی های تنظیم شده می سازد.
.
👍1
#magic_method #oop #php
مجیک متد __debugInfo() :
این متد برای تعریف اطلاعاتی است که برای نمایش در روند debugging یا در تابع var_dump() از یک شئ استفاده می‌شود. با تعریف تابع __debugInfo() در کلاس خود، شما می‌توانید اطلاعات مخصوصی را برای نمایش در این فرایندها تعیین کنید.
این متد باید یک آرایه اطلاعات را برگرداند که شامل جفت‌های key-value است. این جفت‌ها باید مشخص کننده ویژگی‌ها و مقادیر آنها در شئ باشند که می‌خواهید در روند debugging نمایش داده شوند.

مثال:
class Fruit {
public $name;
public $color;

public function __debugInfo() {
return [
'fruit name' => $this->name,
'fruit color' => $this->color
];
}
}

$fruit = new Fruit();
$fruit->name = 'banana';
$fruit->color = 'yellow';

var_dump($fruit);

Result:
object(Fruit)#1 (2) {
["fruit name"]=>
string(6) "banana"
["fruit color"]=>
string(6) "yellow"
}

در این مثال می بینیم که هنگام var_dump() شئ، موارد مشخص شده در __debugInfo() به نمایش در می آید.با این کار می توانیم تنها موارد مورد نیاز را نمایش دهیم و روند debugging را راحت تر کنیم.
.
چند وقتی هست که روی یک پروژه کار میکنم
یه کتابخونه برای ربات های تلگرامی

قابلیت ها:
- پشتیبانی از الوکوئنت لاراول
- - مدل
- - مایگریشن

- پشتیبانی از openSwoole و AMPHP
- - کوروتین
- - و Swoole Table

- پشتیبانی از Telegram Bot Api Server

- پشتیبانی از دیتابیس های:
MySql, Redis, Json

- پشتیبانی از Command Line
- - ساخت مدل و مایگریشن دیتابیس
- - ساخت ریسورس های ربات
- - ران کردن وب سرور
- - مدیریت وب هوک
- سیستم Auth & Access اختصاصی

سرعت ربات درحالت سینک 100ms
سرعت ربات در حالت اِی سینک 1ms

البته هنوز اول راهش هست و قراره کلی قابلیت بهش اضافه بشه که چند تاش پشتیبانی از PHP-ML (کتابخانه هوش مصنوعی) و ساخت ربات های CLI هست

اولش برای استفاده شخصی ساخته بودم ولی خب گفتم بزارم گیت هاب که بقیه هم استفاده کنن

از این لینک میتونید مشاهده ش کنی و خوش حال میشم Star هم بکنید❤️
🔥5👍1
می رسیم به مبحث Magic constants ها در php
طبق مستندات php، نه مجیک کانستنت وجود داره که بسته به محل استفاده و شرایط موجود مقادیر آنها تغییر پیدا میکنه.
این ثابت ها در هنگام کامپایل تعریف می شوند بر خلاف ثابت های معمولی که در زمان اجرا تعریف می شوند و به حروف کوچک و بزرگ حساس نیستند.
لیست این ثابت ها با تعریف به شرح زیر است:
__LINE__ :
شماره خط فعلی فایل

__FILE__ :
نام فایل فعلی

__DIR__ :
نام فولدر فعلی (در انتها نام فولدر اسلش وجود ندارد مگر در فولدر روت)

__FUNCTION__ :
نام فانکشن فعلی (مقدار {closure} برای تابع های ناشناس)

__CLASS__ :
نام کلاس فعلی (همراه با namespace)

__TRAIT__ :
نام تریت فعلی (همراه با namespace)

__METHOD__ :
نام متد فعلی کلاس

__NAMESPACE__ :
نام namespace فعلی

ClassName::class :
کلاس با تمامی داده ها

.
دو مبحث هست که دوست دارم راجع بهش توضیح بدم

یک : معرفی ۱۰ تا دیزاین پترن و آموزششون
دو : روش های نفوذپذیری وب و جلوگیری ازش

فقط نمیدونم کدوم رو اول بگم
هر دو مبحث طولانی و زمان بر هست
همین یکی دو روز آینده یکیش رو شروع میکنم

نظری داشتید خوشحال میشم در میون بزارید❤️
2👍1
متسفانه به دلیل مسائل امنیتی که توی کامیت های LaraGram به وجود اومده بود مجبور به حذف ریپوزیتوری شدم
و خب 72 کامیت که داشت به علاوه استار ها حذف شدند

برای اینکه از این نوع مسائل براتون پیش نیاد میتونه خوب باشه که قابلیت Secret scanning رو فعال کنید
این قابلیت قبل از Push کردن کد رو بررسی میکنه و اگر حاوی توکن و امثالش باشه بهتون هشدار میده

برای فعال کردنش
Setting >> Code security and analysis :
Secret scanning : Enable
Push protection : Enable

در نهایت هم اگر دوست داشتید و براتون مقدور بود مجدد به ریپوزیتوری استار بدید❤️🙏
https://github.com/laraXgram/LaraGram
.
👍31
#design_patterns
خب، قرار شد که 10 تا از دیزاین پترن های پرکاربرد رو معرفی و توضیح بدیم
اما قبل از اینکه شروع کنیم اول باید بدونیم دیزاین پترن چیه

دیزاین پترن (Design Patterns) :
مجموعه‌ای از قواعد و الگوهایی است که در فرآیند طراحی نرم‌افزارها مورد استفاده قرار می‌گیرند. این الگوها برای حل مشکلات معمول در طراحی نرم‌افزارها، بهبود قابلیت‌ها و کاهش پیچیدگی استفاده می‌شوند.

چند تا از کاربرد های اصلی دیزاین پترن ها :
1- افزایش قابلیت خوانایی و درک کد: از اونجایی که دیزاین پترن ها یک ساختار مشخص و قابل فهم دارند، قابلیت خوانایی کد رو هم برای برنامه نویس پروژه و هم سایر برنامه نویسان افزایش میدن.

2- کاهش پیچیدگی: دیزاین پترن با ارائه یک روش ساختارمند برای حل مشکلات معمول، پیچیدگی طراحی را کاهش می‌دهند و فرآیند توسعه نرم‌افزار را ساده‌تر می‌کنند.

3- افزایش قابلیت استفاده دوباره: دیزاین پترن با ارائه الگوهای استاندارد برای حل مسائل مشترک، امکان استفاده مجدد کد را افزایش می‌دهند و زمان و هزینه‌های توسعه را کاهش می‌دهند.

4- افزایش انعطاف‌پذیری: دیزاین پترن با ایجاد ساختارهای قابل تغییر و گسترش، انعطاف‌پذیری نرم‌افزار را افزایش می‌دهند و امکان تغییرات و بهبودهای آتی را فراهم می‌کنند.

5- استانداردسازی و هماهنگ‌سازی: این الگوها به توسعه‌دهندگان کمک می‌کنند تا مشکلات معمول در طراحی نرم‌افزارها را حل کنند و به ساختار و عملکرد بهینه نرم‌افزارها دست پیدا کنند.

تا اینجا با برخی خواص دیزاین پترن ها آشنا شدیم
لیستی از دیزاین پترن هایی که قصد دارم در ادامه توضیح بده :
Singleton
Factory
Observer
MVC
Repository
Strategy
Facade
Dependency Injection
Template Method
Iterator

این الگو ها معمولا در بقیه زبان ها هم کاربرد دارند اما مثال ها با PHP خواهند بود.
.
🔥3
#design_patterns
یکی از معروف ترین و ساده ترین دیزان پترن ها Singleton هست.
دیزان پترن Singleton برای ایجاد یک کلاسی استفاده می‌شود که تنها یک نمونه از آن در سراسر برنامه وجود دارد. این الگو برای اطمینان از اینکه تمام اجزای برنامه از یک نمونه واحد استفاده می‌کنند، مفید است.

ساختارش به این صورت هست:
class DatabaseConnection {
private static $instance;
private function __construct() {
echo "database connected";
}

public static function getInstance() {
if (self::$instance === null) {
self::$instance = new DatabaseConnection();
}
return self::$instance;
}
}

در مثال بالا یک کلاس برای اتصال به دیتابیس داریم.

این کلاس دارای یک پراپرتی instance هست که یا null است یا حاوی یک نمونه از کلاس، و یک متد getInstance.

زمانی که متد getInstance فراخوانی شود چک می کند که آیا از قبل نمونه ایی از کلاس ساخته شده یا خیر، این کار را با بررسی مقدار پراپرتی instance انجام می دهد که آیا null هست یا حاوی یک نمونه از کلاس.

در صورتی که نمونه ساخته نشده باشد(پراپرتی instance برابر null باشد) یک نمونه جدید می سازد و در صورتی که از قبل نمونه وجود داشته باشد(پراپرتی instance برابر نمونه ایی از کلاس باشد) همان نمونه قبلی را استفاده می کند.

با استفاده از این دیزاین پترن درصورتی که صد ها بار هم از کلاس DatabaseConnection نمونه بسازید فقط و فقط یک بار ساخته می شود.
DatabaseConnection::getInstance();
DatabaseConnection::getInstance();
DatabaseConnection::getInstance();
DatabaseConnection::getInstance();

Result:
database connected
.
3👍1
#design_patterns
مورد بعدی دیزاین پترن Factory هست.
این دیزاین پترن در PHP برای ایجاد شئ ها به صورت پویا و بر اساس نیازها و شرایط مختلف استفاده می‌شود. این الگو به شما اجازه می‌دهد که بدون نیاز به دستکاری کد اصلی، شئ های مختلف را ایجاد کنید.

مثال:
interface Fruit {
public function color();
}

class Banana implements Fruit {
public function color() {
echo "yellow";
}
}

class Apple implements Fruit {
public function color() {
echo "red";
}
}

class FruitFactory {
public function createFruit($fruitName) {
if ($fruitName === 'banana') {
return new Banana();
} elseif ($fruitName === 'apple') {
return new Apple();
}
}
}

در مثال بالا، ابتدا یک اینترفیس Fruit تعریف شده است که توابعی مانند color را برای میوه ها تعریف می‌کند. سپس دو کلاس Banana و Apple ایجاد شده‌اند که از رابط Fruit ارث‌بری می‌کنند و توابع color را پیاده‌سازی می‌کنند.
در نهایت، کلاس FruitFactory تعریف شده است که به عنوان یک فکتوری برای ایجاد شیء‌های میوه عمل می‌کند. متد createFruit در این کلاس یک نوع میوه را به عنوان ورودی دریافت می‌کند و بر اساس نوع میوه مورد نظر، یک شئ مربوطه را ایجاد و برمی‌گرداند.

برای استفاده از الگوی Factory به روش زیر عمل می کنیم:
$factory = new FruitFactory();

$banana = $factory->createFruit('banana');
$banana->color();

Result:
yellow

$apple = $factory->createFruit('apple');
$apple->color();

Result:
red

با استفاده از الگوی Factory، ما می‌توانیم به راحتی شئ های مختلف را ایجاد کنیم، بدون اینکه بخش‌های دیگر برنامه را تغییر دهیم. این الگو به ما امکان می‌دهد به سادگی از تغییرات در ایجاد شئ ها برای موارد خاص استفاده کنیم.
.
👍2
#design_patterns
دیزاین پترن بعدی Observer که به معنی مشاهده گر هست.
دیزاین پترن Observer برای برقراری ارتباط بین اجزای نرم‌افزار به منظور رصد و پاسخ به تغییرات استفاده می‌شود. در این الگو، یک شئ ارائه دهنده اطلاعات مرتبط (مشترک) به تعدادی از شئ های مشاهده‌کننده وابسته است. وقتی که وضعیت شئ ارائه دهنده اطلاعات تغییر می‌کند، تمام شئ های مشاهده‌کننده مطلع می‌شوند و عملیاتی را براساس تغییرات انجام می‌دهند.

در دیزاین پترن Observer، ارتباط بین ارائه دهنده اطلاعات (موضوع) و شئ های مشاهده‌کننده (مشترکین) به وسیله رابط یا کلاسی که شئ های مشاهده‌کننده را نگهداری می‌کند (مشترک‌کننده) برقرار می‌شود.

مثال:

interface Observer {
public function update($data);
}

class Subject {
private $observers = [];

public function attach(Observer $observer) {
$this->observers[] = $observer;
}

public function detach(Observer $observer) {
$index = array_search($observer, $this->observers);
if ($index !== false) {
unset($this->observers[$index]);
}
}

public function notify($data) {
foreach ($this->observers as $observer) {
$observer->update($data);
}
}
}

class ConcreteObserver implements Observer {
public function update($data) {
echo "Received data: " . $data . "\n";
}
}

در مثال بالا، اینترفیس Observer تعریف شده است که تابع update را می‌شود پیاده‌سازی کرد. سپس کلاس Subject ایجاد شده است که شئ های Observer را نگهداری می‌کند. متد attach برای اضافه کردن شئ های Observer، متد detach برای حذف آن‌ها و متد notify برای اطلاع‌رسانی تغییرات به تمام Observer ها استفاده می‌شود.

همچنین، یک کلاس مشترک‌کننده ConcreteObserver تعریف شده است که روش update را پیاده‌سازی می‌کند. وقتی که تغییری در Subject رخ می‌دهد و تابع notify فراخوانی می‌شود، تمام مشترک‌کننده‌ها (شئ های Observer) به طور خودکار تابع update را اجرا کرده و تغییرات را دریافت می‌کنند.

$subject = new Subject();

$observer1 = new ConcreteObserver();
$subject->attach($observer1);

$observer2 = new ConcreteObserver();
$subject->attach($observer2);

$subject->notify("Hello Banana!");

Result:
Received data: Hello Banana!
Received data: Hello Banana!

در مثال بالا، ابتدا یک شئ Subject ایجاد شده و دو شئ ConcreteObserver به آن الحاق شده‌اند. سپس با فراخوانی تابع notify روی Subject و ارسال پیام Hello Banana!، تمام مشترک‌کننده‌ها این پیام را دریافت و نمایش می‌دهند.

دیزاین پترن Observer زمانی مفید است که یک تغییر در یک شئ منجر به تغییراتی در شئ های دیگر می‌شود و ارتباط ضعیف بین اجزا مد نظر است. این الگو باعث جداسازی اجزا و افزایش انعطاف‌پذیری در نرم‌افزار می‌شود.
.
👍2
#design_patterns
دیزاین پترن MVC یا معماری MVC که مخفف Model, View, Controller هست و تقریبا همتون باهاش آشنایی دارید.

دیزاین پترن MVC یکی از دیزاین پترن های ساختاری است که برای سازماندهی و جداسازی بخش‌های مختلف یک برنامه مورد استفاده قرار می‌گیرد. MVC متدولوژی معماری محبوبی در توسعه نرم‌افزار است که به برنامه‌ها انعطاف‌پذیری، قابلیت تست و قابلیت نگهداری بیشتری می‌بخشد.

مدل (Mpdel): مدل مسئولیتی را بر عهده دارد که داده‌ها و منطق برنامه را مدیریت کند. مدل‌ها معمولاً شامل کلاس‌ها و ساختارهای داده‌ای هستند که داده‌ها را نگهداری و عملیاتی روی آن‌ها را انجام می‌دهند. مثال‌هایی از مدل‌ها شامل کلاس‌های مرتبط با پایگاه داده، کلاس‌های مدیریت کننده داده و کلاس‌های مرتبط با قوانین برنامه هستند.

ویو یا نما (View): نما مسئولیت نمایش داده‌ها را دارد و بر اساس داده‌هایی که از مدل دریافت می‌کند، اطلاعات را به کاربر نمایش می‌دهد. نما معمولاً شامل تمپلیت‌ها، صفحات و بخش‌های واسط کاربری است که برای نمایش اطلاعات به کاربر استفاده می‌شود. نما مستقیماً با کاربر در ارتباط است و تغییرات در نما بر اثر ورودی کاربر اتفاق می‌افتد.

کنترلر یا کنترل کننده (Controller): کنترل‌کننده مسئولیت هدایت جریان کار بین مدل و نما را بر عهده دارد. وظیفه کنترل‌کننده این است که ورودی‌های کاربر را دریافت کرده، عملیات لازم را بر روی مدل انجام دهد و سپس نمایش مناسب را به نما بدهد. به عبارتی، کنترل‌کننده پلی بین مدل و نما است. مثال‌هایی از عملیاتی که کنترل‌کننده انجام می‌دهد، شامل بررسی validate کردن ورودی‌ها، انجام تغییرات در مدل و انتقال داده‌ها به نما است.

در معماری MVC، نمایش داده‌ها و همچنین منطق برنامه جدا از یکدیگر می‌شوند. این امکان را به توسعه‌دهندگان می‌دهد تا بخش‌های مختلف برنامه را به صورت مستقل توسعه دهند و تغییرات را در بخش‌های دیگر تأثیر ندهد. همچنین، جدا کردن منطق برنامه از نمایش داده‌ها باعث ساده‌سازی فرآیند تست و نگهداری می‌شود.

مثال :
class Model {
private $data;

public function setData($data) {
$this->data = $data;
}

public function getData() {
return $this->data;
}
}

class View {
public function render($data) {
echo "Data: " . $data;
}
}

class Controller {
private $model;
private $view;

public function __construct(Model $model, View $view) {
$this->model = $model;
$this->view = $view;
}

public function processData($data) {
$this->model->setData($data);
$data = $this->model->getData();
$this->view->render($data);
}
}

$model = new Model();
$view = new View();
$controller = new Controller($model, $view);
$controller->processData("Hello, World!");

Result:
Data: Hello, World!

در مثال بالا، مدل (Model) مسئولیتی برای نگهداری و مدیریت داده‌ها دارد. نما (View) وظیفه نمایش داده‌ها را دارد و کنترل‌کننده (Controller) وظیفه هدایت جریان کار بین مدل و نما را بر عهده دارد. با استفاده از کنترل‌کننده، داده ورودی (Hello, World!) به مدل داده شده، سپس از مدل خوانده شده و در نما نمایش داده می‌شود.

این معماری به توسعه‌دهندگان امکان می‌دهد که به صورت جداگانه بر روی هر بخش (مدل، نما و کنترل‌کننده) کار کنند و به سادگی تغییرات را اعمال کنند. همچنین، این الگوی طراحی باعث می‌شود برنامه ماژولارتر و قابل تست‌تر باشد.
.
بعد از کلی زمان گزاشتن روی پروژه LaraGram بلاخره در سایت تلگرام هم منتشر شد 🤝

کتابخانه ی بالایی (PTB) هم ساخت یکی از دوستان هست
فرصت داشتید STAR بدید به دو ریپوزیتوری زمان زیادی نمیبره❤️
.
5👌1
#design_patterns
دیزاین پترن Repository یکی از الگوهای معماری مورد استفاده در توسعه نرم‌افزار است که به عنوان واسطی بین بخش‌های داده‌ی دائمی (مثل دیتابیس) و بخش‌های کد برنامه مورد استفاده قرار می‌گیرد. هدف اصلی این دیزاین پترن، جداسازی لایه‌های داده از لایه‌های برنامه‌نویسی و ایجاد یک واسط یکسان برای دسترسی و مدیریت داده‌ها می باشد.

فرض کنید که شما در حال توسعه یک برنامه‌ی وب برای مدیریت اطلاعات کاربران هستید. اطلاعات کاربران (مانند نام، ایمیل، رمزعبور و ...) در یک پایگاه داده‌ی رابطه‌ای (مثل MySQL) ذخیره می‌شود. به جای اینکه در کد برنامه‌ی خود مستقیماً با پایگاه داده ارتباط برقرار کنید، از دیزاین پترن Repository استفاده می‌کنیم.

مثال :

ابتدا یک Interface برای Repository تعریف می‌کنیم که متد‌هایی برای ایجاد (create)، خواندن (read)، بروزرسانی (update) و حذف (delete) اطلاعات کاربران داشته باشد.
interface UserRepositoryInterface {
public function create(array $data): bool;
public function read(int $id): array;
public function update(int $id, array $data): bool;
public function delete(int $id): bool;
}

حالا یک کلاس برای Repository برای دیتابیس MySQL ایجاد می‌کنیم و متدهای Interface را پیاده‌سازی می‌کنیم.
class MySQLUserRepository implements UserRepositoryInterface {
private $connection;

public function __construct(mysqli $connection) {
$this->connection = $connection;
}

public function create(array $data): bool {
// Code to create user
return true;
}

public function read(int $id): array {
// Code to select user by id
$data = ['userDataFromDb'];
return $data;
}

public function update(int $id, array $data): bool {
// Code to update user
return true;
}

public function delete(int $id): bool {
// Code to delete user
return true;
}
}

حالا می‌توانیم در برنامه‌ی خود از Repository استفاده کنیم.
// create connection and repository
$connection = new mysqli("localhost", "username", "password", "database_name");
$userRepository = new MySQLUserRepository($connection);

// create new user
$newUser = [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'hashed_password'
];
$userRepository->create($newUser);

// select user by id
$userData = $userRepository->read(1);
print_r($userData);

// update user by id
$updatedUser = [
'name' => 'Jane Doe',
'email' => 'jane@example.com',
'password' => 'new_hashed_password'
];
$userRepository->update(1, $updatedUser);

// delete user
$userRepository->delete(1);

در این مثال، با استفاده از اینترفیس UserRepositoryInterface، وابستگی‌های کد به پایگاه داده جدا می‌شود. سپس با پیاده‌سازی کلاس MySQLUserRepository، کار با پایگاه داده‌ی MySQL به صورت مستقیم در Repository انجام می‌شود. این جداسازی باعث می‌شود تا می‌توانیم با تغییر پایگاه داده، کد برنامه‌ی خود را به راحتی تغییر داده و با اطمینان از عملکرد درست نرم‌افزار خود مطمئن شویم. همچنین، این کار باعث می‌شود که مدیریت داده‌ها و دسترسی به آن‌ها به صورت مجزا و قابل مدیریت‌تری صورت گیرد.
.
👍1
#design_patterns
دیزاین پترن Strategy یکی از دیزاین پترن های رایج معماری نرم‌افزاری است که در آن یک خانواده از الگوریتم‌ها یا روش‌های مختلف ارائه می‌شود و این امکان را به کاربر می‌دهد که در زمان اجرای برنامه، یکی از این الگوریتم‌ها را انتخاب کند و از آن استفاده کند.

فرض کنید که شما یک برنامه برای محاسبه قیمت نهایی محصولات در یک فروشگاه آنلاین طراحی می‌کنید. قیمت نهایی هر محصول بسته به شرایط مختلف می‌تواند به روش‌های مختلفی محاسبه شود. مثلاً برخی از محصولات ممکن است با تخفیف‌های ویژه‌ای به فروش برسند، برخی دیگر با توجه به نوع مشتری (حقیقی یا حقوقی) با قیمت متفاوت عرضه شوند و برخی ممکن است به صورت ثابت به فروش برسند.

مثال:

ابتدا یک اینترفیس برای استراتژی‌ها تعریف می‌کنیم که متد محاسبه قیمت نهایی محصول را دارد.
interface PricingStrategy {
public function calculateFinalPrice(float $price): float;
}


سپس برای هر روش محاسبه قیمت نهایی محصول، یک کلاس را پیاده‌سازی می‌کنیم که از این اینترفیس ارث‌بری کند و متد محاسبه قیمت را به شکل متناسب با الگوریتم‌های خود پیاده‌سازی کند.
class RegularPricingStrategy implements PricingStrategy {
public function calculateFinalPrice(float $price): float {
return $price;
}
}

class DiscountPricingStrategy implements PricingStrategy {
private $discountPercentage;

public function __construct(float $discountPercentage) {
$this->discountPercentage = $discountPercentage;
}

public function calculateFinalPrice(float $price): float {
$discountAmount = $price * ($this->discountPercentage / 100);
return $price - $discountAmount;
}
}

class SpecialCustomerPricingStrategy implements PricingStrategy {
private $specialPrice;

public function __construct(float $specialPrice) {
$this->specialPrice = $specialPrice;
}

public function calculateFinalPrice(float $price): float {
return $this->specialPrice;
}
}

حالا می‌توانیم در برنامه‌ی خود از دیزاین پترن استراتژی استفاده کنیم و به راحتی یکی از روش‌های محاسبه قیمت را برای هر محصول انتخاب کنیم.
$strategy = new SpecialCustomerPricingStrategy(10);

$price = 100;
$finalPrice = $strategy->calculateFinalPrice($price);

echo "Final Price: $finalPrice";

Result:
Final Price: 90

در این مثال، از دیزاین پترن Strategy برای جداسازی الگوریتم‌های مختلف محاسبه قیمت نهایی محصول استفاده کردیم. با استفاده از این الگو، می‌توانیم به راحتی یکی از روش‌های مختلف محاسبه قیمت را انتخاب کنیم و از آن استفاده کنیم، بدون اینکه نیاز به تغییر در کد برنامه‌ی خود داشته باشیم. همچنین، با اضافه کردن استراتژی‌های جدید، می‌توانیم به سادگی قابلیت‌های جدید به برنامه‌ی خود اضافه کنیم بدون تغییر در کد موجود.
.
1
فریم ورک nativephp که چیزی از انتشارش نگذشته و در حال حاظر نسخه آلفا هست.
این فریم ورک برای توسعه اپلیکیشن های دسکتابی با استفاده از زبان php توسعه داده شده که واقعا میتونه چیز جالبی باشه.

برای توسعه فرانت اپ های دسکتابی از Html, Css, Js استفاده می کنه و این یعنی توسعه اپ دسکتاپ برای توسعه دهنده های وب به سادگی آب خوردنه.

نکته ی جالب تر اینه که این فریم ورک در حال حاضر فقط با لاراول کار میکنه، ولی گفته شده در آینده میشه جدا از لاراول هم استفاده بشه.
این که بر پایه لاراول باشه خودش یک مزیته، یعنی شما وب سایت خودتون رو با لاراول بنویسید و یک خروجی دسکتاپ هم از وب سایتتون بگیرید!

نکته جالب تر، از اونجایی که فرانت کار با Html, Css, Js هست شما میتونید از react یا vue هم استفاده کنید یا حتی bootstrap و tailwindcss.

سعی کردم که یک تست ازش بگیرم، شروع به نصبش کردم و موقع اجرا با اروری برخورد کردم.
بعد از سرچ متوجه شدم که در حال حاظر فایل های باینری ایی برای ویندوز نداره و حتی روی لینوکس هم کار نمیکنه، وفعلا فقط روی مک کار میکنه درنتیجه باید منتظر موند.

در کل میتونه چیز جالبی باشه، البته که نه برای پروژه های بزرگ ولی در حد خروجی یک وب سایت اداری و حسابداری که نسخه دسکتابی هم داشته باشه.

بقیه مستندات رو از داکیمونت رسمیش بخونید.
و همینطور صفحه گیت هاب.
.
👍3
#design_patterns
دیزاین پترن Facade یکی از الگوهای معماری نرم‌افزاری است که به انتزاع کردن یک رابط ساده‌تر برای دسترسی به ساب سیستم های پیچیده‌تر کمک می‌کند. این الگو، واسطی ساده‌تر برای اجزای پیچیده‌تر سیستم ایجاد می‌کند تا به کاربران اجازه دهد با سیستم برخورد کنند بدون اینکه جزئیات پیچیده را مد نظر قرار دهند.

فرض کنید که شما یک برنامه‌ی پرداخت آنلاین برای یک فروشگاه آنلاین طراحی می‌کنید. فرآیند پرداخت شامل چند مرحله پیچیده‌تر مثل ارتباط با سرور بانک، بررسی اعتبار کارت، ذخیره تراکنش‌ها و ... است. به جای اینکه کلیه جزئیات پیچیده این فرآیند را در هر جای برنامه تکرار کنید، از دیزان پترن Facade استفاده می‌کنیم.

مثال :

ابتدا یک کلاس Facade برای فرآیند پرداخت ایجاد می‌کنیم که به عنوان واسط ساده‌تر با کاربران ارتباط برقرار می‌کند.
class PaymentFacade {
private $paymentGateway;
private $transactionLogger;

public function __construct() {
$this->paymentGateway = new PaymentGateway();
$this->transactionLogger = new TransactionLogger();
}

public function processPayment($creditCard, $amount) {
// Communication with the bank server through PaymentGateway
$response = $this->paymentGateway->makePayment($creditCard, $amount);

// Register the transaction in the TransactionLogger
$this->transactionLogger->logTransaction($creditCard, $amount, $response);

return $response;
}
}

سپس برای هر یک از اجزای پیچیده‌تر که در فرآیند پرداخت استفاده می‌شوند، یک کلاس را پیاده‌سازی می‌کنیم.
class PaymentGateway {
public function makePayment($creditCard, $amount) {
// Connect to the bank server and make payment
return "Transaction Successful";
}
}

class TransactionLogger {
public function logTransaction($creditCard, $amount, $response) {
// Record the transaction in the database or log file
}
}

حالا می‌توانیم در برنامه‌ی خود از کلاس Facade استفاده کنیم و با استفاده از یک متد ساده‌تر فرآیند پرداخت را انجام دهیم.
$paymentFacade = new PaymentFacade();

$creditCard = '1234-5678-9012-3456';
$amount = 100;

$response = $paymentFacade->processPayment($creditCard, $amount);

echo $response;

Result:
Transaction Successful

در این مثال، با استفاده از الگوی طراحی Facade، کار با فرآیند پرداخت به سادگی انجام می‌شود. تمام جزئیات پیچیده‌تر مثل ارتباط با بانک و ثبت تراکنش‌ها، در داخل کلاس‌های جداگانه پنهان شده است. این کلاس‌ها با هم ترکیب شده‌اند تا یک رابط ساده‌تر را ارائه دهند که کاربر می‌تواند به راحتی از آن استفاده کند. این الگو مزیت‌های افزودن اجزا و جداسازی اجزا را به برنامه می‌دهد.
.
👍2
#design_patterns
دیزان پترن Dependency Injection یکی از دیزان پترن های نرم‌افزاری است که به کاهش وابستگی‌ها (Dependencies) در بین کلاس‌ها کمک می‌کند. این الگو، از جمله اصول اصلی SOLID است که به عنوان یک راهنمای خوب برای طراحی کد قابل‌خواندن، قابل‌تغییر و قابل‌تست در نظر گرفته می‌شود.

فرض کنید که شما یک کلاس برای ارسال ایمیل در برنامه خود دارید. این کلاس ممکن است نیاز به ارتباط با سرویس‌های ارسال ایمیل مختلف داشته باشد، مانند ارسال ایمیل از طریق SMTP یا از طریق API‌ های خارجی. اما شما نمی‌خواهید که کلاس اصلی ایمیل وابستگی مستقیم به این سرویس‌ها داشته باشد. بلکه می‌خواهید وابستگی‌ها را به شکلی منعطف و از خارج کلاس تعریف کنید.

مثال:

به جای اینکه کلاس ایمیل از خود به دلیل نیاز به سرویس‌های ارسال ایمیل، این وابستگی‌ها را بخود ایجاد کند، آن‌ها به عنوان پارامترهایی از طریق کانستراکتور دریافت می‌کند.
class EmailSender {
private $mailer;

public function __construct(MailerInterface $mailer) {
$this->mailer = $mailer;
}

public function sendEmail($to, $subject, $body) {
// Send email using $this->mailer
// ...
}
}

ابتدا یک Interface برای سرویس ارسال ایمیل تعریف می‌کنیم که تمام کلاس‌هایی که می‌خواهیم از آن‌ها استفاده کنیم، باید از این Interface ارث‌بری کنند.
interface MailerInterface {
public function send($to, $subject, $body);
}

حالا می‌توانیم کلاس‌های مختلفی برای سرویس‌های ارسال ایمیل ایجاد کنیم که از اینترفیس MailerInterface ارث‌بری می‌کنند.
class SmtpMailer implements MailerInterface {
public function send($to, $subject, $body) {
// Send email via SMTP
}
}

class ExternalApiMailer implements MailerInterface {
public function send($to, $subject, $body) {
// Send email via external API
}
}

// etc. for other email delivery services

حالا می‌توانیم در زمان ایجاد شئ ایمیل، یکی از سرویس‌های ارسال ایمیل را به عنوان وابستگی تزریق کنیم.
// Use SmtpMailer
$smtpMailer = new SmtpMailer();
$emailSender = new EmailSender($smtpMailer);
$emailSender->sendEmail('user@example.com', 'Test Subject', 'Test Body');

// Use ExternalApiMailer
$externalApiMailer = new ExternalApiMailer();
$emailSender = new EmailSender($externalApiMailer);
$emailSender->sendEmail('user@example.com', 'Test Subject', 'Test Body');

در این مثال، با استفاده از دیزاین پترن Dependency Injection، کلاس ایمیل از خود وابستگی به سرویس‌های ارسال ایمیل را حذف کرده است و به جای آن از پارامترهای تزریق شده از طریق کانستراکتور برای ارتباط با سرویس‌ها استفاده می‌کند. این کار باعث می‌شود که کلاس ایمیل قابل‌تغییر و باز است و ما می‌توانیم به راحتی سرویس‌های دیگر را برای ارسال ایمیل به برنامه اضافه کنیم بدون نیاز به تغییر در کلاس ایمیل خود. همچنین، این الگو به ما کمک می‌کند که کلاس‌هایمان را قابل‌تست کنیم.

ادامه در پست بعدی ...
.
#design_patterns

... ادامه پست قبلی

در مثال بالا با تزریق وابستگی ها از طریق کاستراکتور آشنا شدیم، اما راه های دیگری نیز وجود دارد. شامل:
1 - Setter Injection :
در این روش، به جای تزریق وابستگی‌ها از طریق کانستراکتور، از متدهای Setter کلاس استفاده می‌کنیم تا وابستگی‌ها را تنظیم کنیم.
class EmailSender {
private $mailer;

public function setMailer(MailerInterface $mailer) {
$this->mailer = $mailer;
}

public function sendEmail($to, $subject, $body) {

}
}

$smtpMailer = new SmtpMailer();
$emailSender = new EmailSender();
$emailSender->setMailer($smtpMailer);
$emailSender->sendEmail('user@example.com', 'Test Subject', 'Test Body');

————

2 - Method Injection :
در این روش، وابستگی‌ها را به صورت آرگومان‌های ورودی به متدها تزریق می‌کنیم.
class EmailSender {
public function sendEmail($to, $subject, $body, MailerInterface $mailer) {

}
}

$smtpMailer = new SmtpMailer();
$emailSender = new EmailSender();
$emailSender->sendEmail('user@example.com', 'Test Subject', 'Test Body', $smtpMailer);

————

3 -
Container (IoC) Injection :
در این روش، از یک کانتینر (Container) نرم‌افزاری برای ایجاد شئ ها و تزریق وابستگی‌ها استفاده می‌شود. این کانتینر مسئول ایجاد و مدیریت شئ ها و تزریق وابستگی‌ها به طور خودکار است.
$container = new Container();

$container->register('mailer', SmtpMailer::class);
$container->register('emailSender', EmailSender::class)->withArgument('mailer');
$emailSender = $container->get('emailSender');
$emailSender->sendEmail('user@example.com', 'Test Subject', 'Test Body');

تمام این روش‌ها برای تزریق وابستگی‌ها مناسب هستند و انتخاب بین آن‌ها بستگی به نیازها و معماری کد شما دارد. استفاده از Dependency Injection باعث کاهش وابستگی‌ها و افزایش انعطاف‌پذیری و قابلیت تست کد می‌شود.
.
👍2
#design_patterns
دیزاین پترن Template Method یکی از الگوهای رفتاری است که در طراحی نرم‌افزارها مورد استفاده قرار می‌گیرد. این الگو به شما امکان می‌دهد یک چارچوب اصلی برای یک الگوریتم تعریف کنید که بخش‌هایی از آن را به کلاس‌های زیرمجموعه خود می‌سپارید تا به صورت مستقل اجرا شوند. با این روش، تغییرات در الگوریتم اصلی به کلاس‌های زیرمجموعه انتقال پیدا نمی‌کند و همچنین از دسترسی به متدهای مشترک و ارتباط موثر با آن‌ها برخوردار خواهید بود.

فرض کنید که می‌خواهیم یک کلاس برای ساخت یک نوشیدنی دم‌نوش تعریف کنیم که از دو مرحله پیش‌تهیه (Prepare) و تهیه (Brew) تشکیل شده است. این کلاس باید اجازه دهد که بخش‌هایی از فرآیند دم‌نوش‌سازی توسط subclass ها (نمونه‌ها) اجرا شوند.

مثال:
ابتدا این کلاس یک الگوریتم اصلی برای ساخت نوشیدنی دم‌نوش ارائه می‌دهد که شامل مراحل Prepare و Brew است.
abstract class Beverage
{
public function makeBeverage()
{
$this->boilWater();
$this->brew();
$this->pourInCup();
$this->addCondiments();
}

public function boilWater()
{
echo "Boiling water...\n";
}

public function pourInCup()
{
echo "Pouring into cup...\n";
}

// Methods required by subclasses must be defined here
abstract public function brew();
abstract public function addCondiments();
}

سپس subclass ها با توجه به نوشیدنی موردنظر، متدهای brew و addCondiments را پیاده‌سازی می‌کنند.
class Tea extends Beverage
{
public function brew()
{
echo "Steeping the tea...\n";
}

public function addCondiments()
{
echo "Adding lemon...\n";
}
}

class Coffee extends Beverage
{
public function brew()
{
echo "Dripping coffee through filter...\n";
}

public function addCondiments()
{
echo "Adding sugar and milk...\n";
}
}

حالا می‌توانیم از کلاس‌ها و زیرکلاس‌های آن‌ها برای ساخت نوشیدنی دم‌نوش استفاده کنیم.
$tea = new Tea();
$tea->makeBeverage();

Result:
Boiling water...
Steeping the tea...
Pouring into cup...
Adding lemon...

$coffee = new Coffee();
$coffee->makeBeverage();

Result:
Boiling water...
Dripping coffee through filter...
Pouring into cup...
Adding sugar and milk...

در این مثال، با استفاده از دیزاین پترن Template Method، یک چارچوب اصلی برای ساخت نوشیدنی دم‌نوش با مراحل مشترک boilWater و pourInCup تعریف کردیم و بخش‌های خاص هر نوشیدنی را در subclass ها تعیین کردیم. این الگو باعث از دست رفتن تکرار کد، افزایش قابلیت توسعه و حفظ ساختار یکپارچه‌ای در کلاس‌ها می‌شود.
.
🔥1