好的,出于某种奇怪的原因,我在request.cfm文件中设置了request.dsn和我创建的另一个名为request.cfcDIR的变量。(Coldfusion 10)
以下两个变量的值来源于。
<cfset chkURL = "#CGI.HTTP_HOST#">
<cfif ((chkURL) EQ "url.subdomain.here" OR (chkURL) EQ "url.subdomain.here.a" OR (chkURL) EQ "url.subdomain.here.b" OR (chkURL) EQ "url.subdomain.here.c")>
<cfset whichDB = "1,2,3,4,5,6">
<cfelse>
<cfset whichDB = "0">
</cfif>
<!--- Start Check for Which DB the user resides and overwrite the request.dsn variable in Application.cfm --->
<cfif ((whichDB) NEQ 0 OR (whichDB) NEQ "")>
<cfset whichDB = "#whichDB#">
<cfif (whichDB) EQ 0>
<cfset request.dsn = "xxxxx_1">
<cfelse>
<!--- Loop through the whichDB list --->
<cfloop list="#whichDB#" delimiters="," index="i">
<cfquery name="CheckDB" datasource="xxxxx_#i#">
Select username,db,compid
FROM users
WHERE username = <cfqueryparam value="#FORM.username#" cfsqltype="cf_sql_varchar" maxlength="20">
</cfquery>
<!--- Here we check for which database has the results which originates from the Query(CheckDB) above
***IMPORTANT*** in order for this to work properly your Coldfusion DSN must named xxxxx_1, xxxxx_2 and so on...--->
<cfif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 1>
<cfset client.dsn = "xxxxx_1">
<cfset client.cfcDIR = "cfcV5">
<cfset request.dsn = "xxxxx_1">
<cfset request.cfcDIR = "cfcV5">
<cfbreak/>
<cfelseif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 2>
<cfset client.dsn = "xxxxx_2">
<cfset client.cfcDIR = "cfc">
<cfset request.dsn = "xxxxx_2">
<cfset request.cfcDIR = "cfc">
<cfbreak/>
<cfelseif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 3>
<cfset client.dsn = "xxxxx_3">
<cfset client.cfcDIR = "cfcV5">
<cfset request.dsn = "xxxxx_3">
<cfset request.cfcDIR = "cfcV5">
<cfbreak/>
<cfelseif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 4>
<cfset client.dsn = "xxxxx_4">
<cfset client.cfcDIR = "cfc">
<cfset request.dsn = "xxxxx_4">
<cfset request.cfcDIR = "cfc">
<cfbreak/>
<cfelseif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 5>
<cfset client.dsn = "xxxxx_5">
<cfset client.cfcDIR = "cfcV5">
<cfset request.dsn = "xxxxx_5">
<cfset request.cfcDIR = "cfcV5">
<cfbreak/>
<cfelseif (CheckDB.RecordCount) NEQ 0 AND (CheckDB.db) EQ 6>
<cfset client.dsn = "xxxxx_6">
<cfset client.cfcDIR = "cfcV5">
<cfset request.dsn = "xxxxx_6">
<cfset request.cfcDIR = "cfcV5">
<cfbreak/>
<cfelse>
<cfset request.dsn = "xxxxx_1">
</cfif>
</cfloop>
</cfif>
</cfif>
因此,当Application.cfm获取设置变量时,上面的代码工作正常。但是request.dsn并没有坚持,就好像我从未在第一时间定义它一样。为了安全起见,我在上面的代码中定义了两次变量。
这是Application.cfm文件的样子。
<cfapplication name="Appname-here"
sessionmanagement="yes"
clientstorage="cookie"
clientmanagement="Yes"
loginstorage="session"
scriptprotect="all"
sessionTimeout = #CreateTimeSpan(0, 0, 10, 0)#>
<cfswitch expression="#CGI.HTTP_HOST#">
<cfcase value="url.subdomain.here">
<cfif IsDefined("request.dsn")>
<cfset request.dsn = '#client.dsn#'>
</cfif>
<cfset request.cfcDIR = #client.cfcDIR#>
</cfcase>
<cfdefaultcase>
<cfset request.dsn = 'xxxxx_1'>
<cfset request.cfcDIR = cfcV5>
<cfdefaultcase>
</cfswitch>
因此,当用户移动到定义用户页面登陆时,我得到一个错误,指出&#34;元素DSN未在REQUEST中定义&#34;这是废话,因为正在定义。(Coldfusion 10)
答案 0 :(得分:3)
&#34;请求范围&#34;存在于单个请求的生命周期。除非您的<cfapplication ...>
代码上方有某些内容,否则会显示以下内容:
<cfif IsDefined("request.dsn")>
<cfset request.dsn = '#client.dsn#'>
</cfif>
...永远不会触发(永远不会返回true)。
如果要检查Request变量,则需要在检查之前要求设置它或者需要它的代码。它只存在于请求结束之前。但是,您的客户端var将保持不变。也许你的意思是:
<cfif IsDefined("client.dsn")>
<cfset request.dsn = '#client.dsn#'>
</cfif>
这对我来说更有意义。
附加信息
Reya - 你的问题仍然是你在我的回答中看到的。每次用户点击某些内容或加载导致服务器和http调用的内容时,您都需要使用每个请求设置意味着。它需要是在调用cfapplication之前设置,然后检查它。
如果我可以建议更改体系结构,请在登录脚本中找出用户所属的数据库,然后在 session 范围内进行设置。然后改变你的数据源&#34;属于#session.dsn&#34; - 当然你可以使用&#34; client.dsn&#34; - 但这也需要上面的改变。
因此,您需要使用持久性范围(可能是会话或客户端)或运行代码,以便在上面粘贴的应用程序文件中的代码之前设置请求范围。我知道我很难说清楚。 :)
答案 1 :(得分:0)
这是我的建议。对于Application.cfm中的每个case语句,只需声明dsn,如下所示:
<cfcase value="url.subdomain.here">
<cfset request.dsn = 'dsnForThisSubdomain'>
<cfset request.cfcDIR = 'cfcDirForThisSubdomain'>
</cfcase>
Application.cfm代码将始终在每个请求上运行。您不能以这种方式引用稍后在Application.cfc中运行的代码中设置的变量。这就是为什么我建议如果子域与您需要的请求变量之间存在一对一的关系,只需将它们设置在此处即可。
请注意,您可以在case语句中将多个子域作为列表放置,因此您可以:
<cfcase value="url.subdomain1.here, url.subdomain2.here">
<cfset request.dsn = 'dsnForThisSubdomain'>
<cfset request.cfcDIR = 'cfcDirForThisSubdomain'>
</cfcase>
如果这对您不起作用,您需要清除代码中的一些错误和误解。第一:
<!--- Start Check for Which DB the user resides and overwrite the request.dsn variable in Application.cfm --->
此时,您无法覆盖request.dsn变量。在请求生命周期中,这已经太迟了。你认为你可以是一个致命的缺陷。除此之外:
而不是
<cfif ((whichDB) NEQ 0 OR (whichDB) NEQ "")>
我建议使用
<cfif whichDB > 0>
这使你的意图更加明确
<cfset whichDB = "#whichDB#">
上面的cfset只是将whichDB的值赋给自己,你不需要这样做。您也永远不需要取消引用var来设置它。所以即便如此。它没用,写这个的正确方法是:
<cfset whichDB = whichDB>
在该行之后,您有
<cfif (whichDB) EQ 0>
永远不会运行,因为它嵌套在
中 <cfif ((whichDB) NEQ 0 OR (whichDB) NEQ "")>
所以应该移动if分支中的代码。您可以将它放在代码块第5行<cfset whichDB = "0">
下的顶部附近。
至于其余部分,<cfbreak/>
或if
块结束时不需要elseif
。如果您使用cfswitch块而不是多个elseif块,那么您的代码可能更清晰,我建议使用会话范围的变量而不是客户端范围的变量。类似的东西:
<cfif CheckDB.RecordCount>
<cfswitch expression="#CheckDB.db#">
<cfcase value="1">
<cfset session.dsn = "xxxxx_1">
<cfset session.cfcDIR = "cfcV5">
</cfcase>
...
</cfswitch
</cfif>
此时,我建议在代码库中运行搜索和替换,并将request.dsn更改为session.dsn,将request.cfcDIR更改为session.cfcDIR,并忘记在应用程序中设置请求变量。如果会话变量存在,则为cfm文件。在您的应用中为同一件事维护2个变量没有任何价值。但是如果你决定这样做,你必须在你的Application.cfm中得到正确的逻辑 - 你现在已经倒退了。最好的是:
<cfif structkeyexists( session, 'dsn' )>
<cfset request.dsn = session.dsn >
</cfif>
并且你还需要一个围绕cfset的session.cfcDIR的类似if语句,你有一个client.cfcDIR,因为它在用户登录之前不存在,因此会抛出错误。