In Perl, I have script that creates a dropdown list based on a database that contains a list of vendors. I would like to use the selection of the first list to populate the second list with values of different contacts given that specific vendor.
ie. Haliburton is vendor....once this is chosen contact Jim, Paul, George are available in contact list that is next to it.
Currently I am getting the list of vendors and the list of contacts separately. How do I get the list of contacts based on the vendor in the database to be populated in the CGI popup_menu?
The following is my current code:
#!c:\perl\bin\perl.exe
use CGI;
use strict;
use warnings;
require ("data_eXchangeSubs.pm");
$query = new CGI;
print $query->header(-expires=>'-1d');
print $query->start_html(-title=>'Dex Vendor Testing',
-bgcolor=>'white'
);
my $dataX = ${ConnectToDatabase($main::DB1, $main::DBEnv)};
$resultSet = $dataX->Execute("select vendor from vendor_info group by vendor");
my #list_of_vendors;
while(!$resultSet->EOF) {
push #list_of_vendors, $resultSet->Fields("vendor")->Value;
$resultSet->MoveNext;
}
From here, I would like to populate another dropdown list with contacts from the vendor_info data table. Currently I'm making a separate query execution but I would like to take a given vendor from the previous array and populate only those contacts specific to the chosen vendor.
I know I have to change the values of the contacts but don't know how to :(
$resultContact = $dataX->Execute("select contact from vendor_info");
my #list_of_contacts;
while(!$resultContact->EOF) {
push #list_of_contacts, $resultContact->Fields("contact")->Value;
$resultContact->MoveNext;
}
print $query->popup_menu(
-name => 'vendors'
, -values =>\#list_of_vendors
, -default => $default_vendor
, -style=> 'width:200px'
);
print $query->popup_menu(
-name => 'contacts'
, -values => \#list_of_contacts
, -default => $default_vendor
);
print $query->end_html;
This is a very broad question. You have a couple of simple options.
1) Create an HTML form with the list of vendors, take (and sanitize!) the user's selection, and return the list of contacts. This is a traditional dynamic CGI form.
2) Use JavaScript. This only works for a reasonable amount of data. There are several ways to do it but the gist of the idea is: a) associate each contact with the correct vendor, b) hide all the contacts initially, c) when a vendor is selected, display the correct contacts.
JQuery is a handy JavaScript tool for this kind of manipulation and magically hides many browser incompatibility problems.
3) You could create a fancy, modern AJAX-ified form, but from your question, this is probably overkill.
Sorry there is no quick-and-dirty solution but I'm hoping to give you enough here to start Googling in the right direction! Best!
With CGI, you need to use CGI::param method.
# I know the name of the select is "vendors",
# but it makes more sense calling it here with 'vendor'
# *you would have to change the name of the element*
my $vendor_name = $query->param( 'vendor' );
And I'm not sure how your database object works (kind of looks like the Microsoft iteration model), but using the proper way of parameterized queries in DBI, it looks like this:
my $stmt = $dbh->prepare( 'select contact from vendor_info where vendor_name=?' );
$stmt->execute( $vendor_name ); # binds the variable to the query.
Then you step through the rows of the query and build your list of contacts. Of course, you'd mostly likely use fetchrow_array or fetchrow_arrayref methods to walk through them.
Although this might be better off utilizing a more modern strategy by getting a combined list of vendors and contacts for JavaScript or using Ajax to query the contacts for a vendor.
There is no "connecting" structure in basic Perl CGI. You would have to use a more modern web framework for that.
Related
How to select a single row on october cms?
How can a simple thing be so complicated here?
I thought it would be something to help us and not to disturb something that is as simple as
SELECT * FROM `engegraph_forms_membros`
Here it's like fighting against demons without a bible, oh god why?
Why make the query difficult for newbie?
I understand you don't speak English natively but you should watch every single one of these videos.
Does the record belong to a model in a plugin? Here are the docs on how to work with models.
You make a plugin, set the database which creates models, and then make components to be ran in your CMS Pages.
In a component.php file you can have something like this: Here I am calling the model class Agreements with use Author\Plugin\Models\Agreements;. This allows me to run a function/method to retrieve all agreements or one agreements using laravel's eloquent collection services.
Lets say we have the ID of a record. Well we can either call on the Agreements model with ::find or with ::where. You will noticed I have two functions that essentially do the same thing. ::find uses the primary key of the models (in my case the id) and will return a singular record. *Note that find can take an array and return a collection of records; like ::where. Using ::where we are going to look for the ID. *Note ::where always returns a collection which is why I have included ->first().
<?php namespace Author\Plugin\Components;
use Session;
use Input;
use Crypt;
use Db;
use Redirect;
use Illuminate\Contracts\Encryption\DecryptException;
use October\Rain\Support\Collection;
use Author\Plugin\Models\Agreements;
class GetAgreement extends \Cms\Classes\ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Get one agreement',
'description' => 'Get an agreement to change or delete it'
];
}
public function onRun() {
$this->page['agreement'] = $this->getWithFindAgreement;
}
public function getWithFindAgreement() {
$id = 1;
$agreement = Agreements::find($id);
return $agreement;
}
public function getWithWhereAgreement() {
$id = 1;
$agreement = Agreements::where($id)->first();
return $agreement;
}
}
If for some reason you aren't working with models, here are the docs to work with Databases. You will have to register the use Db; facade.
Here call the table you want and use ::where to query it. *Note the use of ->first() again.
$users = Db::table('users')->get();
$user = $users->where('id', 1)->first();
There are two simple ways to select a single row:
This will give you the'first' record in the selected recordset.
SELECT top 1 * FROM `engegraph_forms_membros`
This will select all the records that meet the predicate requirement that the value of <columnname> is equal to <value>
SELECT * FROM `engegraph_forms_membros` where <columnname>=<value>
If you select a record where multiple values meet that requirement, then you can (randomly) pick one by combining the solutions...
SELECT top 1 * FROM `engegraph_forms_membros` where <columnname>=<value>
But be aware that without an ORDER BY clause, the underlying data is unordered and prone to change uncontrollably, which is why most people (including your boss) will find the use of 'Top' to be improper for real use.
Hopefully this question isn't too naive...
I'm attempting to implement The Giving Lab API in order to allow users of my site to donate to charity.
Using a URL such a this:
https://www.thegivinglab.org/api/donation/start?donationtype=0&amount=10&charityid=84ed3c54-6d8c-41c5-8090-f8ec800f45a7&returnurl=mywebsite.com/
the user is directed to the donation page and then returned to the returnURL after the donation has been made.
I want to be able to add how much the user donated to my databases if they successfully complete a payment. Would it be possible to use the returnURL to do this? Ie could I use a returnURL in the form of mywebsite.com?q="amount_donated" and then use this to update my databases?
I can see that this would allow someone to update my databases by just entering the returnURL into their browser.
Is there a generally better method, that removes this problem?
Many thanks.
Dutch banks use a thing called a sha-sign (and they're probally not the first)
All you have to do is add a key which only you can know:
function makeSecureCode($var1, $var2){
$secretCode = 'example';
$secretKey = '';
$secretKey.= $var1 . $secretCode;
$secretKey.= $var2 . $secretCode;
return sha1($secretKey);
}
Then make the url like this: ?var1=foo&var2=bar&key=5e8b73da0b20481c1b4a285fb756958e4faa7ff1
And when you process the code after payment, makeSecureCode( $_GET['var1'], $_GET['var2']) should be equal to $_GET['key']. If not, someone changed it.
This is a simplefied version with only two vars. You can make it have more input arguments, or an array, whichever you prefer.
OK, in good old fashioned PHP MVC, I might use a model to hit the DB, send info to my PHP controller that I pass on to the View. In the View, I might take that info (say i ajax'ed my controller for the info) and create a table or ul to display the data returned.
I've had trouble finding any modern (ver 6.1 is what i'm on) tutorial to show me how to preform this action in typo3.
Can anyone just "steer" me in the right direction? Perhaps provide an example via answer, or some links to further information that may compare it down to "old fashioned MVC"?
Extension has been suggested, but I'd like to know the very base process of what I'm asking before I try writing some extension, unless the extension is the only way. Although, my table is now on the SAME DB my typo3 is on, so shouldn't there be some command to just simply call my table and get the rows? Maybe send them to a ###sub-part###?
You can use a typoscript cObj content and the select option together with the function render_obj when your table name is like the typo3 nameing convention. The select pulls the record from the table and pass it to the render_obj function. It's a function that can apply to all cObj and iterate over the entire selection. stdWrap works only on the entire cObj. When you need to work through each record you need the render_obj function. For example:
10 = CONTENT
10 {
select {
pidInList = 1
where = colpos=1
orderBy = sorting
}
table = tt_content
renderObj.stdWrap.wrap = <li>|</li>
renderObj.stdWrap.required = 1
}
10.stdWrap.wrap = <ul>|</ul>
This gives you an unorderd list from the tt_content table with pid=1 and the content from the far left column.
I am absolute beginner to drupal.
I have added a contact form (using Webform module).
Now I want to save the data entered in the form. But I am lost. I have searched over internet, found db_query() is used to query database.
But I dont know where to write the php code. Please help me or if you know any link,please give me.
The tables you'll be most interested in are webform, webform_submissions, webform_submitted_data and webform_component. Have a look at those tables and it becomes very obvious how they're linked together.
You'll want to look at the Drupal 7 Database API to learn how to use the query system but here's an example to get you going:
/* Get a list of all submissions from webform for the node with ID (`nid`) of 1 */
$nid = 1;
$submissions = db_select('webform_submissions', 'ws')
->fields('ws')
->condition('nid', $nid)
->execute();
/* If you want to use db_query and a plain old SQL statement instead you'd do it like this:
$submissions = db_query('SELECT * FROM webform_submissions WHERE nid = :nid', array('nid' => $nid)); */
/* Loop through the submissions and load up the submitted data for each */
$submission_data = array();
foreach ($submissions as $submission) {
$query = db_select('webform_submitted_data', 'wsa')
->fields('wc', array('name'))
->fields('wsa', array('data'))
->condition('sid', $submission->sid);
/* Join in the component table to get the element label */
$query->join('webform_component', 'wc', 'wc.nid = wsa.nid AND wc.sid = wsa.cid');
$submission_data[] = $query->execute()->fetchAllKeyed();
}
At the end of that code you'll have an array ($submission_data), which contains a list of arrays of submission data for the provided node. Each of those arrays' items has a key of the component label, and a value of the submitted user value.
Hope that helps
It's worth noting that for most normal use cases you'll never need to look at the databases or do any kind of coding. The UI allows you to view submissions of a form (and see what was submitted). You can also configure the Webform to send you a copy of each submission (via email)... There is a lot you can do without "looking under the hood" or messing with the database in any way.
If you are really new to Drupal and Webforms, I just thought I'd point that out. There are a lot of tabs in the UI which might easily be overlooked.
Webform has Views support, so you probably don't really need to write database queries to generate the report you want.
I was tasked to create this Joomla component (yep, joomla; but its unrelated) and a professor told me that I should make my code as dynamic as possible (a code that needs less maintenance) and avoid hard coding. The approach we thought initially is take url parameters, turn them into objects, and pass them to query.
Let's say we want to read hotel with id # 1 in the table "hotels". lets say the table has the fields "hotel_id", "hotel_name" and some other fields.
Now, the approach we took in making the sql query string is to parse the url request that looked like this:
index.php?task=view&table=hotels&hotel_id=1¶m1=something¶m2=somethingelse
and turned it into a PHP object like this (shown in JSON equivalent, easier to understand):
obj = {
'table':'hotel',
'conditions':{
'hotel_id':'1',
'param1':'something',
'param2':'somethingelse'
}
and the SQL query will be something like this where conditions are looped and appended into the string where field and value of the WHERE clause are the key and value of the object (still in JSON form for ease):
SELECT * FROM obj.table WHERE hotel_id=1 AND param1=something and so on...
The problem that bugged me was the exposing of the table name and field names in the request url. I know it poses a security risk exposing items that should only be seen to the server side. The current solution I'm thinking is giving aliases to each and every table and field for the client side - but that would be hard coding, which is against his policy. and besides, if I did that, and had a thousand tables to alias, it would not be practical.
What is the proper method to do this without:
hard coding stuff
keep the code as dynamic and adaptable
EDIT:
Regarding the arbitrary queries (I forgot to include this), what currently stops them in the back end is a function, that takes a reference from a hard-coded object (more like a config file shown here), and parses the url by picking out parameters or matching them.
The config looks like:
// 'hotels' here is the table name. instead of parsing the url for a table name
// php will just find the table from this config. if no match, return error.
// reduces risk of arbitrary tables.
'hotels' => array(
// fields and their types, used to identify what filter to use
'structure' => array(
'hotel_id'=>'int',
'name'=>'string',
'description'=>'string',
'featured'=>'boolean',
'published'=>'boolean'
),
//these are the list of 'tasks' and accepted parameters, based on the ones above
//these are the actual parameter names which i said were the same as field names
//the ones in 'values' are usually values for inserting and updating
//the ones in 'conditions' are the ones used in the WHERE part of the query
'operations' =>array(
'add' => array(
'values' => array('name','description','featured'),
'conditions' => array()
),
'view' => array(
'values' => array(),
'conditions' => array('hotel_id')
),
'edit' => array(
'values' => array('name','description','featured'),
'conditions' => array('hotel_id')
),
'remove' => array(
'values' => array(),
'conditions' => array('hotel_id')
)
)
)
and so, from that config list:
if a parameters sent for a task is not complete, server returns an error.
if a parameter from the url is doubled, only the first parameter read is taken.
any other parameters not in the config are discarded
if that task is not allowed, it wont be listed for that table
if a task is not there, server returns an error
if a table is not there, server returns an error
I actually patterned this after seeing a component in joomla that uses this strategy. It reduces the model and controller to 4 dynamic functions which would be CRUD, leaving only the config file to be the only file editable later on (this was what I meant about dynamic code, I only add tables and tasks if further tables are needed) but I fear it may impose a security risk which I may have not known yet.
Any ideas for an alternative?
I have no problem with using the same (or very similar) names in the URL and the database — sure, you might be "exposing" implementation details, but if you're choosing radically different names in the URL and the DB, you're probably choosing bad names. I'm also a fan of consistent naming — communication with coders/testers/customers becomes much more difficult if everyone calls everything something slightly different.
What bugs me is that you're letting the user run arbitrary queries on your database. http://.../index.php?table=users&user_id=1, say? Or http://.../index.php?table=users&password=password (not that you should be storing passwords in plaintext)? Or http://.../index.php?table=users&age=11?
If the user connected to the DB has the same permissions as the user sitting in front of the web browser, it might make sense. Generally, that's not going to be the case, so you'll need some layer that knows what the user is and isn't allowed to see, and that layer is a lot easier to write correctly by whitelisting.
(If you've stuck enough logic into stored procedures, then it might work, but then your stored procedures will hard-code column names...)
When composing a SQL query with data from the input, it presents a security risk. But keep in mind that columns values are inserted to the fields by taking input from the user, analyzing it and composing a SQL query with it (except for prepared statements). So when done properly, you have nothing to worry about - simply restrict the user to those column & tables. Open source software's code/database is visible to all - and it doesn't harm the system so much as one would think.
Your aliasses could be a rot13() on the meta/name of your objects.
Although, if you escape the input accordingly when working with those names, I don't see any problem in exposing their names.