[PHP]HTMLフォームで検索条件を解除するリンクを作る

form

条件検索で絞りこみすぎた場合のために、条件を取り消すボタンを用意するケースはよくあります。
GET方式のフォームであればそのパラメータを除いたリンクを作るだけなのですが、配列からキー名を文字列で指定して取り除く処理が思ったよりややこしかったため下記ページを参考にさせていただきました。

参考:『ドットチェイン表現で配列要素をget/set/unset – Qiita』
http://qiita.com/mpyw/items/185c00306b7d7d6a06d0

<?php
$requests = [];
if(isset($_GET['q']) && $_GET['q'] !== ''){
    $requests['q'] = filter_input(INPUT_GET, 'q');
}

if(isset($_GET['options'])){
    $requests['options'] = filter_input(INPUT_GET, 'options',
     FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
}

function array_unset($array, $path, $separator = '.') {
    $keys = explode($separator, $path);
    $current = &$array;
    $parent = &$array;
    foreach ($keys as $i => $key) {
        if (!array_key_exists($key, $current)) return;
        if ($i) $parent = &$current;
        $current = &$current[$key];
    }
    unset($parent[$key]);
    return $array;
}

?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <form action="" method="GET">
            <div>Keyword: <input type="text" name="q" value=""></div>
            <p>
                <label><input type="checkbox" name="options[]" value="1">1</label>
                <label><input type="checkbox" name="options[]" value="2">2</label>
                <label><input type="checkbox" name="options[]" value="3">3</label>
            </p>
            <p><input type="submit" value="Search"></p>
        </form>

        <ul>
        <?php foreach($requests as $key => $value): ?>
            <?php if(is_array($value)): ?>
                <?php foreach($value as $key2 => $value2): ?>
                <li>
                    <?php printf('%s[%s]=%s', $key, $key2, $value2);?>
                    <a href="?<?php echo http_build_query(array_unset($requests, $key . '.' . $key2));?>">[remove]</a>
                </li>
                <?php endforeach;?>
            <?php else: ?>
            <li>
                <?php echo $key .  '=' . $value;?>
                <a href="?<?php echo http_build_query(array_unset($requests, $key));?>">[remove]</a>
            </li>
            <?php endif; ?>
        <?php endforeach; ?>
        </ul>
    </body>
</html>

[CSS, jQuery]クリックされたボタンの色を変更したり文字を書き換えたりする

ボタンをクリックした際にクリック済みを表すクラスを付ける場合は jQuery の addClass() や toggleClass() を使用すれば簡単です。
toggleClass() はクリックするごとにつけたり外したり出来ます。

<script>
$(function(){
    $('.btn').on('click', function(event){
		event.preventDefault();
        $(this).toggleClass('active');
    });
});
</script>

これでクラス名「btn」を持つ要素をクリックした際、その要素に「active」というクラスが追加されます。
クリック済みの要素の色を変えるだけなら「.btn.active」に対して CSS を書くだけで終わりです。
しかし、クリックしたらボタンの文字を書き換えたい場合、更に一工夫必要です。

click-done

javascript を使って書き換えてしまうなら jQuery の html() で変更できます。
data属性を使ってデフォルトの文字「data-text-default」、クリック後の文字「data-text-clicked」を持たせて、ボタンの状態に応じてテキストを書き換えます。
hasClass() を使うとクラス active を持っているかどうかを簡単に確認できます。

<a class="btn" data-text-default="Click" data-text-clicked="Done" href="#">Click</a>
$(function(){
    $('.btn').on('click', function(event){
		event.preventDefault();
        $(this).toggleClass('active');

        if($(this).hasClass('active')){
            var text = $(this).data('text-clicked');
        } else {
            var text = $(this).data('text-default');
        }

		$(this).html(text);
    });
});

変更後の文字が単純な場合や、javascript を自由に書き換えられる状態ならこれでも良いのですが、そうでない場合は CSS で切り替えを表現します。

Demo

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CSS</title>
        <script src="https://code.jquery.com/jquery-1.12.4.min.js"
            integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
            crossorigin="anonymous"></script>

        <style>
        .btn
        {
            display: block;
            width: 96px;
            height: 32px;
            line-height: 32px;
            background-color: #3692ff;
            color: #fff;
            text-align: center;
        }

        .btn.active {
            background-color: #ccc;
        }

        .btn > span:last-of-type,
        .btn.active > span:first-of-type
        {
            display: none;
        }

        .btn.active > span:last-of-type {
            display: inline;
        }
        </style>

        <script>
        $(function(){
            $('.btn').on('click', function(event){
				event.preventDefault();
                $(this).toggleClass('active');
            });
        });
        </script>
    </head>
    <body>
        <a class="btn" href="#">
            <span>Click</span>
            <span>Done</span>
        </a>
    </body>
</html>

ボタン要素 <a> 内にある2つの span のうち、最初のものがデフォルトに表示され、2番めがクリック後に表示されます。
必要に応じて <span> 内で <img> などを使っても構いません。
クラス active がつけられると、最初の span が非表示にされ、2番めの span が表示されます。
CSS はやや複雑ですが、Javascript 部分はクラスをつける処理だけあればいいので簡潔に出来ます。

[PHP]「mailto:」リンクでデフォルトの件名や本文に含まれるスペースや改行を正しく出力する

<a>タグの href 属性に「mailto:」を用いるとクリック時に送り先が設定された状態で標準のメーラーが立ち上がります。
パラメータとして subject を使うと件名が設定され、body を使うと本文を設定できます。
書式としては「mailto:送信先アドレス?subject=件名&body=本文」という形になりますが、
リンク内に日本語などのマルチバイト文字が含まれていてはいけないため、URLエンコードという処理を行い、
URL として正しくする必要があります。

PHP にはそういった場合 urlencode() や rawurlencode() などの関数が用意されています。
どちらも同じ役割ですが、urlencode() はスペースを「+」として変換し(RFC 1738)、
rawurlencode() はスペースを「%20」として変換する(RFC 3986)などの変換方式の違いが有ります。
メールリンクの場合は rawurlencode() の方を使用します。(より正確には RFC 6068 に従う必要がありますが実用範囲では互換性があります。)

また、subject や body, cc など複数のパラメータを用いる場合は http_build_query() を
使うと綺麗に書くことが出来ます。これは連想配列の形で複数のパラメータを受け取り、URLエンコードした状態でリンクを出力する為の関数です。
標準では urlencode() と同じ RFC 1738 による変換が行われますが、第4引数に PHP_QUERY_RFC3986 を
使うことで rawurlencode() と同じ RFC 3986 での変換を行うことが出来ます。
加えて第3引数を「&amp;」とすると区切り文字の「&」自体もエスケープすることが出来ます。

<?php
$body = <<<EOD
一行目
二行目
三行目
EOD;

$query = http_build_query([
    'subject' => 'ここに件名が入ります',
    'body' => preg_replace('/\R/', "\r\n", $body)
], null, '&amp;', PHP_QUERY_RFC3986);
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>mailto test</title>
    </head>
    <body>
        <a href="mailto:email@example.com?<?php echo $query;?>">Email</a>
    </body>
</html>

本文などで改行を行う場合は改行コードとして「\r\n」(CR+LF)を用います。これは変換すると「%0D%0A」として表されます。
上記サンプルでは preg_replace() によって統一しています。