Интерполиране на променливи в низ, идващ от ДБ

explozen

Registered
Здравейте :dance:

Опитвам се да направя някакво фокусче но явно не съм добър факир :naughty:

Използвам mail() за да изпращам имейли. Функцията си работи без проблем. Искам да направя следното:
В базата записвам шаблон на имейл в който шаблон има променливи. Целта ми е този запис да го извикам в темплейта и тези променливи да си работят. Когато си извикам променливите директно в имейла те си работят без проблем. Когато ги извиквам от базата, резултата е следния:
Код:
Hello, $row[client_name]<p>Your service $row[support_service] expired. End date: $row[date_end]</p>
Това е получен имейл...

Ще бъда благодарен ако някой ми даде съвет както да го направя :angelic-flying:
 
така би трябвало да изведе резултатите:
Код:
<?php
echo "Hello, $row['client_name']<p>Your service $row['support_service'] expired. End date: $row['date_end']</p>";
?>
 
Да разбираме, че в базата имаш запазен следния стринг:

Код:
'Hello, $row[client_name]<p>Your service $row[support_service] expired. End date: $row[date_end]</p>'

И искаш като го вземеш с PHP, променливите автоматично да се попълнят?

Можеш да си направиш някакви placeholderи, с които да кодираш местата, на които искаш да застанат променливите, и след това със string_replace да извършиш заместването.

Например, вместо горния стринг, в базата ще пазиш нещо такова:

Код:
'Hello, $$client_name$$<p>Your service $$support_service$$ expired. End date: $$date_end$$</p>'

И когато вземеш този низ в променлива, за да го изпратиш с mail, ще направиш нещо такова

Код:
$parsed_str = str_replace($str_from_db, [ '$$client_name$$', .... ], [ $row["client_name"], .... ])
Където в двата масива изредаш нещата, които заместваш.
 
systems каза:
така би трябвало да изведе резултатите:
Код:
<?php
echo "Hello, $row['client_name']<p>Your service $row['support_service'] expired. End date: $row['date_end']</p>";
?>

Няма да се получи с echo защото така попълвам функцията:
Код:
email_send(
            $expiryRow['mail_from'],
            $row['client_email'],
            $expiryRow['e3_days_notifications_mail_subject'],
            "$expiryRow[e3_days_notifications_mail_text]"
        );
 
има вариянт:

Код:
<?php
email_send(
echo    "$expiryRow['mail_from'],
            $row['client_email'],
            $expiryRow['e3_days_notifications_mail_subject'],
            $expiryRow[e3_days_notifications_mail_text]"
        );
?>
 
systems каза:
има вариянт:

Код:
<?php
email_send(
echo    "$expiryRow['mail_from'],
            $row['client_email'],
            $expiryRow['e3_days_notifications_mail_subject'],
            $expiryRow[e3_days_notifications_mail_text]"
        );
?>
Ехото печата на изхода и не връща нищо: https://www.php.net/manual/en/function.echo.php
Така че да подадеш void аргумент на функция ще е невалидно.
 
Тъй като възникна въпрос на ЛС, ще разясня малко по-подробно какво имах предвид.

В PHP суровите низови литерали (грр, българска терминология, raw string literals :D), заградени с двойни кавички, автоматично интерполират променливите, които са изписани в тях.
Това означава, че когато види следното:

Код:
$var = "Love WebTourist";
echo "В променливата има: $var";

PHP интерпретаторът ще замести стойността на $var в низа след 'echo'-то, и по този начин ще се отпечатат слепените стойности.

Това, обаче е съвсем различно от следното:

Код:
// когато в URLто има следното: file.php?userInput=$val
$val = 'Hidden value';
echo $_GET['userInput'];

Ако в променливата от потребителя е записано име на някоя променлива (в горния случай - $val), то тя няма да се интерполира.
Интерполират се единствено низове, записани директно в кода.

В противен случай, някой зъл хакер би могъл така да ви прочете всичките променливи, ако поиска.

Затова и в горния случай няма да се отпечата 'Hidden value', а самият символ 'доларче', последвано от 'val': '$val'.
Низът не е hardcode-нат в скрипта, не е изписан в явен вид. А интерполиране се случва само в този случай.

В твоя случай с mail-а, имаш същата ситуация - низ, който не е hardcode-нат в програмата, а идва от БД. Съответно, в него интерполиране на променливите не се случва.
Затова се налага да правиш някакви логистики с разни placeholderи и ръчно да имплементираш заместването.
 
anonimen каза:
Да разбираме, че в базата имаш запазен следния стринг:

Код:
'Hello, $row[client_name]<p>Your service $row[support_service] expired. End date: $row[date_end]</p>'

И искаш като го вземеш с PHP, променливите автоматично да се попълнят?

Можеш да си направиш някакви placeholderи, с които да кодираш местата, на които искаш да застанат променливите, и след това със string_replace да извършиш заместването.

Например, вместо горния стринг, в базата ще пазиш нещо такова:

Код:
'Hello, $$client_name$$<p>Your service $$support_service$$ expired. End date: $$date_end$$</p>'

И когато вземеш този низ в променлива, за да го изпратиш с mail, ще направиш нещо такова

Код:
$parsed_str = str_replace($str_from_db, [ '$$client_name$$', .... ], [ $row["client_name"], .... ])
Където в двата масива изредаш нещата, които заместваш.

https://www.php.net/manual/en/function.sprintf.php
 
uphero каза:
anonimen каза:

https://www.php.net/manual/en/function.sprintf.php

Вариант, но така се обвръзва с подредбата на променливите. Ако реши да ги размести, ще трябва да оправя кода, а не само записа в таблицата.
 
anonimen каза:
Да разбираме, че в базата имаш запазен следния стринг:

Код:
'Hello, $row[client_name]<p>Your service $row[support_service] expired. End date: $row[date_end]</p>'

И искаш като го вземеш с PHP, променливите автоматично да се попълнят?

Можеш да си направиш някакви placeholderи, с които да кодираш местата, на които искаш да застанат променливите, и след това със string_replace да извършиш заместването.

Например, вместо горния стринг, в базата ще пазиш нещо такова:

Код:
'Hello, $$client_name$$<p>Your service $$support_service$$ expired. End date: $$date_end$$</p>'

И когато вземеш този низ в променлива, за да го изпратиш с mail, ще направиш нещо такова

Код:
$parsed_str = str_replace($str_from_db, [ '$$client_name$$', .... ], [ $row["client_name"], .... ])
Където в двата масива изредаш нещата, които заместваш.

Не знам какво направих но сега в имейла получавам просто Array :D

Код:
  $parsed_str = str_replace($expiryRow['e3_days_notifications_mail_text'], [ '$$client_name$$' ], [ $row["client_name"] ]);

if($e3_days_notifications == 1){
    if ($date_end == $today_date_minus_3_days) {
        if(basename(__FILE__)==basename($_SERVER['PHP_SELF']))echo email_send(
            $expiryRow['mail_from'],
            $row['client_email'],
            $expiryRow['e3_days_notifications_mail_subject'],
            "$parsed_str"
        );
    } 
  }
    }

Играх си доста но не успях да го направя....
 
По-бързо ще е, ако вместо да пращаш мейл, директно печаташ на екрана. И чак като го подкараш, тогава да го пуснеш да праща мейли.

Дай var_dump($parsed_str), че нещо не виждам на око откъде може да е проблемът.
 
anonimen каза:
По-бързо ще е, ако вместо да пращаш мейл, директно печаташ на екрана. И чак като го подкараш, тогава да го пуснеш да праща мейли.

Дай var_dump($parsed_str), че нещо не виждам на око откъде може да е проблемът.

$parsed_str връща пълен масив. Това с печатането първо звучи ок но не ми хвумва как да го подкарам така...
 
explozen каза:
anonimen каза:
По-бързо ще е, ако вместо да пращаш мейл, директно печаташ на екрана. И чак като го подкараш, тогава да го пуснеш да праща мейли.

Дай var_dump($parsed_str), че нещо не виждам на око откъде може да е проблемът.

$parsed_str връща пълен масив. Това с печатането първо звучи ок но не ми хвумва как да го подкарам така...

https://www.php.net/manual/en/function.str-replace.php

Виж, аргументите съм ги дал наобратно. $subject трябва да е последен. Странно :D. Това като оправиш, вече трябва да замества правилно.
 
anonimen каза:
explozen каза:
anonimen каза:
По-бързо ще е, ако вместо да пращаш мейл, директно печаташ на екрана. И чак като го подкараш, тогава да го пуснеш да праща мейли.

Дай var_dump($parsed_str), че нещо не виждам на око откъде може да е проблемът.

$parsed_str връща пълен масив. Това с печатането първо звучи ок но не ми хвумва как да го подкарам така...

https://www.php.net/manual/en/function.str-replace.php

Виж, аргументите съм ги дал наобратно. $subject трябва да е последен. Странно :D. Това като оправиш, вече трябва да замества правилно.

Може би не аз не обясних като хората :D
subject и другите са си ок, имам проблем с "$expiryRow[e3_days_notifications_mail_text]".
Тези замествания трябва да се случват в това: $expiryRow[e3_days_notifications_mail_text]...
 
Таблица;
Код:
CREATE TABLE `email_templates` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `type` enum('contact_us','registration') COLLATE utf8_unicode_ci NOT NULL,
 `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `content` text COLLATE utf8_unicode_ci NOT NULL,
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Код:
$userName  = 'Казвам се турист';
$userEmail = 'turist@example.com';

$query = $db->query("SELECT * FROM `email_templates` WHERE type = 'contact_us'"); //вземаш темплейта
$tempData = $query->fetch_assoc();

//правиме замянка на променливите
$token = array(
    'SITE_URL'  => 'http://www.web-tourist.net',
    'SITE_NAME' => 'Аз съм турист',
    'USER_NAME' => $userName,
    'USER_EMAIL'=> $userEmail
);
$pattern = '[%s]';
foreach($token as $key=>$val){
    $varMap[sprintf($pattern,$key)] = $val;
}

$emailContent = strtr($tempData['content'],$varMap);

//изпращаме писмото
$to = $userEmail;
$subject = "Свържете се с нас;
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= 'From: Аз съм турист<sender@example.com>' . "\r\n";
if(mail($to,$subject,$emailContent,$headers)) {
    $successMsg = 'Изпратено';
} else {
    $errorMsg = 'Възникна грешка';
}


Както по-горе стана въпрос:

$msg = str_replace("[NAME]", $sub['name'], $template);
[NAME] - променлива, която се променя
$sub['name'] - променлива , която ще промени горната [NAME]
$template - променлива, която взема текста (HTML) от базата данни.
 
explozen каза:
anonimen каза:
explozen каза:
$parsed_str връща пълен масив. Това с печатането първо звучи ок но не ми хвумва как да го подкарам така...

https://www.php.net/manual/en/function.str-replace.php

Виж, аргументите съм ги дал наобратно. $subject трябва да е последен. Странно :D. Това като оправиш, вече трябва да замества правилно.

Може би не аз не обясних като хората :D
subject и другите са си ок, имам проблем с "$expiryRow[e3_days_notifications_mail_text]".
Тези замествания трябва да се случват в това: $expiryRow[e3_days_notifications_mail_text]...

Да, този аргумент трябва да го подадеш последен на str_replace(). Просто го махни отпред и го сложи отзад, трябва да тръгне.
 
anonimen каза:
explozen каза:
anonimen каза:
https://www.php.net/manual/en/function.str-replace.php

Виж, аргументите съм ги дал наобратно. $subject трябва да е последен. Странно :D. Това като оправиш, вече трябва да замества правилно.

Може би не аз не обясних като хората :D
subject и другите са си ок, имам проблем с "$expiryRow[e3_days_notifications_mail_text]".
Тези замествания трябва да се случват в това: $expiryRow[e3_days_notifications_mail_text]...

Да, този аргумент трябва да го подадеш последен на str_replace(). Просто го махни отпред и го сложи отзад, трябва да тръгне.

Добрееее... Успях да го направя но само за client_name. Другото си е както преди:
Hello, Гошо Георгиев
Your service $$support_service$$ expired. End date: $$date_end$$

Как мога да го направя за всяка променлива да заменя?

Те са 4-5 на брой.
 
Справих се :D
Направих го така:
Код:
  $searchArray = array('$$client_name$$', '$$support_service$$', '$$date_start$$', '$$date_end$$', '$$today_date$$');
 
  $replaceArray = array($row["client_name"], $row["support_service"], $row["date_start"], $row["date_end"], $row["today_date"]);
      
  $ready = str_replace($searchArray, $replaceArray, $e3_days_notifications_mail_text2);
 
Е затова беше многоточието, да си попълниш всичките променливи :)
 

Горе