たけるのプログラミング

作ったものとか、気ままにアップします。

【PHP】Pagination(ページネーション)を作ってみた!!!

今回は、長いコンテンツやページを分割する際に使われる「ページネーション」を作っていきたいと思います。

完成品

5データごとにページを変える

f:id:takeru232423:20210902130424p:plain

7をクリックすると
f:id:takeru232423:20210902130546p:plain

ソースコード

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="style.css" rel="stylesheet">
</head>

<body>
    <?php
//db接続処理
try {
    $db = new PDO('mysql:dbname=testing;host=localhost;charset=utf8', 'root', 'root');
} catch (PDOException $e) {
    echo 'DB接続エラーが起こりました。'. $e->getMessage();
}
if (isset($_GET['page'])) {
    $page=$_GET['page'];
    if ($page>=7) {
        //1〜6ページの時はページネーションが1〜10
        //7ページ目は2〜11になる → 7-5 と 7+4
        //8ページ目は3〜12になる → 8-5 と 8+4
        $page_first = $page - 5;
        $page_last = $page + 4;
    }
} else {
    $page=1;
}

//全データ数を取得
$count_data = $db->prepare("SELECT COUNT(*) FROM pagination");
$count_data->execute();
$count_data = $count_data->fetch(PDO::FETCH_COLUMN);

//5個ずつ表示する
$pagination=5;

//ページごとのデータのヘッドのインデックス
$page_per_data_head = $pagination*($page-1);

//必要なページ数を計算
$pages = ceil($count_data/$pagination);

//LIMIT0、10 の意味は 1番目のデータから10個データを取得する。
//0が1というのは配列のインデックスと同じイメージです。
$comments = $db->prepare("SELECT comment FROM pagination LIMIT ?,5");
$comments->bindParam(1, $page_per_data_head, PDO::PARAM_INT);
$comments->execute();
$comments_list = $comments->fetchAll(PDO::FETCH_ASSOC);

?>
    <!--コメント表示-->
    <div class="comment_area">
        <?php foreach ($comments_list as $comment) { ?>
        <p><?php echo $comment['comment'];  ?></p>
        <br>
        <?php } ?>
    </div>
    <!--10ページ以下だった場合は全て表示-->
    <div class="pagination_area">
        <?php if ($pages<=10) {?>
        <?php for ($i=1;$i<=$pages;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>

        <!--10ページより多かった、かつ現在6ページ以下の場合-->
        <?php } elseif ($pages>10&&$page<=6) {?>
        <?php for ($i=1;$i<=10;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>

        <!--10ページより多かった、かつ現在6ページより大きい場合-->
        <?php } elseif ($pages>10&&$page>6) {
    if ($page_last>=$pages) {
        $page_last = $pages;
    } ?>
        <?php for ($i=$page_first;$i<=$page_last;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>
        <?php
} ?>
    </div>

</body>

</html>

コードの説明

データベースの接続
//db接続処理
try {
    $db = new PDO('mysql:dbname=testing;host=localhost;charset=utf8', 'root', 'root');
} catch (PDOException $e) {
    echo 'DB接続エラーが起こりました。'. $e->getMessage();
}
テーブルのデータ数を取得
//全データ数を取得
$count_data = $db->prepare("SELECT COUNT(*) FROM pagination");
$count_data->execute();
$count_data = $count_data->fetch(PDO::FETCH_COLUMN);

SQLのCOUNT(*)で行数をカウントして、fetchして、COUNT(*)カラムの最初の行の値を取得して、その値を$count_dataに入れる。

1ページに表示するデータ数を指定
//5個ずつ表示する
$pagination=5;

$paginationに代入する。

必要なページ数を計算する
$pages = ceil($count_data/$pagination);

先ほど計算したデータ数である$count_dataを、$paginationで割り、必要なページ数を計算し、その値を$pagesに入れる。例えば4.1だった場合、5ページ必要なのでceil()関数を使い切り上げを行う。

5個データを抽出する
$comments = $db->prepare("SELECT comment FROM pagination LIMIT ?,5");
$comments->bindParam(1, $page_per_data_head, PDO::PARAM_INT);
$comments->execute();
$comments_list = $comments->fetchAll(PDO::FETCH_ASSOC);

SQLのLIMITについて、プログラミングにおける配列をイメージする。例えば1個目のデータから5つデータを抽出する場合 " LIMIT 0,5 "と 指定する。つまり1ページ目のデータはLIMIT 0,5と指定し、2ページ目のデータはLIMIT5,5、3ページ目のデータはLIMIT10,5とSQLを指定する。つまり第二引数は5固定で第一引数は以下のコードのように指定する。

$page_per_data_head = $pagination*($page-1);

5データずつページを区切るので、$paginationの値は5、に現在いるページ数から1引いたものをかけることによって第一引数を求めることができる。

ページネーションのリンクの設定
if (isset($_GET['page'])) {
    $page=$_GET['page'];
    if ($page>=7) {
        //1〜6ページの時はページネーションが1〜10
        //7ページ目は2〜11になる → 7-5 と 7+4
        //8ページ目は3〜12になる → 8-5 と 8+4
        $page_first = $page - 5;
        $page_last = $page + 4;
    }
} else {
    $page=1;
}

URLのパラメータpageの値を$pageに代入する。

もし7ページだった場合、

7-5=2 3 4 5 6 7 8 9 10 11=7+4

もし8ページだった場合、

8-5=3 4 5 6 7 8 9 10 11 12=8+4

になるようにするため、数列の最初と最後の値を$page_first、$page_lastに代入する。

ページネーションのリンク表示①
  <?php if ($pages<=10) {?>
        <?php for ($i=1;$i<=$pages;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>

        <!--10ページより多かった、かつ現在6ページ以下の場合-->
        <?php } elseif ($pages>10&&$page<=6) {?>
        <?php for ($i=1;$i<=10;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>
ページネーションのリンク表示②
 <?php } elseif ($pages>10&&$page>6) {
    if ($page_last>=$pages) {
        $page_last = $pages;
    } ?>
        <?php for ($i=$page_first;$i<=$page_last;$i++) { ?>
        <a href="http://localhost:8888/pagination/index.php?page=<?php echo $i ?>"><?php echo $i ?></a>
        <?php } ?>
        <?php
} ?>

$page_lastを$page + 4で求めましたが、$pageの数によっては必要なページ数である$pagesを超える場合があります。
そのため

  if ($page_last>=$pages) {
        $page_last = $pages;
    } ?>

を記述し、$page_lastが$pagesを超えた場合に、$page_lastを$pagesの値にします。こうすることで無限にページネーションのリンクが出現することを防ぎます。

最後に

競技プログラミングぽくアルゴリズム考えるの面白かったです。

何かご指摘等ございましたら、コメントいただけたらありがたいです。

【PHP】Web APIを作ってみた。【Lakers】

普段APIを使う側なので、作るのも体験しようかと思い簡単なAPIを作ってみました。

NBAが大好きなので、NBAに関するAPIを作りたいと思い、その中でもLeBron、ADが率いるLakersが好きなので、Lakersに関するテーマにしました。

API概要

PPG(1試合平均得点)、RPG(1試合平均リバウンド)、APG(1試合平均アシスト)のスタッツをパラメータに指定し、そのスタッツ以上の選手の情報をjson形式で返すというものです。

今回は2020-21シーズンのスタメンのデータを利用します。

f:id:takeru232423:20210828221432p:plain

実行結果

パラメータに何も指定しなかった場合

http://localhost:8888/make_api/my_api.php
f:id:takeru232423:20210828222155p:plain

ちなみにChrome拡張機能を使っています。
chrome.google.com

ソースコード

<?php
//db接続処理
try {
    $db = new PDO('mysql:dbname=lakers_api_db;host=localhost;charset=utf8', 'root', 'root');
} catch (PDOException $e) {
    echo 'DB接続エラーが起こりました。'. $e->getMessage();
}
//パラメーターはppgとrpgとapg
//指定された値以上の選手の情報をjson形式で出力する

if (isset($_GET['ppg'])) {
    //平均得点を取得
    $PPG = $_GET['ppg'];
} else {
    //0とすれば指定しないのと同じ
    $PPG = 0;
}
if (isset($_GET['rpg'])) {
    //平均リバウンドを取得
    $RPG = $_GET['rpg'];
} else {
    $RPG = 0;
}
if (isset($_GET['apg'])) {
    //平均アシストを取得
    $APG = $_GET['apg'];
} else {
    $APG = 0;
}

$statement = $db->prepare('SELECT * FROM member WHERE ppg >= ? AND rpg >= ? AND apg >= ?');
$statement->execute(array($PPG,$RPG,$APG));
$row_count = $statement->rowCount();
$loop_counter = 0;
header("Content-type: application/json; charset=utf-8");
echo "[\n";
while ($info = $statement->fetch()) {
    $loop_counter++;
    echo "{\n";
    echo "\"name\":"."\"".$info['name']."\",";
    echo "\n";
    echo "\"number\":".$info['number'].",";
    echo "\n";
    echo "\"PPG\":"."".$info['ppg'].",";
    echo "\n";
    echo "\"RPG\":"."".$info['rpg'].",";
    echo "\n";
    echo "\"APG\":"."".$info['apg']."\n";
    if ($row_count==$loop_counter) {
        echo "}\n";
        break;
    }
    echo "},\n";
}
echo "]";

アコーディオンメニューを作ってみた【jQuery】【Material icons】

crestadesign.org

こちらの記事ではアコーディオンメニューにおけるメニューの開閉状態を示す矢印をCSSの擬似要素で作っていました。

他の方法として思いついたのは、googleのMaterial icons の利用です。
fonts.google.com


実行結果(上記記事のコードを利用させていただいています。)


See the Pen
by sk (@sk232423)
on CodePen.


<span class="material-icons-outlined">expand_more</span>
<span class="material-icons-outlined">expand_less</span>

spanタグで囲う文字によりアイコンの種類を指定します。このときexpand_moreが下向きのアイコンを表しているので、javascriptでクリックイベントを検知し、spanタグが囲う文字がexpand_moreだった場合にexpand_lessに入れ替え、上向きのアイコンにします。再びクリックされた際にその逆を行うという原理です。

LP作ってみたので、FireShot使ってみた。

横浜の企業のLPを想定して以下のようなLPを作ってみました。

GitHub - Shota232423/lp_yokohama


https://shota232423.github.io/lp_yokohama/


作ってみてページ全体のスクリーンショットが撮りたくなったので、撮り方について調べてみました。


すると方法は大きく2つで、ブラウザのデベロッパーツールを使うか、ブラウザの拡張機能を使う方法があるみたいです。


今回は後者のブラウザの拡張機能のFireShotを使ってみました。


chrome.google.com


addons.mozilla.org


使ってみた結果
PC
f:id:takeru232423:20210822222030p:plain


SP
f:id:takeru232423:20210822222208p:plain

【PHP】APEX LEGENDS TRACKER APIを使って、ユーザー情報を取得してみた!!!

www.itmedia.co.jp

上記の記事によると、FPSゲームをプレイすると、仕事や勉強などにも関係する「課題遂行能力」が向上する


実際に自分はよくAPEX LEGENDSをプレーしていますが、課題遂行能力が向上したかは自分ではよく分かりません、、、


apex をプレーしている最中にふと思いつきました。


apexのapiってあるのかな?


調べてみるとありました。
apex.tracker.gg

まず上記サイトからユーザー登録し、api keyを取得します。

今回は、自分の好きなストリーマーのKHさんhttps://www.twitch.tv/dtn_khのapexのスタッツを取得することをゴールとします。!!!

実行結果

f:id:takeru232423:20210813162608p:plain

khさんの情報を取得することができました。取得したデータを利用するならjsonデコードする感じですね。

ソースコード

<?php
    $header = array(
        "TRN-Api-Key:取得したapi keyを指定してください"
    );
        //urlの形式
        //https://public-api.tracker.gg/apex/v1/standard/profile/{PLATFORM}/{NAME}
        //Platforms: 1 = XBOX 2 = PSN 5 = Origin / PC
        $url = "https://public-api.tracker.gg/v2/apex/standard/profile/5/dtn_kh";

        //user情報取得
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        //実行!!!
        $response = curl_exec($curl);
        //ブラウザでjsonを表示してみる!!!
        echo $response;
        curl_close();

説明

apiを利用するためには、httpリクエストヘッダーにapi keyを渡す必要があります。

githubのreadmehttps://github.com/TrackerNetwork/TRN.Developers
によると

Name: TRN-Api-Key Value: Your api key

のように指定するようです。

さいごに

大学でもapexはとても人気で、apexが共通の話題で他の学部の子ともコミュニケーションが取りやすいです!


ご指摘等ございましたら、コメント頂けるとありがたいです。

【Chart.js】モノカブのチャート真似して作ってみた!!!

私はスニーカー収集が趣味で、毎日スニーカーのリセール価格をチェックしています。


リセール市場として今人気なのが、モノカブやスニーカーダンクと呼ばれるサービスです。


モノカブでAirMax95のイエローグラデを買いましたが、非常に使いやすいサービスでした。


モノカブでは以下の画像のように、リセール価格の相場をチャートで知ることができます。

f:id:takeru232423:20210812194339p:plain
(https://monokabu.com/items/nike-air-max-95-og-crystal-blue より引用)


私はこのチャートを見て思いました。どうやって作ってるんだろう。「モノカブ チャート 作り方」みたいな感じで調べても出てこなかったので


グラフを作ることができるライブラリを調べていたら「Chart.js」というライブラリを知りました。


実際に使ってみました。

実行結果

f:id:takeru232423:20210812194156p:plain

ソースコード

html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.4/Chart.min.js"></script>
  </head>
  <body>
    <canvas id="myChart"></canvas>
    <script type="text/javascript" src="index.js"></script>
  </body>
</html>
javascript
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['2021/8/1', '2021/8/2', '2021/8/3', '2021/8/4', '2021/8/5', '2021/8/6', '2021/8/7'],
    datasets: [{
      label: 'スニーカー',
      data: [12000, 19000, 30000, 17000, 60000, 30000, 70000],
      borderColor: "rgb(255, 110, 40)",
      backgroundColor: "rgba(255,110,40,0.5)"
    }]
  },
  options:{
    //ここにオプションを設定する
  }
});

感想

結構簡単にできました。普段使ってるサービスがどのようにできているのか調べたりするって面白いと思いました。

ご指摘等ございましたら、コメント頂けるとありがたいです。

PHPでtweetしてみた!!!

こんにちは、夏休みをstay homeで堪能しているたけるです。


突然PHPtweetしたくなったので、実際にtweetしてみました。


twitter apiを使う方法がありますが、英語で申請したり結構めんどくさかった気がします。(※以前pythonapi使って遊んでました。)


なので今回はIFTTTというサービスを使いたいと思います。
ifttt.com


IFTTTについて知りたい方は、以前IFTTTについて書いた記事あるので、よかったらどうぞ!!!

takeru232423.hatenablog.com

実行結果

f:id:takeru232423:20210812142831p:plain



f:id:takeru232423:20210812123332p:plain

textareaに入力した文字をtweetできるという簡単なプログラム。

作り方

まずIFTTTでWebhooksとTwitterを使い、以下の構成のアプレットを作ってください!!!
f:id:takeru232423:20210812124650p:plain

上記画面のtwitterのedit部分を押しtweet内容を作ります。

f:id:takeru232423:20210812125319p:plain

PHPTweetしました!!!」は固定で、Value1の部分をtextareaで入力した文字が入るようにします。

ifttt.com

そして上記ページ画面のDocumentationから key と リクエスト用のurlを取得します。

これで準備完了です。

次にPHPのコードです。

<?php
$key = "自分のkeyを指定してください";
$url = "https://maker.ifttt.com/trigger/イベント名を指定してください/with/key/".$key;

if (!empty($_POST)) {
    $values = array(
    'value1' => $_POST['tweet']
);
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($values));
    
    $response = curl_exec($curl);

    curl_close($curl);
}
?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>テストツイート</title>
  
</head>

<body>
    <form action="" method="post">
        <textarea name="tweet" cols="50" rows="10"></textarea>
        <button>ツイート</button>
    </form>
    

</body>

</html>

ソースコードの説明

cURL関数についてのドキュメント
PHP: cURL 関数 - Manual

  • curl_init cURLセッションを初期化する
  • curl_setopt cURLオプションを設定

第1引数にはcurl_initが返すcURLハンドルを指定する。

第2引数にはオプション指定

  • CURLOPT_POST trueと指定することでhtmlのformと同じ形式でpostできる
  • CURLOPT_RETURNTRANSFER trueと指定することでcurl_execの返り値を文字列にできる ※特に今回のプログラムに関係ありません。
  • CURLOPT_POSTFIELDS postで送るデータを指定する。データの形式として、a=1&b=2みたいな形式や連想配列などを指定できる。本プログラムでは

PHP: http_build_query - Manual

を使い、データを指定した。

感想

IFTTTでGoogleのサービス、例えばドライブやスプレッドシートとも連携できるため、うまく利用できれば業務効率化に利用できるかもですね。

今回の記事について、ご指摘等ございましたらコメントよろしくお願いいたします。

参考記事
https://amg-solution.jp/blog/14245