Author Archives: PHP-Archive

[PHP]Silexの基本的なルーティング方法とTwigによるビューの作り方

Share on Facebook
Bookmark this on Delicious
LINEで送る
Pocket

Silex は PHP 製のマイクロフレームワークで、EC-CUBE 3 のベースとしても利用されています。インストールには Composer が必要となりますのであらかじめインストールしておいて下さい。詳細は割愛しますが Linux, Unix, macOS であれば下記のようにしてインストールします。Windows の場合 exe 形式のインストーラーが公式に用意されています。

curl -s http://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

Silex 2.0のインストール

Silex のインストール方法は 2 種類あり、公式サイトからアーカイブファイルをダウンロードする方法と Composer 経由でインストールする方法があります。アーカイブファイルには必要最低限の slim 版と、全て入った fat 版がありますが、必要に応じてあとから追加していくこともできるので slim 版を使うのが良いと思います。今回は「silex-app」というフォルダ名で作業を進めていきますのでアーカイブ版を使う場合は展開してフォルダ名を変更して下さい。プロジェクトフォルダ名は自由につけても構いません。

Composer 経由でインストールする場合次のようにします。プロジェクト用のフォルダ「silex-app」を作り、そのフォルダ内にインストールします。(フォルダ名は一例ですので自由な名前をつけて読み替えて下さい。)

mkdir silex-app
cd silex-app
composer require silex/silex "~2.0"

これで Silex 本体はインストールされました。他にもテンプレートエンジンの Twig などが必要となりますので Composer で追加します。

composer require twig/twig
composer require symfony/twig-bridge

クラスファイルの自動読み込み(PSR-4)に対応するため、composer.json ファイルに手を加えます。
環境によってバージョンの違いはあると思いますが最終的に次のようになりました。

{
    "require": {
        "silex/silex": "~2.0",
        "twig/twig": "^1.24",
        "symfony/twig-bridge": "^3.1"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    }
}

書き足したら「composer dump-autoload」コマンドで更新しておきます。

コントローラー、ビューの作成

次に現在のプロジェクトフォルダに「app」と「web」の2つのフォルダを作ります。アーカイブ版をダウンロードした場合すでに「web」フォルダがあるかもしれません。「web」フォルダは Web 公開フォルダとなりますのでドメインの割り当てる際はこのフォルダをルートにして下さい。画像ファイルや CSS、JS ファイルもこのフォルダ以下に置きます。

フォルダを作成したら「web」フォルダ内に移動し、「index.php」ファイルと、「.htaccess」ファイル(Apacheの場合)を作成して下さい。
ファイルの内容は次のとおりです。

web\index.php

<?php
require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();
$app['debug'] = true;
$app->get('/', function(){ return 'Hello, World!'; });

$app->run();

web\.htaccess

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    #RewriteBase /silex-app/web
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]
</IfModule>

環境によっては RewriteBase を書き換える必要があります。# を外して適宜編集して下さい。

用意ができたらサイトにWebブラウザでアクセスします。ドメインを利用しない場合「http://localhost/silex-app/web」のようなアドレスになっていると思います。正しく動作している場合ブラウザに「Hello, World!」の文字が表示されます。

「$app->get()」となっている部分がルーティング処理です。「/」にアクセスしたときの動作を定義しています。
単純なプログラムでない限りは例のようにせず、ページコントローラーを経由してビューを表示することになります。
まずはコントローラーのためのフォルダを作成します。「app\Controllers」となるように作成して下さい。
その中にファイル「HomeController.php」を作成して下さい。

app\Controllers\HomeController.php

<?php
namespace App\Controllers;

use Silex\Application;
use Symfony\Component\HttpFoundation\Request;

class HomeController
{
    public function index(Application $app, Request $request){
        $data = ['foo' => 'World'];
        return $app['twig']->render('index.twig', $data);
    }
}

render() によって表示するビューファイルを指定し、第2引数でビュー内で使える変数を連想配列の形で渡します。必要なければ空でも構いません。
上記の例では変数 foo に 値「World」を格納してビューに渡しています。

次にビューとなる Twig ファイルを用意します。プロジェクトフォルダに「views」フォルダを作成し、その中に index.twig ファイルを作成します。

views\index.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Silex</title>
    </head>
    <body>
        <h1>Hello, {{foo}}!</h1>
    </body>
</html>

基本的には HTML ファイルと変わりません。{{ 〜 }} を使うことで変数の内容などを表示します。この内容は自動的に安全な文字列に変換(エスケープ)されます。

コントローラーとビューが用意できたら Twig を使うための準備とルーティングを行います。再度 web\index.php を編集して下さい。twig.path には twig ファイルが格納されているフォルダのパスを指定します。

$app->register(new Silex\Provider\TwigServiceProvider(), [
    'twig.path' => __DIR__ . '/../views',
]);

$app->get('/', 'App\Controllers\HomeController::index')->bind('index');

get() の箇所を上のように書き換えます。これにより「/」にアクセスした際は HomeController のメソッド index() が実行されます。bind() によって一意な名前をつけておくと URL を生成する際に役に立ちます。ビューで下記のように名前を指定するとそのページへの URL が生成されます。

{{ url("index") }}

user/1234、post/1234 のようにユーザーIDや記事IDを URL からパラメータとして受け取る場合のルーティングは次のようにします。

$app->get('/post/{id}', 'App\Controllers\PostController::show')->assert('id', '\d+')->bind('post_show');

id は波括弧で括ります。assert() の正規表現によって id が数値のみである場合という条件にしています。
コントローラーでは次のようにして id の値を受け取れます。bind() ではアンダーバーで区切って「post_show」と名付けました。

app\Controllers\PostController.php

public function show(Application $app, Request $request, $id){
    //
}

引数 $id の中に ID の値が格納されます。この場合に Twig ビューで URL を生成するには次のようにします。

{{ url('post_show', {'id': 1234}) }}

コントローラーで「/?category=1」のような GET や POST パラメーターを受け取るには Request を使います。

$request->get('category');

以上が基本的な流れとなります。ここで紹介したクラス名やファイルの設置場所はあくまで例であり、どんな名前をつけるか、どこに置くかについてはアプリケーションに応じて変更して下さい。

Posted in PHP | Tagged , , | Leave a comment

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

Share on Facebook
Bookmark this on Delicious
LINEで送る
Pocket

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>

Posted in PHP | Tagged | Leave a comment

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

Share on Facebook
Bookmark this on Delicious
LINEで送る
Pocket

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

<script>
$(function(){
    $('.btn').on('click', function(){
        $(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(){
        $(this).toggleClass('active');

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

変更後の文字が単純な場合や、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(){
                $(this).toggleClass('active');
            });
        });
        </script>
    </head>
    <body>
        <a class="btn" href="javascript:void(0)">
            <span>Click</span>
            <span>Done</span>
        </a>
    </body>
</html>

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

Posted in CSS, HTML, JavaScript | Tagged , , | Leave a comment