たけるのプログラミング

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

【PHP】PHPとIFTTTを使って簡単にLINEしてみた!!!【IFTTT】

こんにちは。

LINEは自分にとって革新的なアプリでした。中学時代流行った時、よく友達と夜遅くまでLINEしたものです。笑

というわけで今回はPHPとIFTTTを使ってLINEでメッセージを送りたいと思います。

IFTTTについては以下の記事も書いてます。

takeru232423.hatenablog.com
takeru232423.hatenablog.com

実行結果

f:id:takeru232423:20210917142149j:plain

IFTTTレシピ

f:id:takeru232423:20210917141610p:plain

イベントを受け取り、LINE Notifyという公式アカウントからメッセージを送ることができます。

ソースコード

これだけ

<?php
$key = "自分のKey";
$url = "https://maker.ifttt.com/trigger/自分のイベント名/with/key/".$key;


    $values = array(
    'value1' => "PHPプログラムからラインしました!!!");

    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($values));
    
    $response = curl_exec($curl);

    curl_close($curl);

www.php.net
www.php.net
www.php.net

感想

最近LINE Botに興味を持っています。

飲食店や薬局でLINEを活用していることをよく見るようになりました。

他のサービスと連携がしやすいので可能性は無限大です。

この記事に関してご指摘等ございましたら、コメント頂けるとありがたいです。

【PHP】会員登録なしで投票できる仕組みを考えてみた!【Cookie】

こんにちは。

クッキーといえばステラおばさんのクッキーが好きです、、、、、、



今回はタイトル通り、「会員登録なしで投票できる仕組み」について考えていきたいと思います。

最近、会員登録なしで投票ができるWebアプリを見かけます。

例えば以下のアプリ
tagvote.grinspace.jp

1度投票すると、再投票できない仕組みになっています。

1回目の投票はChromeを用いて投票しました。2回目としてSafariで投票しようとすると、、、投票できました。

つまりリクエストを送ってくるブラウザごとに何か値をプログラム上で設定して、認識していると思います。

結論、Cookieを使っているのではないかと考えました。

実際に同じ現象を再現すべく自分でプログラムを書いてみました。

実行結果

chromeで画面表示
f:id:takeru232423:20210912225428p:plain

投票してみる
f:id:takeru232423:20210912225518p:plain

画面を更新しても上記のまま

そして、そのままSafariで画面表示してみると、投票ができる
f:id:takeru232423:20210912225902p: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>
</head>

<body>
    <?php
    //ボタンが押されたらcookieをブラウザにセットする
    if (!empty($_GET)) {
        setcookie('is_pushed', $_GET['is_pushed'], time()+60*60*24);
        header('location:vote.php');
    }
    ?>
    <form action="" method="GET">
        <!--cookieに値があった場合(投票されていた場合)、disabled属性を追加して投票できなくする-->
        <button type="submit" name="is_pushed" value="pushed" <?php if (isset($_COOKIE['is_pushed'])) {
        echo 'disabled';
    } ?>><?php if (empty($_COOKIE['is_pushed'])) {
        echo '投票する!';
    } else {
        //cookieに値があった場合(投票されていた場合)
        echo '投票済み!';
    }?></button>
    </form>
</body>

</html>

www.php.net

比較的に簡単に実装できました。

感想

インストールとか会員登録とかはユーザーにとって、そのサービスを使うか使わないか判断する要因の一つだと考えています。

上記で紹介した投票サイトや、twitterでよく見かける匿名質問サービスのpeing(
Peing(ペイング) -質問箱- 匿名で質問を受け取ろう
)は会員登録が必要ないので、気軽に使えると感じるユーザーが多いのではないかと感じました。

この記事関して、間違い等ございましたらコメント頂けるとありがたいです。

【PHP】MediaWiki APIを使って情報を取得してみた!!!

MediaWikiAPIを使ってみました。

このAPIを使うことによりWikipediaのデータへアクセスすることができます。

さっそく、使ってみました。

実行結果

自分の好きなNBA選手「カーメロアンソニー」のWikipediaにおける最初の節の文章を取得しました。
f:id:takeru232423:20210908003141p: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>
</head>

<?php
$title = 'カーメロ・アンソニー';
$url = "https://ja.wikipedia.org/w/api.php?action=query&prop=extracts&exintro=1&explaintext=1&format=json&titles=".urlencode($title);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($curl);
curl_close();

$response_array = json_decode($response, true);//jsonデコードする、配列にする

$page_title = $response_array['query']['pages']['485246']['title'];
$explain_text = $response_array['query']['pages']['485246']['extract'];
?>

<body>
    <h1><?php echo $page_title ?></h1>
    <p><?php echo $explain_text ?></p>

</body>

</html>

解説

詳しい情報はこちら↓
ja.wikipedia.org

APIから情報を取得するためのエンドポイント

https://ja.wikipedia.org/w/api.php

パラメーター actionにqueryを指定し、MediaWikiからデータを取得する

https://ja.wikipedia.org/w/api.php?action=query

パラメーター propにextractsを指定し、指定されたページのテキストまたはHTMLを取得

https://ja.wikipedia.org/w/api.php?action=query&prop=extracts

パラメーター exintroに何かを指定して、最初の節の内容を取得する

https://ja.wikipedia.org/w/api.php?action=query&prop=extracts&exintro=1
exintroに何かが指定されていればtrueとして扱われます。上記ではexintro=1としましたが、exintro=2でも構いません。

パラメーター explaintextに何かを指定して、プレーンテキストとして抽出する

https://ja.wikipedia.org/w/api.php?action=query&prop=extracts&exintro=1&explaintext=1

パラメーター formatにjsonを指定して、データをjson形式で出力する

https://ja.wikipedia.org/w/api.php?action=query&prop=extracts&exintro=1&explaintext=1&format=json

json出力結果

f:id:takeru232423:20210908003042p:plain

感想

今回MediaWiki APIを使ってみましたが、このAPIは自作でWebアプリを作る際に使いやすいのではないかと思いました!

Wikipediaって本当に色々なジャンルの情報がありますしね!

記事に関して、ご指摘等ございましたらコメントいただけるとありがたいです。

【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