Динамически выполнять код coldfusion, хранящийся в строке?

У меня есть тело электронной почты, хранящееся в виде строки в базе данных, примерно так:

Это тело электронной почты, содержащее множество различных переменных. Уважаемый #name#, <br/> Пожалуйста, свяжитесь с #representativeName# для получения дополнительной информации.

Я извлекаю это поле из базы данных с помощью хранимой процедуры, а затем хочу оценить его на стороне coldfusion, чтобы вместо «#name#» было вставлено значение переменной name.

Я пытался использовать оценку, но, кажется, это работает, только если есть просто имя переменной. Выдает ошибку из-за другого текста.

(Я не могу просто использовать заполнители и поиск/замену, подобные этому - Разрешение переменных внутри строки Coldfusion, потому что весь смысл хранения этого в базе данных заключается в том, что переменные, используемые для построения строки, являются динамическими. Например, в одном случае поле имени может называться «имя», а в другом еще это может быть "firstName" и т. д.)


person froadie    schedule 09.11.2011    source источник
comment
извините, я до сих пор не понимаю, почему вы не можете использовать заполнитель.   -  person Henry    schedule 09.11.2011


Ответы (5)


Я бы перебирал каждую ссылку #variableName# и заменял ее оцененной версией.

Регулярное выражение сможет найти их все, а затем цикл, чтобы просмотреть их все и просто оценить их одну за другой.

person Dale Fraser    schedule 09.11.2011

Вам нужно записать его в файл и CFINCLUDE. Это повлечет за собой накладные расходы на компиляцию, но это неизбежно.

Можете ли вы не сохранять код в файловой системе и просто хранить ссылку на то, где он находится в БД? Таким образом, он будет перекомпилироваться только при изменении, а не каждый раз, когда вы будете его использовать?

<!--- pseudo code --->
<cfquery name="q">
    SELECT fileContent // [etc]
</cfquery>
<cfset fileWrite(expandPath("/path/to/file/to/write/code.cfm"), q.fileContent)>
<cfinclude template="/path/to/file/to/write/code.cfm">
<cfset fileDelete(expandPath("/path/to/file/to/write/code.cfm"))>

Это основная идея: получить код, написать код, включить код, удалить код. Хотя вы захотите убедиться, что создаваемый файл не сталкивается с каким-либо другим файлом (используйте UUID в качестве имени файла или что-то еще, согласно чьему-то предложению).

Вы также захотите выполнить нагрузочное тестирование. Сомневаюсь, что он будет работать очень хорошо. Другие предлагали использовать виртуальную файловую систему, но я не уверен, что это принесет большую пользу: время занимает процесс компиляции, а не фактические операции с файлами. Но это стоит исследовать.

person Adam Cameron    schedule 09.11.2011
comment
Есть несколько разных шаблонов, для которых потребуются несколько разных файлов... Может быть, я просто сделаю отдельное поле для каждой переменной и буду оценивать их по отдельности? - person froadie; 09.11.2011
comment
Однако я могу рассмотреть метод cfinclude... можете ли вы предоставить какой-нибудь базовый пример кода для этого? - person froadie; 09.11.2011

Вы используете ColdFusion 9 или Railo? Если да, запишите и включите файлы в памяти может быть быстрым и простым решением. Просто создайте имя файла с чем-то вроде CreateUUID(), чтобы избежать коллизий.

person Sergey Galashyn    schedule 09.11.2011

Итак, в основном, после изучения и чтения ответов, кажется, что это мои варианты:

  1. Имейте отдельные поля в таблице для каждой переменной и оценивайте их по отдельности. например nameVariable, reprNameVariable, а затем я могу построить тело с помощью такого кода:

    This is an email body containing lots of different variables. Dear #evaluate(nameVariable)#, <br/> Please contact #evaluate(reprNameVariable)# for further details.

  2. Имейте поле emailBody со всем текстом и применимыми именами полей, запишите его во временный файл и включите его. (Как предложил Адам Кэмерон, и я думаю, что Сергей имеет в виду)

  3. Имейте поле emailBody и напишите код, чтобы перебрать его, найти все переменные coldfusion и заменить их оцененной версией. (Как предложил Дейл Фрейзер)

  4. Имейте небольшие файлы шаблонов, по одному для каждого типа отчета, с телом сообщения электронной почты и полем emailBodyTemplate, указывающим, какой шаблон следует включить. (По предложению Адама Кэмерона)

Теперь мне просто нужно решить, что использовать :) Когда я это сделаю, я приму ответ человека, предложившего этот метод (если только это не тот, который не был предложен, и в этом случае я, вероятно, приму это, или если кто-то придумает другой метод, который имеет больше смысла)

person froadie    schedule 09.11.2011

Прошло некоторое время с тех пор, как вы опубликовали это, но это ИМЕННО то, что я делаю. Я нашел ваш вопрос, когда искал что-то еще.

Я просто создал свой собственный простой синтаксис для переменных, когда я пишу свои электронные письма в базу данных:

Hello ~FirstName~ ~LastName~,

Затем в моем файле отправки cfm я извлекаю текст письма из базы данных и сохраняю его в переменной:

<cfset EmailBody = mydatabasequery.HTMLBody>

Затем я быстро удаляю собственный синтаксис со своими переменными (из другого запроса под названием RecipientList):

<cfset EmailBody = ReplaceNoCase(EmailBody, "~FirstName~", "#RecipientList.First#", "ALL")>
<cfset EmailBody = ReplaceNoCase(EmailBody, "~LastName~", "#RecipientList.Last#", "ALL")>

Затем я просто отправляю письмо:

<cfmail ....>#EmailBody#</cfmail>

Надеюсь, вам удастся это увидеть. Если вы контролируете создание сообщений электронной почты, что, я подозреваю, вы делаете, это должно работать хорошо.

Рассел

person Russell Schutte    schedule 04.01.2012