Google Apps Script - 備忘録 - 001
Google Apps Scriptの練習のために簡単なWebアプリを作成してみました。
ドットインストールの「詳解PHP ウェブ開発編」を参考にさせて頂いております。
※プログラミング初級者が勉強の為の備忘録として書き綴ったメモとして利用しているため、内容に誤りもあるかと思いますが多めに見て下さると幸いです。
詳解PHP ウェブ開発編 » #03 PHPのコードを埋め込んでみよう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
<p>Today: <?= date('Y-m-d H:i:s l'); ?></p>
以下、GASのコード。
// コード.gs
function doGet(e) {
let temp = HtmlService.createTemplateFromFile('index');
let today = new Date();
today = replaceFormat(today, 'y-m-d h:n:s w');
temp.today = today;
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
function replaceFormat(today, format) {
let str = format;
str = str.replace(/y/, today.getFullYear());
str = str.replace(/m/, today.getMonth() + 1);
str = str.replace(/d/, today.getDate());
str = str.replace(/h/, today.getHours());
str = str.replace(/n/, today.getMinutes());
str = str.replace(/s/, today.getSeconds());
str = str.replace(/w/, getWeekName(today.getDay()));
return str;
}
function getWeekName(weekNum) {
let weekName = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
]
return weekName[weekNum];
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p>Hello, PHP!</p>
<p>Today: <?= today; ?></p>
</body>
</html>
JavascriptにはDateオブジェクトに表示形式を設定するメソッドがないので自作の「replaceFormat」関数を作成。
同様に、曜日を表示する関数もないので自作。→「getWeekName」
日付を埋め込むだけでこんなに記述量が必要とは。。
いきなりGASとPHPとの格差を体感。。
PHP便利。
詳解PHP ウェブ開発編 » #04 htmlspecialchars()を使ってみよう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
$name = 'Taro <script>alert(1);</script>';
<p>Hello, <?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?>!</p>
以下、GASのコード。
// コード.gs
function doGet(e) {
let temp = HtmlService.createTemplateFromFile('index');
temp.name = 'Taro <script>alert(1)</script>';
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p>Hello, <?= name; ?>!</p>
</body>
</html>
GASだとhtmlspecialchars関数を使わなくても”文字実体参照”にしてくれるみたい。
ただ、<?= name; ?> のところを <?!= name; ?> に変えるとアラートが生じるようになります。
標準スクリプトレット
構文<?...?>を使用する標準スクリプトレット、コンテンツをページに明示的に出力せずにコードを実行します。ただし、この例が示すように、スクリプトレット内のコードの結果は、スクリプトレット外のHTMLコンテンツに影響を与える可能性があります。
スクリプトレットの印刷
構文<?= ...?>を使用するスクリプトレットを印刷すると、コンテキストエスケープを使用してコードの結果がページに出力されます。コンテキストエスケープとは、AppsScriptがページ上の出力のコンテキストをHTML属性内で追跡することを意味します。クライアント側のスクリプトタグ内、またはその他の場所—クロスサイトスクリプティング(XSS)攻撃から保護するために、エスケープ文字を自動的に追加します。この例では、最初の印刷スクリプトレットが文字列を直接出力します。その後に、配列とループを設定する標準のスクリプトレットが続き、その後に、配列の内容を出力する別の印刷スクリプトレットが続きます。
スクリプトレットを強制印刷する
構文<?!= ...?>を使用するスクリプトレットの強制印刷は、コンテキストエスケープを回避することを除いて、スクリプトレットの印刷に似ています。スクリプトで信頼できないユーザー入力が許可されている場合は、コンテキストエスケープが重要です。対照的に、スクリプトレットの出力に、指定どおりに正確に挿入するHTMLまたはスクリプトが意図的に含まれている場合は、強制印刷する必要があります。原則として、必要があることがわかっている場合を除き、スクリプトレットを強制印刷するのではなく、スクリプトレットを印刷することを使用してください。 HTMLまたはJavaScriptを変更せずに印刷します。
上記はむりやりGoogle翻訳した結果。
エスケープは『< や > といった特殊記号を文字列に変換する』ということみたいです。
詳解PHP ウェブ開発編 » #06 配列を埋め込んでみよう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
<ul>
<?php if (empty($names)) { ?>
<li>Nobody!</li>
<?php } else { ?>
<?php foreach ($names as $name) { ?>
<li><?= h($name); ?></li>
<?php } ?>
<?php } ?>
</ul>
以下、GASのコード。
// コード.gs
function doGet(e) {
let temp = HtmlService.createTemplateFromFile('index');
let names = [
// 'Taro',
// 'Jiro',
// 'Saburo'
];
temp.names = names;
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<ul>
<? if (names.length == 0) { ?>
<li>Nobody!</li>
<? } else { ?>
<? for (let i in names) { ?>
<li><?= names[i]; ?></li>
<? } ?>
<? } ?>
</ul>
</body>
</html>
Javascriptにはempty関数と同じ処理の関数が無かった(もしあったらすみませんmm)ので、lengthプロパティを使用して代用しました。
PHPとJavascript、制御構文が似てるから関数も同じものが用意されてるかと思ってたけど、色々差がありますのね。
詳解PHP ウェブ開発編 » #10 フォームから値を受け取ってみよう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
<form action="result.php" method="get">
<input type="text" name="message">
<input type="text" name="username">
<button>Send</button>
</form>
$message = filter_input(INPUT_GET, 'message');
$username = filter_input(INPUT_GET, 'username');
<p><?= h($message); ?> by <?= h($username); ?></p>
<p><a href="index.php">Go back</a></p>
以下、GASのコード。
// コード.gs
function doGet(e) {
let page = e.parameter['page'];
if (page == null || page == 'index') {
let temp = HtmlService.createTemplateFromFile('index');
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
} else if (page == 'result') {
let temp = HtmlService.createTemplateFromFile('result');
let message = e.parameter['message'];
let username = e.parameter['username'];
temp.message = message;
temp.username = username;
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form action="https://script.google.com/macros/s/☆ID☆/exec" method="GET">
<input type="hidden" name="page" value="result">
<input type="text" name="message">
<input type="text" name="username">
<button>Send</button>
</form>
</body>
</html>
<!-- result.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p><?= message; ?> by <?= username ?></p>
<p><a href="https://script.google.com/macros/s/☆ID☆/exec?page=index">Go back</a></p>
</body>
</html>
GASだとformタグのaction属性にはアプリのURLを入力するので、htmlファイルを指定できない。
なので、hiddenタイプのinputタグを使ってhtmlファイルの名前を指定しました。
doGet関数でhtmlファイル名による分岐をし、それぞれの処理をしています。
詳解PHP ウェブ開発編 » #11 入力内容をチェックしよう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
$message = trim(filter_input(INPUT_GET, 'message'));
$message = $message !== '' ? $message : '...';
以下、GASのコード。
// コード.gs
function doGet(e) {
let page = e.parameter['page'];
if (page == null || page == 'index') {
let temp = HtmlService.createTemplateFromFile('index');
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
} else if (page == 'result') {
let temp = HtmlService.createTemplateFromFile('result');
let message = e.parameter['message'];
message = message.trim();
message = message !== '' ? message: '...';
temp.message = message;
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form action="https://script.google.com/macros/s/☆ID☆/exec" method="GET">
<input type="hidden" name="page" value="result">
<input type="text" name="message">
<button>Send</button>
</form>
</body>
</html>
<!-- result.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p><?= message; ?></p>
<p><a href="https://script.google.com/macros/s/☆ID☆/exec?page=index">Go back</a></p>
</body>
</html>
PHPはtrim関数、Javascriptはstringオブジェクトのtrimメソッド。
この違い毎回戸惑う。
詳解PHP ウェブ開発編 » #12 textareaから値を受け取ろう
以下、お手本のコード。
(有料コンテンツなので一部だけ)
<p><?= nl2br(h($message)); ?></p>
以下、GASのコード。
// コード.gs
function doGet(e) {
let page = e.parameter['page'];
if (page == null || page == 'index') {
let temp = HtmlService.createTemplateFromFile('index');
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
} else if (page == 'result') {
let temp = HtmlService.createTemplateFromFile('result');
let message = e.parameter['message'];
message = message.trim();
message = message !== '' ? message: '...';
message = nl2arr(message);
temp.message = message;
let output = temp.evaluate();
output.setTitle('PHP Practice');
return output;
}
}
function nl2arr(str) {
return str.split(/\n/);
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form action="https://script.google.com/macros/s/☆ID☆/exec" method="GET">
<input type="hidden" name="page" value="result">
<textarea name="message"></textarea>
<button>Send</button>
</form>
</body>
</html>
<!-- result.html -->
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? for (let i in message) { ?>
<p><?= message[i]; ?></p>
<? } ?>
<p><a href="https://script.google.com/macros/s/☆ID☆/exec?page=index">Go back</a></p>
</body>
</html>
Javascriptにnl2br関数がないので、nl2arrを自作。これで改行区切りの配列に変換してループ処理にした。
<?!= ?>を使えば、配列になんかせずに改行文字を<br>に置換すれば済むのだが、XSS対策を考えると上述のやり方しかないか。。
1万文字を超えたのでここまで。
この記事が気に入ったらサポートをしてみませんか?