(Надявам се, че този отговор не е твърде дълъг. Не смятах, че съществуващите отговори дават достатъчно информация, но се надявам, че не съм отишъл твърде далеч в обратната посока...)
В CF има разнообразни обхвати, в които могат да бъдат поставени променливи (приложение, сесия, url, cgi и т.н.).
Някои от тях изискват изрична декларация, за да се използва (напр. променливите на сесията винаги трябва да са с обхват), други могат да бъдат автоматично достъпни при четене на променлива (напр. променливите за форма и url могат да бъдат прочетени чрез използване на променлива без обхват) - има ред на предимство тук, което определя кои обхвати се проверяват за променлива без обхват.
Долният обхват в това подреждане е обхватът variables
, който е обхват, който се прилага за цялата текуща страница/екземпляр на обект.
Когато задавате нова променлива, ако е без обхват, тя се създава в обхвата variables
. Тъй като това е глобален обхват, той може да бъде достъпен както от различни екземпляри на една и съща функция, така и от различни функции, което причинява проблемите, за които знаете.
За да предотвратите попадането на променлива в обхвата на глобалните променливи, трябва да я поставите в обхвата local
на функцията. (Технически можете да го поставите в обхвата arguments
на функцията, но това вероятно ще обърка хората.)
В по-ранните версии на CF нямаше начин за изричен достъп до локалния обхват - трябваше да използвате ключовата дума var
, за да създадете променливата в локалния обхват - и веднъж създадена, тя винаги ще има предимство (както за четене, така и за писане) над обхвата на променливите.
С CF9 обхватът local
вече е "правилен" обхват и може да бъде достъпен изрично, така че вместо да използвате <cfset var x = 0 />
, можете да напишете <cfset local.x = 0 />
- основното предимство от това е, когато създавате променлива, където ключовата дума var
не може да се използва, напр. <cfquery name="local.qGetElementsByType" ...>
и <cfloop index="local.lcv"...>
Все още само трябва да приложите локалния обхват при първото създаване на всяка променлива, за да предотвратите навлизането й в обхвата на променливите - последващите четения/актуализации могат да бъдат необхванати, ако предпочитате, точно както биха били, когато правите var scope.
(Въпреки че има други потенциални проблеми, свързани с обхвата с променливи без обхват, като например вътре в блок <cfloop query="queryname">
, и поради това някои хора ще твърдят, че винаги трябва да обхващате всички променливи, независимо от всичко.)
В обобщение, за да направите кода, който показвате, безопасен, трябва да имате обхват:
qGetElementsByType
от тага cfquery
lvc
от тага cfloop
Тъй като тези променливи не се създават с cfset, обхватът се извършва най-лесно чрез префикс на имената с local.
Тъй като вече сте var
обхванали променливата listCount, не е необходимо да го правите отново в същата функция - по избор можете да използвате <cfset local.listCount = local.listCount + 1>
(или наистина <cfset local.listCount++ >
), но отново това е въпрос на предпочитание и не е необходимо за защита срещу изтичане в обхвата на променливите.
(странична бележка: В идеалния случай трябва да използвате маркера cfqueryparam около #lcv#
, за да се предпазите от SQL инжектиране - въпреки че това е заявка за заявка, това пак може да е проблем и винаги е по-добре да играете безопасно по отношение на сигурността.)
Разбира се, това е само тази функция - ще трябва да поправите и други функции - и лесен начин да направите това е да използвате varscoper инструмент за сканиране на цялата ви кодова база и идентифициране на променливи, които се нуждаят от обхват.
person
Peter Boughton
schedule
10.06.2012
WHERE subjectid IN ( <cfqueryparam value="#arguments.element_type_id#" cfsqltype="cf_sql_integer" list="true"> )
- person Leigh   schedule 11.06.2012