| کانال توسعه‌دهندگان PHP |
1.66K subscribers
48 photos
1 video
60 links
⭕️ کانال توسعه‌دهندگان پی‌اچ‌پی (PHP) دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
📌 سوال برای توسعه‌دهندگان PHP

خروجی اجرای کد زیر در PHP چیست؟

به رفتار reference در foreach و تأثیر آن روی آرایه اصلی دقت کنید و در نهایت، مقدار چاپ‌شده را بنویسید.

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
👎2👍1
‏اصل Single Responsibility در کدهای PHP 🧱

یکی از مهم‌ترین اصول SOLID که روی تمیزی کد PHP تاثیر مستقیم دارد، Single Responsibility Principle (SRP) است؛ یعنی هر کلاس فقط یک دلیل برای تغییر داشته باشد.

وقتی همه‌چیز را در یک کلاس می‌ریزیم، بعد از مدتی هر تغییر کوچک تبدیل می‌شود به کابوس ریفکتور، با ده‌ها باگ پنهان 😅

نمونه کد بد (نقض SRP) 👇
<?php

class UserService
{
public function register(string $email, string $password): void
{
// 1) validation
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email');
}

if (strlen($password) < 8) {
throw new InvalidArgumentException('Weak password');
}

// 2) save to database
// imagine: DB queries here...

// 3) send welcome email
mail($email, 'Welcome', 'Thanks for registering');
}
}

در این کلاس، UserService هم validation انجام می‌دهد، هم کار دیتابیس، هم ارسال ایمیل. سه دلیل برای تغییر در یک کلاس؛ این یعنی خلاف SRP.

ریفکتور با SRP ✅
هر بخش را به مسئولیت خودش محدود می‌کنیم:

<?php

class UserValidator
{
public function validate(string $email, string $password): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email');
}

if (strlen($password) < 8) {
throw new InvalidArgumentException('Weak password');
}
}
}

class UserRepository
{
public function save(string $email, string $password): void
{
// persist user to DB (PDO / ORM / ...)
}
}

class Mailer
{
public function sendWelcome(string $email): void
{
// use real mailer here
}
}

class UserService
{
public function __construct(
private UserValidator $validator,
private UserRepository $repository,
private Mailer $mailer,
) {}

public function register(string $email, string $password): void
{
$this->validator->validate($email, $password);
$this->repository->save($email, $password);
$this->mailer->sendWelcome($email);
}
}

حالا:

• تغییر قوانین پسورد فقط روی UserValidator اثر دارد 🔐

• تغییر دیتابیس یا ORM فقط در UserRepository انجام می‌شود 🗄️

• سوییچ از mail() به مثلاً Symfony Mailer فقط در Mailer عوض می‌شود 📧

چرا این ساختار در پروژه واقعی PHP (مثلاً Laravel) جواب می‌دهد؟

در فریم‌ورک‌هایی مثل Laravel و Symfony همین ایده تکرار شده: Form Requestها برای validation، Repository / Model برای persistence، و Service / Mailer برای بیزنس لاجیک و ایمیل. SRP دقیقا پشت این تفکیک قرار دارد.

یک قدم ساده مثل جدا کردن validation و ایمیل از کلاس اصلی، کد را:

• قابل تست‌تر می‌کند (Unit Test روی هر کلاس جدا)

• قابل ریفکتورتر می‌کند

• خوانایی تیمی را بالا می‌برد

موقع نوشتن کلاس بعدی، فقط از خودت بپرس:
این کلاس دقیقاً مسئول چه کاری است؟ اگر جواب بیشتر از یک جمله شد، یعنی وقت ریفکتور است 😉

منابع پیشنهادی برای مطالعه بیشتر:
PHP The Right Way - SOLID
Single Responsibility Principle (Wikipedia)


🔖 #PHP #پی_اچ_پی #PHP #Clean_Code #SOLID #SRP #Architecture

👤 Developix

💎 Channel: @DevelopixPHP
👍3❤2
🇮🇷 مخزن داخلی WP Mirror

این مخزن برای افرادی که دسترسی به اینترنت بین‌المللی ندارند ایجاد شده و به راحتی از طریق اینترنت داخلی قابل دسترسی است. در حال حاضر شامل ۴۰۰ پلاگین اورجینال و رایگان از مخزن رسمی وردپرس است که بدون هیچ‌گونه دستکاری و تغییر در اختیار شما قرار گرفته. به زودی پلاگین‌های بیشتری به این مجموعه اضافه خواهد شد.

برای دریافت آخرین آپدیت‌ها به صورت رایگان، از لینک زیر استفاده کنید:

http://wpexperts.ir

مخزن به صورت هفتگی آپدیت می‌شود.

🔖 #PHP #پی_اچ_پی

👤 Mojtaba

💎 Channel: @DevelopixPHP
👎7❤1
اگه تا حالا خواستی یه لاگین سبک برای SPA، موبایل یا حتی فرم ساده خودت بسازی، یه API لاگین کوچیک با PHP خالص می‌تونه عالی باشه؛ مخصوصاً وقتی با سبک مدرن و OOP نوشته بشه 😊

ایده این پست بر اساس ترکیبی از مستند رسمی PHP و چند نمونه‌کار تمیز روی GitHub هست (مثل ریپوهای سبک login API با PDO). تمرکز روی اینه که یه ساختار تمیز، قابل‌گسترش و امن‌تر نسبت به کدهای قدیمی و procedural داشته باشیم.

سناریو 🔎
می‌خوای یه endpoint مثل /api/login.php داشته باشی که:

• JSON از کلاینت بگیره (email و password)
• یوزر رو توی دیتابیس MySQL چک کنه
• پسورد رو با password_hash و password_verify هندل کنه
• در جواب، JSON تمیز برگردونه

چند نکته مهم قبل از کد 🧠
• حتماً PDO با prepared statement استفاده کن، نه query خام.
• همیشه Content-Type: application/json رو ست کن.
• خطاها رو JSON برگردون، نه echo ساده.

نمونه ساختار ساده API لاگین 🧩
این یه مثال مینیمال و قابل‌اجراست (فرض بر اینه که جدول users با ستون‌های id، email، password داری و پسوردها با password_hash ذخیره شدن):

<?php
// api/login.php

declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');

class DB
{
private \PDO $pdo;

public function __construct()
{
$dsn = 'mysql:host=localhost;dbname=myapp;charset=utf8mb4';
$user = 'db_user';
$pass = 'db_pass';

$this->pdo = new \PDO($dsn, $user, $pass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
]);
}

public function findUserByEmail(string $email): ?array
{
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE email = :email LIMIT 1');
$stmt->execute(['email' => $email]);
$user = $stmt->fetch();
return $user ?: null;
}
}

class LoginController
{
public function __construct(private DB $db) {}

public function handle(): void
{
$input = json_decode(file_get_contents('php://input'), true);

if (!isset($input['email'], $input['password'])) {
http_response_code(400);
echo json_encode(['error' => 'invalid_payload']);
return;
}

$user = $this->db->findUserByEmail($input['email']);
if (!$user || !password_verify($input['password'], $user['password'])) {
http_response_code(401);
echo json_encode(['error' => 'invalid_credentials']);
return;
}

echo json_encode([
'id' => (int) $user['id'],
'email' => $user['email'],
]);
}
}

$db = new DB();
$controller = new LoginController($db);
$controller->handle();


چرا این سبک خوبه؟ ⚙️
• کلاس DB جداست، بعداً راحت می‌تونی لاگ، کش یا تست واحد براش بنویسی.
• LoginController فقط روی لاجیک لاگین تمرکز داره، نه اتصال به دیتابیس.
• از strict_types و type hint استفاده شده که با PHP مدرن هماهنگه.

برای عمیق‌تر شدن توی این سبک، مستند رسمی PHP درباره PDO و همچنین بخش password hash و password_verify خیلی کمک‌کننده است.

این ساختار کوچیک رو بردار، توی پروژه‌هات امتحانش کن و با اضافه کردن token (مثلاً JWT) یا session، تبدیلش کن به یه auth کامل‌تر. تجربه‌هات رو هم با بقیه توسعه‌دهنده‌های PHP به اشتراک بذار 🔧💬

🔖 #PHP #پی_اچ_پی #PHP #Login_API #PDO #OOP #Authentication #Backend

👤 Developix

💎 Channel: @DevelopixPHP
👍3❤1
در نمونه‌کد بالا در بخش کد اشتباه برای گرفتن پست‌ها و کامنت‌ها در یک حلقه روی هر پست، یک Query جداگانه به دیتابیس ارسال شده است (مشکل معروف به N+1 Queries). این کار در اسکیل بالا فشار زیادی به دیتابیس وارد می‌کند و زمان پاسخ‌گویی را به‌شدت بالا می‌برد.

در کد صحیح با استفاده از with('comments.user') همه‌ی داده‌های مورد نیاز به‌صورت Eager Loading در چند Query محدود واکشی می‌شوند. به این ترتیب تعداد Queryها کاهش پیدا کرده، Latency پایین می‌آید و Performance در سناریوهایی مثل لیست کردن پست‌های صفحه‌ی اصلی یا Dashboard با تعداد زیاد رکورد به‌مراتب بهتر می‌شود.

اگر در پروژه‌ی PHP/Laravel خود با Modelهای مرتبط زیاد سروکار دارید، به جای دسترسی تنبلی (Lazy Loading) داخل حلقه، از Eager Loading استفاده کنید تا هم Queryهای غیرضروری حذف شوند و هم در Loadهای بالا دچار افت شدید سرعت و فشار روی دیتابیس نشوید.

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
در کد زیر، یک تابع برای trim کردن همه مقادیر یک آرایه چندبعدی نوشته شده است، اما نتیجه‌ی نهایی به‌درستی کار نمی‌کند و آرایه‌ی اصلی دچار رفتار عجیب می‌شود:


<?php

$data = [
['name' => ' Ali ', 'email' => ' ali@example.com '],
['name' => ' Sara ', 'email' => ' sara@example.com'],
];

function deepTrim(array $items): array
{
foreach ($items as &$row) {
foreach ($row as &$value) {
$value = trim($value);
}
}

return $items;
}

$result = deepTrim($data);

print_r($data);
print_r($result);


در این کد از reference در حلقه‌های foreach استفاده شده است و باعث بروز باگ پنهان در آرایه‌ی اصلی می‌شود.

چه چیزی باید در این کد اصلاح شود تا هم Memory Leak و هم رفتار غیرمنتظره روی آرایه‌ی اصلی برطرف شود؟

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
خروجی نهایی اجرای این کد در PHP چیست؟

توجه کنید که از closure بازگشتی و متغیر static داخل تابع استفاده شده است و ترتیب فراخوانی تابع اهمیت دارد.

<?php

function makeCounter() {
static $base = 1;
$multiplier = 2;

$f = function($n) use (&$f, $multiplier) {
static $inner = 0;
$inner += $n;
if ($n <= 1) {
return $inner * $multiplier;
}
return $f($n - 1) + $inner;
};

$result = $f($base + 2);
$base += 2;

return $result;
}

echo makeCounter() . "\n";
echo makeCounter() . "\n";


خروجی دقیق این اسکریپت (دو خط echo شده) را بنویسید.

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
خروجی اجرای این کد در PHP چیست؟


$val = "9";

for ($i = 0; $i < 3; $i++) {
$val++;
}

echo $val . "\n";

$val2 = "A9";
$val2++;

echo $val2 . "\n";

$val3 = "09";
$val3++;

echo $val3 . "\n";


به ترتیب سه خط خروجی این اسکریپت را بنویس.


🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
👍1
اگه برای هر صفحه‌ی پروژه‌ی PHP خودت یه فایل جدا مثل about.php، contact.php و ... می‌سازی، کم‌کم همه‌چی شلوغ و سخت‌قابل‌مدیریت می‌شه. یه Router ساده می‌تونه کل مسیرها رو تمیز و قابل‌گسترش کنه، حتی بدون استفاده از فریم‌ورکی مثل Laravel 👌

این پست بر اساس ایده‌ها و الگوی PSR-7 و نمونه‌های ساده‌ای مثل klein.php یه روتر سبک رو نشون می‌ده که به راحتی تو هر پروژه PHP 8 می‌تونی استفاده‌اش کنی.

ایده‌ی اصلی چیه؟

✅ همه‌ی request ها از یه index.php رد بشن (Front Controller)

✅ بر اساس REQUEST_METHOD و REQUEST_URI، تابع یا Controller مناسب صدا زده بشه

✅ کدهای صفحه‌ها به‌جای پخش شدن، در توابع/کلاس‌ها باشن

ساخت یک Router خیلی ساده

تو public روت پروژه، یه index.php بساز و کد زیر رو بذار:

<?php

declare(strict_types=1);

$routes = [
'GET' => [
'/' => function () {
echo 'Home Page';
},
'/about' => function () {
echo 'About Page';
},
],
'POST' => [
'/contact' => function () {
echo 'Form submitted';
},
],
];

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);

if (isset($routes[$method][$uri])) {
$handler = $routes[$method][$uri];
$handler();
} else {
http_response_code(404);
echo '404 Not Found';
}


الان وقتی بری به / یا /about یا با POST بری به /contact، روترت دقیقا می‌دونه چی رو اجرا کنه 🙌

یه کم تمیزتر با کلاس

می‌تونی روتر رو تو یه کلاس بذاری (مثلا src/Router.php) و با composer و autoload استفاده‌اش کنی. نمونه‌ی خیلی شبیه به این ساختار رو تو پروژه‌های کوچیک GitHub مثل "simple-php-router" راحت پیدا می‌کنی و می‌تونی ایده بگیری.

چرا این کار مفیده؟

• اضافه کردن route جدید فقط با یه خط تو آرایه انجام می‌شه 🔧
• بعدا می‌تونی middleware، auth، یا JSON API رو راحت اضافه کنی
• قدم اولیه برای مهاجرت به معماری تمیزتر و نزدیک‌تر به استانداردهایی مثل PSR هست

امتحانش کن، یه پروژه کوچیک بساز و چند تا route تعریف کن. اگه برات مفید بود، برای بقیه‌ی PHP dev ها هم بفرست تا اون‌ها هم از این ساختار تمیزتر لذت ببرن 👨‍💻👩‍💻

🔖 #PHP #پی_اچ_پی #PHP #Routing #Web #Backend #Modern_PHP #PSR

👤 Developix

💎 Channel: @DevelopixPHP
👍5
‍ساخت فرم لاگین امن با PHP با استفاده از password_hash 🔐

خیلی از پروژه‌های PHP هنوز از md5 یا sha1 برای ذخیره پسورد استفاده می‌کنن و این یعنی دردسر امنیتی 😅
بیایم یه لاگین ساده ولی استاندارد بسازیم که روی password_hash و password_verify سوار باشه؛ همون چیزی که توی داک رسمی PHP هم پیشنهاد شده:
php.net/manual/en/function.password-hash.php

ایده کلی اینه:

• سمت دیتابیس فقط hash پسورد ذخیره می‌شه، نه خود پسورد.
• برای ساخت یوزر جدید از password_hash استفاده می‌کنیم.
• برای لاگین از password_verify کمک می‌گیریم.
• بعد از لاگین موفق، یه session امن راه می‌ندازیم.

این یه مثال خیلی مینیمال و قابل‌استفاده توی پروژه‌های کوچیکه 👇

<?php
// config.php
$pdo = new PDO(
'mysql:host=localhost;dbname=test;charset=utf8mb4',
'db_user',
'db_pass',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);

// register.php - ساخت یوزر جدید
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
exit('ایمیل نامعتبر است');
}

if (strlen($password) < 8) {
exit('پسورد باید حداقل 8 کاراکتر باشد');
}

$hash = password_hash($password, PASSWORD_DEFAULT);

$stmt = $pdo->prepare('INSERT INTO users (email, password_hash) VALUES (:email, :hash)');
$stmt->execute([
':email' => $email,
':hash' => $hash,
]);

echo 'ثبت‌نام با موفقیت انجام شد ✅';
}

// login.php - لاگین یوزر
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';

$stmt = $pdo->prepare('SELECT id, password_hash FROM users WHERE email = :email');
$stmt->execute([':email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$user || !password_verify($password, $user['password_hash'])) {
exit('ایمیل یا پسورد اشتباه است');
}

session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];

echo 'خوش اومدی! 🎉';
}


نکته‌ها و ترفندهای کوچیک ولی مهم:

• الگوریتم داخلی PASSWORD_DEFAULT ممکنه در آینده عوض بشه، ولی همون برای اکثر سناریوها عالیه.
• با password_needs_rehash می‌تونی موقع لاگین، hashهای قدیمی رو خودکار به نسخه‌ی جدیدتر migrate کنی (مثلاً وقتی cost رو عوض کردی).
• حتماً روی ستون پسورد توی دیتابیس حداقل طول 255 بگذار تا با تغییر الگوریتم‌های آینده مشکل نداشته باشی.
• از PDO prepared statement استفاده کن که جلوی SQL Injection رو بگیره، مثل همین نمونه.
• بعد لاگین، session_regenerate_id رو فراموش نکن تا Session Fixation اتفاق نیفته.

این الگو پایه‌ی خیلی از سیستم‌های auth امروزی توی PHP ـه و راحت می‌شه بعداً روش چیزهایی مثل remember me، محدودیت تلاش لاگین، و لاگ آدیت اضافه کرد.

امتحانش کن روی یه پروژه کوچیک، اگر جواب داد همون رو تمیزتر کن و بذار توی پروژه‌های اصلی‌ات 💻

🔖 #PHP #پی_اچ_پی #PHP #Authentication #Security #Password_Hashing #Login #PDO

👤 Developix

💎 Channel: @DevelopixPHP
👍4👎2
✴️ جست‌وجوی تکراری روی آرایه بزرگ توی حلقه

توی قطعه‌کد اول هر بار داخل حلقه array_search صدا زده شده؛ یعنی اگه ۱۰هزار تا یوزر داشته باشی و لیست بلاک‌ها هم بزرگ باشه، عملاً می‌زنی دیتای خودت رو با دست خودت دی‌داس می‌کنی 😅

توی نسخهٔ دوم، اول یه lookup table می‌سازیم و بعد توی حلقه فقط روی یه isset ساده چک می‌کنیم؛ هم خواناتر می‌شه هم از نظر Time Complexity از O(n×m) می‌آد پایین به O(n+m) و فشار روی CPU به‌شدت کمتر می‌شه.

اگر قراره داخل حلقه روی آرایه بزرگ سرچ کنی، قبلش ساختار داده‌ات رو برای lookup بهینه کن؛ معمولاً یه array_flip یا یه array_fill_keys درست‌حسابی، نصف bottleneck رو جمع می‌کنه.


🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
🔥4
‏یک قطعه‌کد زیر را در نظر بگیرید (زبان: PHP). تمرکز روی رفتار generator و ارجاع‌ها است.

به‌نظر شما خروجی اجرای این اسکریپت چیست؟

خروجی را دقیقاً همان‌طور که در ترمینال چاپ می‌شود (با ترتیب و جداکننده‌ها) حدس بزنید.

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
🔥 پکیج: استاندارد PSR-11 برای Container

استاندارد PSR-11 فقط یه interface مشترک برای Containerهاست؛ خودش DI Container نیست، ولی باعث می‌شود بین فریم‌ورک‌ها و کتابخانه‌ها راحت‌تر سوییچ کنی ✅

هر کتابخانه‌ای که از PSR-11 پیروی کند، فقط با یک type-hint ساده مثل Psr\Container\ContainerInterface با هر Container سازگار می‌شود.

برای جزئیات بیشتر، خود استاندارد را این‌جا ببین:
لینک PSR Container

📥 دانلود: 1,102,739,550
⭐️ 10,032 علاقه‌مند

🔖 #PHP #پی_اچ_پی #PHP #PSR_11 #Container

💎 @DevelopixPHP
👍2
برنامه نویسی سوکت در PHP بخش اول

عبارت دیگر در ارتباط های غیر سوکت برای ارسال یک پالس از سمت سرور به سمت کلاینت نیاز داریم که ابتدا یک درخواست به سمت سرور بدهیم تا بعد پاسخ را دریافت کنیم ولی در ارتباط سوکت می توان مستقیم از سرور به کلاینت ( یا کلاینت ها ) درخواست ارسال کنیم.

تصویر زیر نمونه یک ارتباط مانا میان یک کلاینت و یک سرور ( دو node در سوکت ) روی یک پورت می باشد. این ارتباط با ارسال یک پالس از سمت سرور به کلاینت شروع می شود و در ادامه پس از گذشت زمان دو پالس از سمت کلاینت به سرور می آید.

https://gnutec.net/socket-programming-in-php-part-1/

🔖 #PHP #پی_اچ_پی

👤 ابوالفضل

💎 Channel: @DevelopixPHP
👍2
ارسال ایمیل تأیید ثبت‌نام، بازیابی رمز عبور یا نوتیفیکیشن سفارش، تقریباً توی هر پروژه‌ PHP جدی لازم می‌شود. این‌جا با هم یک ماژول ساده و تمیز با PHPMailer می‌سازیم که هم امن باشد، هم قابل‌گسترش. 😉

منبع اصلی‌ای که ایده‌ها ازش گرفته شده، داکیومنت رسمی و مثال‌های PHPMailer در گیت‌هاب است؛ حتماً ارزش یک نگاه عمیق‌تر را دارد. 🔍

۱️⃣ نصب PHPMailer با Composer
اول مطمئن شو روی سرور یا سیستم لوکال، Composer نصب است. بعد داخل رoot پروژه این دستور را بزن:
composer require phpmailer/phpmailer
حالا پوشه‌ vendor ساخته می‌شود و می‌توانی از Autoload استفاده کنی.

۲️⃣ ساخت یک کلاس EmailService تمیز
به‌جای این‌که هرجا لازم شد مستقیم شی‌ء PHPMailer بسازی، بهتر است یک کلاس سرویس داشته باشی تا کانفیگ SMTP فقط یک‌جا باشد و بعداً راحت عوض شود (مثلاً وقتی از Gmail رفتی روی Mailgun یا SMTP هاست).

یک فایل مثل EmailService.php بساز و ساختار را شبیه مثال زیر نگه دار 👇

<?php

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require __DIR__ . '/vendor/autoload.php';

class EmailService
{
private PHPMailer $mailer;

public function __construct()
{
$this->mailer = new PHPMailer(true);

// تنظیمات پایه SMTP
$this->mailer->isSMTP();
$this->mailer->Host = 'smtp.gmail.com';
$this->mailer->SMTPAuth = true;
$this->mailer->Username = 'your-email@gmail.com';
$this->mailer->Password = 'app-password-here';
$this->mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$this->mailer->Port = 587;

$this->mailer->setFrom('no-reply@yourapp.test', 'Your App');
$this->mailer->isHTML(true);
$this->mailer->CharSet = 'UTF-8';
}

public function send(string $to, string $subject, string $htmlBody): bool
{
try {
$this->mailer->clearAllRecipients();
$this->mailer->addAddress($to);
$this->mailer->Subject = $subject;
$this->mailer->Body = $htmlBody;

return $this->mailer->send();
} catch (Exception $e) {
error_log('Mail error: ' . $e->getMessage());
return false;
}
}
}


🔐 نکته مهم: برای Gmail باید از App Password استفاده کنی (نه پسورد عادی اکانت). راهنماش توی صفحه‌ رسمی گوگل موجود است و بدون این کار معمولاً اتصال SMTP بلاک می‌شود.

۳️⃣ استفاده در سناریوی واقعی
مثلاً بعد از ثبت‌نام، یک لینک فعال‌سازی بفرست:

$emailService = new EmailService();
$activationLink = 'https://yourapp.test/activate?token=' . urlencode($token);
$html = "سلام  {$userName}!<br>برای فعال‌سازی حسابت روی لینک زیر کلیک کن:<br><a href='{$activationLink}'>فعال‌سازی حساب";
$emailService->send($userEmail, 'فعالسازی حساب کاربری', $html);

🧩 چند نکته‌ تجربی کوتاه:
- لاگ ارور را حتماً جایی ذخیره کن تا اگر روی سرور ایمیل نرسید، راحت‌تر دیباگ شود.
- محتوا را هم HTML نگه دار، هم یک نسخه‌ متن ساده برای سازگاری بهتر با بعضی کلاینت‌ها (قابلیت AltBody در PHPMailer).
- اطلاعات SMTP و پسوردها را داخل فایل env. نگه دار، نه مستقیم داخل کلاس.

در هر پروژه‌ جدید، داشتن یک EmailService آماده کلی زمان ذخیره می‌کند. اگر این ساختار را کمی برای خودت شخصی‌سازی کنی، عملاً یک ماژول ایمیل قابل‌استفاده مجدد برای تمام پروژه‌های PHP خواهی داشت. 🚀

🔖 #PHP #پی_اچ_پی #PHP #PHPMailer #Email #SMTP #Backend #Security

👤 Developix

💎 Channel: @DevelopixPHP
🔥 پکیج: قراردادهای ترجمه سیمفونی

اگر کد PHP را برای چندزبانگی می‌نویسید، بهتر است منطق برنامه را به یک پیاده‌سازی مشخص ترجمه گره نزنید. پکیج Translation Contracts سیمفونی، قراردادهای مشترکی برای کار با ترجمه فراهم می‌کند تا وابستگی‌ها بر پایهٔ interface باشند، نه جزئیات اجرا.

برای کتابخانه‌هایی که باید با مترجم‌های مختلف سازگار بمانند، گزینهٔ قابل‌توجهی است. مستنداتش را در Packagist ببینید.

📥 دانلود: 802,393,817
⭐️ 2,585 علاقه‌مند

🔖 #PHP #پی_اچ_پی #PHP #Symfony #ترجمه

💎 @DevelopixPHP
👍2
این کد موقع اجرا چه خروجی‌ای می‌ده و مشکلش کجاست؟

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
افزونه CURL در PHP

برای ایجاد یک درخواست راه های متفاوتی وجود دارد. اگر درخواست از نوع GET باشد راه های ساده تری نظیر تابع file_get_content و یا افزونه DOM می باشد. برای ارسال درخواست از انواع دیگر متد ها مثل POST می توان از افزونه CURL استفاده کرد.
فرم ها نیز ابزارهایی جهت ارسال درخواست با پارامتر های خاص ( فیلد های فرم ) به یک آدرس خاص ( پارامتر action ) و با یک متد خاص ( پارامتر method ) می باشد. در حقیقت وقتی یک فرم را ارسال می کنیم از طریق متد ( method ) به یک url خاص ( action ) یک درخواست ارسال می کنیم. در این درخواست یک سری داده را نیز ارسال می کنیم ( همان مقادیر فیلد های فرم ) . در نوع درخواست به وسیله فرم کاربر نیز همراه با درخواست به وب سرویس می رود. سرعت پاسخ در curl نیز بسیار بالاتر از تابع file_get_content می باشد.

https://gnutec.net/curl-function-php/

🔖 #PHP #پی_اچ_پی

👤 ابوالفضل

💎 Channel: @DevelopixPHP
👍2
محاسبهٔ پول بدون دردسر float 💰

اگر در PHP جمع قیمت‌ها گاهی اعشار عجیب تولید می‌کند، مشکل از نمایش دودویی اعداد در float است. کتابخانهٔ Brick Math برای محاسبات عددی با دقت دلخواه ساخته شده؛ مناسب قیمت، مالیات و محاسبات حساس.

📌 با BigDecimal اعشار را دقیق نگه می‌داری، با BigInteger محدودیت اندازهٔ عدد صحیح را کنار می‌زنی و هنگام تقسیم، روش گرد کردن را صریح انتخاب می‌کنی. اشیای عددی هم immutable هستند؛ عملیات، مقدار قبلی را تغییر نمی‌دهد.

نصب با Composer:
composer require brick/math


نمونه در PHP:
<?php
require 'vendor/autoload.php';

use Brick\Math\BigDecimal;

$total = BigDecimal::of('0.1')
->plus('0.2');
echo $total; // 0.3


💡 ورودی اعشاری را رشته بده؛ تبدیل یک float خطادار به BigDecimal، دقت ازدست‌رفته را برنمی‌گرداند.

کد و مستندات رسمی

برای شروع، محاسبهٔ جمع سبد خرید را با آن پیاده کن. 🛠️

🔖 #PHP #پی_اچ_پی #PHP #BrickMath #BigDecimal #Precision

👤 Developix

💎 Channel: @DevelopixPHP
حلقه تموم شده، ولی ارجاع هنوز زنده‌ست!

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

توی کد اول، خروجی به‌جای [10,20,30] می‌شه [10,20,20].

با unset($value) بلافاصله بعد از حلقه اول، این اتصال رو قطع کن. این کار عضو آرایه رو حذف نمی‌کنه؛ فقط متغیرِ ارجاع‌دهنده رو از بین می‌بره.

🔖 #PHP #پی_اچ_پی

👤 Developix

💎 Channel: @DevelopixPHP
👍1