Coldfusion and session variable not setting - session

I have a survey form with 5 ques, there is one question on each page and user clicks through them with next button on the page. Now, the user is not logged in, I want to set a session variable only when the user takes the first ques on form and clicks next. But I am getting userid not defined in session for the line 2. I am not really sure what I am doing wrong here. Can anyone suggest if they see what is going on. I don't want to be creating multiple userids every time he hits next button. Thanks
<cfif structKeyExists(FORM, "user_mode") and form.user_mode EQ "next">
<cfif NOT ( StructKeyExists(session,userid) )>
<cfquery name="insertuser" datasource="#application.datasource#">
INSERT INTO survey_user(ip_address)
VALUES (<cfqueryparam cfsqltype="cf_sql_varchar" value="#CGI.REMOTE_ADDR#" />)
</cfquery>
</cfif>
</cfif>

StructKeyExists(session,userid)
should be:
structKeyExists( session, 'userid' )
Note the quotes. Without them it's looking for the variable "userid" rather than the key name "userid".

Related

Book an event page

I need to setup A form where a user would be signing up to an event but while doing that it will collect the data of the user from their database table automatically while also taking information from the events table and inserting it into another table
What are you using primarily to achieve this at the moment? Are you using PHP? In case of PHP,
if you have a user id on whichever user that is going to fill out the form, then you can use that user id to fetch the information from whatever table that you need, and retrieve the information of the user. You then put those into PHP variables for later use. The only way to know which user is which, is by using sessions. This session can be their user id, which I will go by in this example, simply because it's simple and easy.
The handling of form data can be done by a classic form tag with post method and a submit button. You tell the form whichever page it is to supposed to post to.
It can also be handled by AJAX.
You then put those posts into PHP variables, or use them directly, but I personally prefer to put them into variables for clarification. It can look a bit messy using the post variables directly into your query, as well as the security risks it involves.
What it could look like is something like this:
<?php
/*
Firstly we need our session (this should be set upon logging by using $_SESSION['userId'].
As mentioned before, I am using a user id as our session variable in this example.
*/
/*
Carry over the session.
Use session_start() before anything else in a file to get the session of a user.
*/
session_start();
//Put session into a php variable
//mysql_ syntax:
$userId = mysql_real_escape_string($_SESSION['userId']);
mysqli_ syntax, with $conn being your database connection variable:
$userId = mysqli_real_escape_string($conn, $_SESSION['userId']);
mysqli_ syntax, with $conn being your database connection variable:
$userId = mysqli_real_escape_string($conn, $_SESSION['userId'])
?>
Now what is left, is to construct our form and send that data. Since I personally would prefer to handle the data in another file than the file that contains the form, we're going to tell the form to post to another file. This file will contain our form data, as well as our user data. How we will go by getting our user data is by using the session variable, which conveniently happens to be the user id (which is unique to every user). We can post this with everything else in our form by using a hidden input field carrying the user id variable (just as an example).
<!--
What we do here is make a form that that tells which page it is going to go to
on submit
-->
<form action="/another_page.php" method="POST">
<!-- Our hidden input field, carrying the user id -->
<input type="hidden" name="userId" value="<?php echo $userId; ?>" />
What brand is your current car?:<br />
<input type="text" name="carBrand" placeholder="Brand of your car" />
Tell us a little about yourself:
<textarea rows="4" cols="50" name="summary"></textarea>
Rate your experience, 1-5:
<select name="rating">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<br /><br />
<button type="submit" name="submitButton">Submit form!</button>
</form>
Now we go to the other file to handle our data, which we will later put into the second table as per your request.
<?php
//This is our POST variables from our form:
$userId = $_POST['userId'];
$car_brand = $_POST['carBrand'];
$summary = $_POST['summary'];
$rating = $_POST['rating'];
//Now to our SQL, to get there data of our user:
//Put SQL command into a variable
$sql = "SELECT * FROM name_of_user_table WHERE userId='$userId'";
//Put query into a variable with mysql_ syntax:
$result_set = mysql_query($sql);
//Put query into a variable with mysqli_ syntax:
//$conn still being your connection variable
$result_set = mysqli_query($conn, $sql);
//The rows in your table in mysql_ syntax:
$row = mysql_fetch_array($result_set);
//The rows in your table in mysqli_ syntax:
$row = mysqli_fetch_array($conn, $result_set);
/*
Now we can start using our data from the database, and store them into variables.
The variables depends on your fields names in the database.
We basically have the data stored into an array,
where we need to tell the array exactly which index we'd like to use
(in this case which field we'd like to store into a variable).
*/
//Examples:
$variable1 = $row['name_of_field'];
$variable2 = $row['name_of_another_field'];
[...]
?>
Now what is left, is to put everything into your second table, using our variables. Hope this helps :)
It is also very important that you use prepared statements before firing your SQL commands into your database, or at least sanitize the inputs to prevent SQL-injections.
Martin wrote a really comprehensive answer; I'm not saying that it is wrong (how could I? I don't speak PHP); however, as the OP tagged it as Oracle Application Express (not PHP), it might not be the best fit.
Anyway: that looks like a simple task: if signing up to the event is done by pushing a button (why wouldn't it be?), you'd create a process which does the rest of the job. Either write it in the appropriate process property, or create a stored procedure which collects data & inserts it elsewhere and - in the Apex process - call that procedure.

CFWheels - updateByKey() - The key argument contains an invalid value

<cfset result = model("user").updateByKey(
key=authUser.user_id
, encryption_key=local.encryptionKey
)>
The code above returns the following error in cfwheels:
The key argument contains an invalid value.
Suggested action
The key argument contains a list, however this table doesn't have a
composite key. A list of values is allowed for the key argument, but
this only applies in the case when the table contains a composite key.
Now I have resolved this by using the update all method like this:
<cfset recordsReturned = model("user").updateAll(
encryption_key=local.encryptionKey
, where="user_id=#authUser.user_id#"
)>
I've checked the database and cannot find duplicate primary keys. I've also tried setting the instantiated=false argument in the updateByKey method but that did not work either. Any explanation as to why this might happen would be appreciated.
ps: the closest thing i have to a primary key in the table apart from the user_id is the email_address which is unique so as not to allow duplicates.

Coldfusion validate list of emails

I am trying to validate a list of emails that have been pulled from the database.
<cfquery name="AdminEmail" datasource="#blah#">
Select email from users where role = "admin"
<cfquery>
<cfset variable.mailto = #adminemail.Email#>
The query would return multiple emails which is fine for cfmail, but IsValid only validates a single variable. Any advice. This is needed to get to the security standards asked of me.
Loop through the query of your emails and then add them to a new variable if they're valid.
<cfset validEmails = []>
<cfloop query="adminemail">
<cfif isValid('email', adminemail.email)>
<cfset arrayAppend(validEmails, adminemail.email)>
</cfif>
</cfloop>
<cfset mailTo = arrayToList(validEmails)>
Note: I used an array to store the emails because appending to a list is a more costly process and an array will be slightly faster. Probably nothing you'll notice unless you have hundreds of emails but still a good practice.

Where to put queries (especially long ones) in a CFWheels project

(wheels novice here)
I'm trying to figure out the best place to put a number of large and/or complex queries that are used in the controllers function for the view.
I have a view calendar.cfm, and a controller with the function:
<cffunction name="calendar">
<cfset formData = getValidatedFormData()>
<cfset fromDate = formData.fromDate>
<cfset toDate = formData.toDate>
<cfset dbLocation = formData.dbLocation>
<cfset dateList = getDateList()>
<cfset selectLists = getSelectLists()>
<cfset companySelectList = selectLists.companySelectList>
<cfset activitySelectList = selectLists.activitySelectList>
<cfset instructorSelectList = selectLists.instructorSelectList>
<cfset statusSelectList = selectLists.statusSelectList>
<cfset courseNumberLists = getCourseNumberLists()>
<cfset girsCourseNumberList = courseNumberLists.girsCourseNumberList>
<cfset activityCourseNumberList = courseNumberLists.activityCourseNumberList>
<cfset activityCourseNumberList = courseNumberLists>
<cfset ELMActivityList = getELMActivityList()>
<cfset activityList = getActivityList()>
<cfif len(elmActivityList.LM_ACT_CD) gt 0>
<cfset elmActIDList = Replace(QuotedValueList(ELMActivityList.LM_ACT_CD, ","), "'',", "", "all")>
<cfelse>
<cfset elmActIDList = "'String1','String2'">
</cfif>
<cfif len(activityList.girs_act_cd) gt 0>
<cfset girsActIDList = Replace(QuotedValueList(activityList.GIRS_ACT_CD, ","), "'',", "", "all")>
<cfelse>
<cfset girsActIDList = "'String1','String2'">
</cfif>
<cfset combinedList = getCombinedList( elmActIDLIst , girsActIDList )>
<cfset needUnion = false>
<cfset programList = getProgramList()>
</cffunction>
Each of the functions, such as getDateList(), contains long and/or complex queries. The controller is already almost 700 lines long, and I've only implemented one of the 5 or 6 views in the project -- which will require additional queries.
I have the sense that I'm doing this wrong. I tried putting all the query functions in a cfc file in the models folder
<cfcomponent extends="Model">
functions...
but I can't figure out how to call them from the calendar function in the controller. I tried, for instance,
<cfset dateList= model("model_file_name").getDateList()>
but that isn't it.
Where should I put the queries and how should I call them?
EDIT
When I try to call the function in the model, I get "The data source could not be reached." However, I explicitly specify the datasource in the query. For example I have the following function in both the model and controller:
<cffunction name="getDateList" returntype="any">
<cfquery name="dateList" dataSource="ELM_Prod">
SELECT DATES FROM
(SELECT dateadd(dd,DAYS, <cfqueryparam cfsqltype="cf_sql_date" value="#fromDate#">) DATES
FROM
(SELECT TOP 365 colorder - 1 AS DAYS from master..syscolumns
WHERE id = -519536829 order by colorder) a
WHERE datediff(
dd,
dateadd(
dd, DAYS, <cfqueryparam cfsqltype="cf_sql_date" value="#fromDate#">
),
<cfqueryparam cfsqltype="cf_sql_date" value="#toDate#">
) >= 0
AND dateadd(
dd,
DAYS,
<cfqueryparam cfsqltype="cf_sql_date" value="#fromDate#">
) <= <cfqueryparam cfsqltype="cf_sql_date" value="#toDate#">
) a order by DATES
</cfquery>
<cfreturn dateList>
</cffunction>
When I call the function in the controller with <cfset dateList = getDateList()>, everything is fine, and I don't get the datasource error. However if I call it from the model with <cfset dateList = model("wheels_girs_model").getDateList()/>, I get the error. Because I am using more than one datasource, I'm not setting the datasources in the config file. I have set them both up in the admin panel and refer to them directly in the cfqeury. What would prevent the model from finding the datasource?
There are different ways to do this:
First of all, 700 lines per controller is not too long.
You can put all queries in the controller it self. You can create different functions for different queries (i guess you are doing this).
If you still think this is too long. You can group functions in different cfc's. Then you can create object of these cfc's using createObject to access methods or you can invoke cfc using cfinvoke to access your function.
Secondly, You can put your queries in the model file. You need to create a function in the your model cfc, then add your query in this function and you need to return the query or particular value, whatever you want using cfreturn.
You can call that function using the format
<cfset yourVariableName = model("yourModelName").yourCustomFunctionName(arguments if required) />
After adding a new function to your cfc, you need to reload application using your_site_url/?reload=true&password=password_you_set
Third, as Dan Bracuk suggested, you can use stored procedures and call stored procedures using cfstoredProc
Edit Answer to the problem i understood from comment
You should have put error in the question itself as this changes everything. This error has nothing to do with your code. This error means you haven't set the correct datasource or you haven't created datasource but you are using it or it means there is something wrong in your datasource configuration.
Do as the following:
Check whether you have defined correct datasource in the
config/settings.cfm.
If not, please define it. You can define the datasource by <cfset
set(dataSourceName="your_desired_datasource_name.") />
If yes, then go to your cfadministrator control and datasource tab.
Check whether that datasource exists or not.
If not, create datasource. If yes, check whether it is correctly
configured or not, also check for spelling differnece between the
datasource name from cfadministrator and the one defined in the
config/settings.cfm.
Your problem should go if you do one of the above. Remember, whatever you do, you have to reload application using yourappurl/?reload=1&password=password_you_set
Second Edit:
Your question still doesn't give us clear info like How do you set datasource in admin panel and then how do you access in the query? This should have been different question as this question is totally different from the original question. Anyway, You should always use default datasource (the one defined in the config/settings.cfm). You can override this datasource in the model cfc. You can override default datasource for particular model by <cfset dataSource("your datasource name for that particular table")>. Please check the link for more info. And if you have more queries, you should as separate question (you will probably get more responses).

Using a session variable in the where clause of a LINQ statement

Good afternoon all.
I have a page that displays data in a gridview based upon what the user selects for a material in a radiobutton list and how many they wish to see, a text box.
Upon logging into this page, a session variable for MemberID is created, MemberKey.
What I would like to do is pass this session variable into the LINQ statement so that only the specific member that has logged in sees their data:
ContextTypeName="VDSWeightsReportingService.CompleteWeightsDataContext" EnableInsert="True"
EnableUpdate="True" TableName="tblOnlineReportingCOMPLETEWEIGHTSFINALDEMOs"
Where="MaterialText == #MaterialText && Productpriority <= #Productpriority && MemberId == #MemberId">
<WhereParameters>
<asp:ControlParameter ControlID="radMaterial" Name="MaterialText"
PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="tbxHowMany" Name="Productpriority"
PropertyName="Text" Type="Int32" />
<asp:SessionParameter Name="MemberId" SessionField="MemberKey"
Type="String" />
</WhereParameters>
</asp:LinqDataSource>
I have tried to insert the session variable as above but without the LINQ no longer seems to go through the motions.
Can someone point out to me where I am going wrong?
If this doesn't work, or is not possible, can someone advise of a way around this? i.e. using this session variable in the LINQ where clause.
Make sure you select the correct session variable!!!!

Resources