I have been searching around for a solution to this problem for a few days and finally decided to ask you lovely people as there seem to be multiple ways to skin this proverbial cat.
I have a php page (index.php) that currently displays results from a SQL select query using the following external php script (script.php):
<?php
{
include('database.php');
// Microsoft SQL Server using the SQL Native Client 11.0 ODBC Driver
$conn = odbc_connect($server,$Username,$Password);
// Query
$qry = $Query; <-- this var is set in the included database.php above
$nextbreach = odbc_exec($conn,$qry);
odbc_close();
}
$nextbreachvalue = odbc_result($nextbreach,"Breached Time");
$nextbreachref = odbc_result($nextbreach,"Reference");
?>
$nextbreachvalue and $nextbreachref are then echo'd in my index.php using
<?php echo ($nextbreachref); ?>
<?php echo ($nextbreachvalue); ?>
I'm able to do this as i have used {include('script.php');}
Whilst this works on loading index.php in the browser I would like to update the variables $nextbreachref and $nextbreachvalue every second without having to refresh the page.
I have seen many articles suggesting ajax, json and js can achieve this however i'm somewhat confused on how this is achieved in my circumstance especially as many of the online examples use mysql and not mssql.
Index.php below:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="assets/css/style.css">
<?php
{include('script.php');}
?>
</head>
<body>
<div id="container">
<div id="countdowncontainer">
<div id="countdownclock">
<p id="ref" ><?php echo ($nextbreachref); ?></p>
</div>
</div>
</div>
A basic structure for what you are trying to do is:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="assets/css/style.css">
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script>
$(function() {
setInterval(function(){
$.get("data.php", function( data ) { //receiving the echo from the php data file
$("#ref").html(data); //putting the echoed value directly into the p tag
});
}, 1000); //setting the requests to 1 second each
);
</script>
</head>
<body>
<div id="container">
<div id="countdowncontainer">
<div id="countdownclock">
<p id="ref" ></p>
</div>
</div>
</div>
And your data.php would be similar to the code you have that fecthes data from the database. The difference is that it now echoes the result you want to retrieve in the main page, and does not include any html:
<?php
{
include('database.php');
// Microsoft SQL Server using the SQL Native Client 11.0 ODBC Driver
$conn = odbc_connect($server,$Username,$Password);
// Query
$qry = $Query; <-- this var is set in the included database.php above
$nextbreach = odbc_exec($conn,$qry);
odbc_close();
}
$nextbreachvalue = odbc_result($nextbreach,"Breached Time");
$nextbreachref = odbc_result($nextbreach,"Reference");
echo($nextbreachref);
?>
Related
I installed Apache2 server on linux Mint system to do some web development. I have a code where there is a text in <pre> tag. The php code makes a link to edit the text by transferring all text into edit page <textarea>.
The text transfers in URI. Well, as Apache has a URI length limit, I don't know how to transfer large amount of text.
I searched and found out that there is a way to change this limit, but I couldn't find out where it is set. Also I read that it is not good to use long URIs.
So, I have to either increase the URI length limit or change my code. I haven't figured out how, though. This is the piece of page where text is (story.php, stored in $s variable):
<!DOCTYPE html>
<?php session_start() ?>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="main.css">
<title>The story</title>
<style>
#story{border: darkolivegreen; border-style: solid ;border-width: 3px; padding: 10px }
pre{white-space: pre-wrap}
span{padding-right: 8px}
</style>
</head>
<body>
<?php
include "navigation.php";
$id=$_GET['id'];
//ar_dump($id);
$mysql=new mysqli("",databaseuser,databasepassword,database);
$set=$mysql->query("select title,story,creator,dateCreated,identifier from Stories where identifier='$id'");
if( $set==false) echo $mysql->error;
$record=$set->fetch_array();
//var_dump($record);
if($record)
{
$t=$record['title'];
//check
$s=htmlspecialchars_decode($record['story']);
$c=$record['creator'];
$time=$record['dateCreated'];
$storyid=$record['identifier'];
echo "<h1 id='heading'>$t</h1>";
echo "<h2>By $c on $time</h2>";
echo "<pre id='story' on>$s</pre>";
if(isset($_SESSION[username]))
$user=$_SESSION[username];
$q="SELECT class FROM Accounts WHERE identifier='$user'";
$result=$mysql->query($q);
$group;
if($res)
{
$group=$result->fetch_array()[0];
}
if(($user==$c && $group==users2) or $group==admins or $group==overseers)
{
$s=urlencode($s);
$link='editstory.php?sid='.$storyid.'&text='.$s;
echo "<a href='$link'>Edit</a>";
//echo "<button data-storyid='$storyid' data-story='$s' onclick=''>Edit</button> ";
echo "<button data-storyid='$storyid' onclick='deleteStory(this)'>Delete</button>";
}
This is the page where text transfers into (editstory.php):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Editing</title>
<link rel="stylesheet" href="main.css"
</head>
<body>
<?php
$storyid=$_GET['sid'];
$text=$_GET['text'];
$text=urldecode($text);
echo "<textarea id='text' rows='33' cols='200'>$text</textarea>
<button data-sid='$storyid' onclick='updatestory(this)'>Save</button>
"
?>
<script>
function updatestory(button) {
var sid=button.getAttribute('data-sid')
var text=document.getElementById('text')
var value=text.value;
console.log(text.value)
var request=new XMLHttpRequest()
request.onreadystatechange=function () {
if(request.readyState==4)
{
window.location='story.php?id='+sid;
console.log(request.responseText)
}
}
request.open('POST','updatestory.php',true)
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.send('sid='+sid+'&text='+value)
}
</script>
</body>
</html>
There should be no reason to tamper with URI length.
You should instead send the story text data as HTTP POST message body, and the submission could be inside HTML form element.
See W3 PHP5 Form Handling
I couldn't figure out how to change my code, so I've increased URI length for now.
I have this code, which checks a database and returns some rows to my PHP code containing 4 values (id, playerA, playerB, turn, all INT).
I would like to use that array to build up a table and then append the table to a specific location in the DOM, but i dont know how i could do that.
I could do it another way (get the rows via JS Ajax and then use JS to build and append the table), which i know how, but i dont want to do that.
Is it possible to create a table and append it to a div using php/html/css ?
thanks
<?php
if (isset($_SESSION["userid"])){
$dbManager = DBManager::app();
$manager = new Manager($_SESSION["userid"]);
$gameList = $manager->getGames();
if ($gameList) {
Debug::log("got active games: ".sizeof($gameList);
}
else {
Debug::log("no games");
}
}
else {
Debug::log("no user id");
}
?>
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='style.css'/>
<script src="jquery-2.1.1.min.js"></script>
<script src='script.js'></script>
<script src='ajax.js'></script>
</head>
<body>
<input type="button" value="createGame" onclick="createGame()">
<divid="gameListDiv">
<div>LOGOUT</div>
</body>
</html>
EDIT
<?php
$table = "";
if ($gameList) {
foreach ($gameList as $game){
$table += "<tr>";
$table += "<td>";
$table += $game["name"];
$table += "</td>";
$table += "</tr>";
}
$table += "</table>";
}
?>
<body>
<input type="form" id="gameName" placeholder="Enter Game Name here"></input>
<input type="button" value="createGame" onclick="createGame()"></input>
<div>
<span>Active Games</span>
<?php echo $table; ?>
</div>
<div>LOGOUT</div>
</body>
You need to understand that the DOM does not yet exist - it is created by the browser, and the browser builds it based on the output of your combined PHP & HTML.
There are many ways to solve this problem without resorting to Ajax calls etc.
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' href='style.css'/>
<script src="jquery-2.1.1.min.js"></script>
<script src='script.js'></script>
<script src='ajax.js'></script>
</head>
<body>
<input type="button" value="createGame" onclick="createGame()">
<div id="gameListDiv">
<?php
if (isset($_SESSION["userid"])){
$dbManager = DBManager::app();
$manager = new Manager($_SESSION["userid"]);
$gameList = $manager->getGames();
if ($gameList) {
Debug::log("got active games: ".sizeof($gameList);
echo '<table style="width:100%">';
//assuming we can iterate over the $gameList value
foreach($gameList as &$game)
{
//here i assume that the result returned is an object with these properties - it might be the case that you need to do something like $game['playerA'] or $game->getData('playerA') - i am not sure what database lib you are using.
echo '<tr>
<td>'.$game->playerA.'</td>
<td>'.$game->playerB.'</td>
<td>'.$game->turn.'</td>
</tr>';
}
echo '</table>';
}
else {
Debug::log("no games");
}
}
else {
Debug::log("no user id");
}
?>
</div>
<div>LOGOUT</div>
</body>
</html>
In this example we are just running the PHP in-line with the HTML.
You could also do something like this if you wanted to keep all of your database logic at the top of the page and not in-line with the HTML:
<?php
/* Database logic here */
$variable = '<span>this variable could contain any old html that came from the database logic</span>';
?>
<html>
<head>
</head>
<body>
<php echo $variable; ?>
</body>
</html>
If you want to build the list before page load, you can just insert something like this where you want the table to go:
<table>
<?php foreach($gamelist as $game){ ?>
<tr>
<td><?=$game.id></td>
<td><?=$game.playerA></td>
<td><?=$game.playerB></td>
<td><?=$game.turn></td>
</tr>
<? } ?>
</table>
This will work because with PHP, the page hasn't been built and displayed to the user yet when you've got your data in $gamelist. All of your PHP code will be run before the page is actually sent to the user--which means you don't need to "update" the page later, you can just build it now.
If you're looking to collect or update your data after page load (it's unclear from your comments), this is impossible with only PHP as it's a server-side language. You would need to either reload the page or use AJAX for that.
Diving into a new project and trying to teach myself JSON,PHP,MySQL and Morris.js.
Some background into what I am trying to achieve.
I have a PHP file that goes out to a webpage and grabs JSON data. (Right now I just have it set to grab everything). Then with the data that it grabs it puts it into a mysql database. I have set a Cron job up right now to run this file every 1 minute, so that I can get some data flowing into this database.
<?php
//connect to mysql db
$con = mysql_connect('localhost','user','password',"") or die('Could not connect: ' . mysql_error());
//connect to the database
mysql_select_db('database', $con);
//read the json file contents
$jsondata = file_get_contents('http://192.168.10.243/j');
//convert json object to php associative array
$data = json_decode($jsondata, true);
//get the device details
$id = $data['data']['id'];
$type = $data['data']['type'];
$detector = $data['data']['detector'];
$cpm = $data['data']['cpm'];
$temperature = $data['data']['temperature'];
$uptime = $data['data']['uptime'];
//insert into mysql table
$sql = "INSERT INTO database_table_1(id, type, detector, cpm, temperature, uptime)
VALUES('$id', '$type', '$detector', '$cpm', '$temperature', '$uptime')";
if(!mysql_query($sql,$con))
{
die('Error : ' . mysql_error());
}
?>
After this, I then use PHP again to parse the information out of MySQL into a JSON array. Right now it will parse all the MySQL data it has (which I'm not sure if this is a good thing right now or if I should figure out a way to just parse the most recent data from MySQL.) Let me know what you think.
<?php
//open connection to mysql db
$connection = mysqli_connect('localhost','user','password','database_table_1') or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "select * from database_table_1";
$result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
//create an array
$emparray[] = array();
while($row =mysqli_fetch_assoc($result))
{
array_push(
$emparray,
array(
'a' => $row['timestamp'],
'w' => $row['id'],
'x' => $row['cpm'],
'y' => $row['temperature'],
'Z' => $row['uptime']
)
);
}
// $emparray[] = $row;
echo json_encode($emparray);
//close the db connection
mysqli_close($connection);
?>
Now if I was to run this PHP file by itself manually I would receive a lot of JSON data formatted just like this.
[{"a":"2015-08-17 21:34:01","w":"110000","x":"16","y":"28","Z":"112094"}]
Now my plan is to have this information update a chart or charts on a webpage using the morris.js charts. Here is my current index.html page with the PHP script and morris.js sections being near the bottom.
<!DOCTYPE html>
<html lang="en">
<!-- morris.js dependencies -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Chart V0.1</title>
<!-- Bootstrap Core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="css/simple-sidebar.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
<div id="sidebar-wrapper">
<ul class="sidebar-nav">
<li class="sidebar-brand">
<a href="#">
Start Bootstrap
</a>
</li>
<li>
Dashboard
</li>
</ul>
</div>
<!-- /#sidebar-wrapper -->
<!-- Page Content -->
<div id="page-content-wrapper">
<div id="myfirstchart" style="height: 300px;"></div>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<h1>Simple Sidebar</h1>
<p> This template has a responsive menu toggling system.</p>
Toggle Menu
</div>
</div>
</div>
</div>
<!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
<!-- PHP from Mysql to Json array -->
<?php
//open connection to mysql db
$connection = mysqli_connect('localhost','user','password','database_table_1') or die("Error " . mysqli_error($connection));
//fetch table rows from mysql db
$sql = "select * from database_table_1";
$result = mysqli_query($connection, $sql) or die("Error in Selecting " . mysqli_error($connection));
//create an array
$emparray[] = array();
while($row =mysqli_fetch_assoc($result))
{
array_push(
$emparray,
array(
'a' => $row['timestamp'],
'w' => $row['id'],
'x' => $row['cpm'],
'y' => $row['temperature'],
'Z' => $row['uptime']
)
);
}
// $emparray[] = $row;
echo json_encode($emparray);
//close the db connection
mysqli_close($connection);
?>
<!-- Json Pull -->
<script>
Morris.Area({
// ID of the element in which to draw the chart.
element: 'myfirstchart',
// Chart data records -- each entry in this array corresponds to a point on the chart.
data: <?php echo json_encode($emparray);?>,
// The name of the data record attribute that contains x-values.
xkey: 'a',
// A list of names of data record attributes that contain y-values.
ykeys: ['x'],
// Labels for the ykeys -- will be displayed when you hover over the chart.
labels: ['x-test']
});
</script>
<!-- jQuery -->
<script src="js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="js/bootstrap.min.js"></script>
<!-- Menu Toggle Script -->
<script>
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
</script>
So far I have figure most of this new project, though I am currently stumped on how to take the data that I can parse from my PHP script and feed it to a morris.js chart or charts. I would like to have it so the chart or charts will update themselves every 1 minute for now and that the morris.js charts will get their data from my PHP script.
Any help, ideas, links, or best practices would help out a lot. My coding experience is little to none so I do apologize in advance.
Thank you
UPDATE:
I migrated the PHP script out of the HTML page and tried calling the PHP results via $.getJSON in the HTML page. Though I still am not able to get morris.js to use the parsed data. I dont even get a chart Any ideas?
<!-- Ajax -->
<script>
$.getJSON('export_php_test_1.php', function( data ){
Morris.Area({
// ID of the element in which to draw the chart.
element: 'myfirstchart',
// Chart data records -- each entry in this array corresponds to a point on the chart.
data: data,
// The name of the data record attribute that contains x-values.
xkey: 'a',
// A list of names of data record attributes that contain y-values.
ykeys: 'x',
// Labels for the ykeys -- will be displayed when you hover over the chart.
labels: 'x-test'
});
});
</script>
You can use meta refresh. Following code will refresh the full html page automatically after 60 seconds.
<meta http-equiv="refresh" content="60">
If you want to refresh only the chart section, then you have to remove the inline php codes to a separate source, and use Ajax to fetch the data for morris. If you do so, then you can use JS function setInterval to run the Ajax in regular interval.
I have a few questions:
Part 1: I have a div with the id="hiddenID". I would like to create (if the sub folder does not exist) a subfolder with this id under the existing mainfolder sobimages.
And then to write the files in this new sub folder.
Note: Without the subfolder is it working!
Part 2: The uploaded files leave always the names and the success mnessage behind. I would like to delete this messages including the names of the uploaded files from the screen.
Part 3: Read before all file names in a simple Javascript array. I will then safe this with Json in the MySql-Databse. After your great help. I know how to do this, hehe
File body_editarticles.php
<?php session_start();
$_db_host = "myserver.com:3306";
$_db_username = "admin0";
$_db_passwort = "star1dgffh";
$_db_datenbank = "sob";
$_db_currentID ="";
# Verbindung zur Datenbank herstellen
$_link = mysql_connect($_db_host, $_db_username, $_db_passwort);
# Pr�fen ob die Verbindung geklappt hat
if (!$_link)
{
# Nein, also das ganze Skript abbrechen !
die("Keine Verbindung zur Datenbank m�glich: " .
mysql_error());
}
# Datenbank ausw�hlen
mysql_select_db($_db_datenbank, $_link);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" type="text/css" href="css/style.css">
<script type="text/javascript" src="js/scroll.js"></script>
<script type="text/javascript" src="js/jquery.js" ></script>
<script type="text/javascript" src="js/jquery.uploadfile.min.js"></script>
</head>
<body class="page page-id-11505 page-template-default" onload="jsRecordCurrent();">
<div id="page-wrap">
<?php
include('includes/header.html');
?>
<div id="hiddenID" style="display: none;"></div>
<div id="mulitplefileuploader" title="">
<br>
Upload
</div>
<div id="status"></div>
<script>
$(document).ready(function()
{
var settings = {
url: "upload.php",
method: "POST",
allowedTypes:"jpg,png,gif",
fileName: "myfile",
multiple: true,
onSuccess:function(files,data,xhr)
{
$("#status").html("<font color='green'>Upload successful</font>");
},
onError: function(files,status,errMsg)
{
$("#status").html("<font color='red'>Upload failed</font>");
}
}
$("#mulitplefileuploader").uploadFile(settings);
});
</script>
</div>
</div>
</div>
<div id="aside">
</div>
<br class="clearfloat" />
</div> <!-- End of main container -->
</div><!-- END Page Wrap -->
<div id="footer">
<br class="clearfloat" />
</div>
</body>
</html>
file "upload.php"
<?php
//If directory doesnot exists create it.
$output_dir = "sobimages/";
if(isset($_FILES["myfile"]))
{
$ret = array();
$error =$_FILES["myfile"]["error"];
{
if(!is_array($_FILES["myfile"]['name'])) //single file
{
$fileName = $_FILES["myfile"]["name"];
move_uploaded_file($_FILES["myfile"]["tmp_name"],$output_dir. $_FILES["myfile"]["name"]);
//echo "<br> Error: ".$_FILES["myfile"]["error"];
$ret[$fileName]= $output_dir.$fileName;
}
else
{
$fileCount = count($_FILES["myfile"]['name']);
for($i=0; $i < $fileCount; $i++)
{
$fileName = $_FILES["myfile"]["name"][$i];
$ret[$fileName]= $output_dir.$fileName;
move_uploaded_file($_FILES["myfile"]["tmp_name"][$i],$output_dir.$fileName );
}
}
}
echo json_encode($ret);
}
You could use mkdir to create folders and subfolders recursively before writing the files:
mkdir($path, 0777, true);
Note the third parameter, which means recursive
See the mkdir docs: http://php.net/manual/en/function.mkdir.php
1) send hiddenID value to ajax call
like var hiddenID = $("#hiddenID").val();
pass this id to ajax call, in PHP page you can get like $_POST['hiddenID];
then make a directory using the $_POST['hiddenID] using mkdir function (mkdir($pathtocreate, 0777, true);)
3) to read file names.....
http://www.html5rocks.com/en/tutorials/file/dndfiles/
I have problem I use several php codes inside html page and it gave me wrong result like this code
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Form</title>
</head>
<body>
<form method="post">
<input type="text" name="int1" />
+
<input type="text" name="int2" />
=
<?php
if (isset($_POST)) {
$int1 = $_POST['int1'];
$int2 = $_POST['int2'];
echo $int1 + $int2;
}
?>
<br />
<input type="submit" value="Get Sum" />
</form>
</body>
</html>
the right result is calculate the numbers and display it here is no thing display
the other code
<html>
<head></head>
<body>
<ul>
<?php for($i=1;$i<=5;$i++){ ?>
<li>Menu Item <?php echo $i; ?></li>
<?php } ?>
</ul>
</body>
</html>
the right result to display like this
Menu Item 1
Menu Item 2
Menu Item 3
Menu Item 4
Menu Item 5
but when I display the page just display like this
Menu Item
that is meaning the php code didn't work in the page
I don't know what is the solution I want to use php code and php functions inside html page
because phonegap.com not accept php page
You cannot run PHP in PhoneGap. PhoneGap loads a local html file in a native webview. You need to have PHP installed to run PHP and this not possible from a mobile device, even if you use native code.
You need to use JavaScript for the typr of processing you are looking for.
PHP code is processed only in PHP files ( files with .php extentions). If your file is .html, try to rename it. In your case the PHP not processed and you see anly first li.
Also I recommend to you set error_reporting = E_ALL in php.ini config and restart server. And then you will see what happened with your script
and better use:
<html>
<head></head>
<body>
<ul>
<?php for ($i=1; $i<=5; $i++) : ?>
<li>Menu Item <?php echo $i; ?></li>
<?php endfor; ?>
</ul>
</body>
</html>
Your first code does not return anything because your isset is not set.
First code:
<?php
if (isset($_POST['int1']) && isset($_POST['int2'])) {
$int1 = $_POST['int1'];
$int2 = $_POST['int2'];
echo $int1 + $int2;
}
?>
Second code:
<html>
<head></head>
<body>
<ul>
<?php
for($a = 1; $a <=5; $a++){
echo "<li>Menu Item ".$a."</li>";
}
?>
</ul>
</body>
</html>
EDIT: After closer inspection it looks as though your code is not being parsed, rename your index.html to index.php
If you view the source you can see the PHP code.
It could be your first section failing..
$_POST is always set but it can be empty
Try this
<?php
if (isset($_POST['int1'], $_POST['int2'])) {
$int1 = $_POST['int1'];
$int2 = $_POST['int2'];
echo $int1 + $int2;
}
?>
isset() can take multiple arguments