お天気APIを試してみました。#超簡単コード

2022.11.21

Logging

おはようございます、今日は天気APIの話なので天気のお話はしませんが…。

さて、超簡単コードを記載しています。下記のソースコードとオープンウェザーマップのAPIKEYがあれば、誰でもプログラマーです。という事を言えば後ろから蹴られそうですが…。先ずは簡単なコードを見て勉強するのが大事かなって思います。

お天気APIを試してみました。#超簡単コード
API

いきなり難しいことを身に着けようと思っても、三日坊主になって先に進まないのが世の常ですw。なので、簡単なコードで楽しんで勉強するほうが大事かなって。

<?php
require "./assets/config.php";
$lat = "33.55972";
$lon = "133.53111";
$lang = "ja";
$url = "https://api.openweathermap.org/data/2.5/weather?units=metric&lang={$lang}&lat={$lat}&lon={$lon}&appid=".APIKEY;
$hasWeatherdata = json_decode(@file_get_contents($url));
print($hasWeatherdata->weather[0]->description);
print("<img src='./assets/images/". $hasWeatherdata->weather[0]->icon .".png.webp'>");
print((int)($hasWeatherdata->main->temp) . "℃");

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

0, 133.53111, 33.55972, API, APIKEY, assets, com, config, ea, https, ja, lang, lat, lon, lt, php, quot, require, url, , watch, www, Xn-VCyGQ, youtube, ウェザー, お話, コード, こと, ソース, プログラマー, マップ, 三日坊主, 下記, 世の常, , 今日, 勉強, 大事, 天気, 後ろ, 簡単, 記載, , , 超簡単,

md5でいいのかそれで?。 #wp #phpcode

2022.11.17

Logging

おはようございます、いきなり寒くなりましたね。朝起きるのに勢いが必要になってきました😆。

今日はワードプレスでもパスワードの暗号化に使用されているmd5に関して思うことがあります。そもそもmd5は強固な暗号なのか?、答えはnoだと思いますよ。md5を使用すると32文字の暗号化された文字列が返却されます。確かに暗号化されているですけど・・・。同じ文字をもう一度、暗号化すると同じ文字列が返却されます、なので暗号化された文字列になるかどうかで、元の文字が割り出せてしまいます。

総当たりすれば時間はかかりますがパスワードが分かちゃうので、パスワードを保存する方法としては△な感じかと思います。じゃ何が良いかといえばphpの場合、password_hashと言う関数があるので、そちらを使用した方が得策かと思います。Eメールなどはmd5でも良いかも知れませんが微妙。

echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

因みに、パスワードなどやメールアドレスを平文で扱っている開発会社はよく見かけます。何故、平文を放置しているかと言えば直す暇がないなどの理由からだと思います。また、クライアント様がそうして欲しいなどの理由もあります。そういう事から個人情報が保護されていないデータベースはあります。

尚、自分が使用しているWEBサービスも個人情報にあたる部分は暗号化しています。なので、データーが流出しても直ぐに情報が漏れるということはないと思っています🫠。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

32, 5, echo, hash, md, no, password, php, PHPCODE, quot, rasmusl, wp, こと, そちら, パスワード, プレス, メール, ワード, 一度, 今日, , 使用, 保存, , 勢い, 場合, 得策, 微妙, 必要, 文字, 文字列, , 方法, 時間, 暗号, 暗号化, , 答え, 総当たり, 返却, 関数,

htmlとcssとphp-初学非同期処理とおまけ-No.3

2022.11.14

Logging

おはようございます。月曜日の朝ですね‥お仕事探しは続いています。

さて、非同期処理とは何かと問われると詰まりますが・・・。いつ結果を返してくれない処理といえば良いのでしょうか。じゃ同期処理はといえば仕事が終わるまで次の仕事を進めない事といえば良いのかな🤔、教えるのが下手なのでぐぐってみてください。

document.querySelector(".btn").addEventListener("click", () => {
    let p = [document.querySelector("[name='name']").value, document.querySelector("[name='text']").value];
    [...document.querySelectorAll(".put")].forEach((elm, index) => {
        elm.innerText = p[index];
    });
    document.querySelector("#box2").style.display = "none";
    document.querySelector("#data").insertAdjacentHTML("beforeend", `<button class="btn2" type="button">非同期送信</button>`);
    document.querySelector(".btn2").addEventListener("click", async () => {
        //submit code
        let url = "./submit.php";
        let data = (() => {
            return ([...document.querySelectorAll(".put")].map((elm, index) => {
                return "test" + index + "=" + elm.innerText;
            })).join("&");
        })();
        const options = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                "Content-Length": data.length,
                'Accept': 'application/json'
            },
            body: data //JSON.stringify(data)
        };
        await fetch(url, options).then(response =>
            response.json()
        ).then(resultdata => {
            document.getElementById("view").insertAdjacentHTML("beforeend", resultdata.test0 + "," + resultdata.test1);
        }).catch(error => {
            console.log(error);
        });
    });
});


function imgchg(imagename){
    document.body.setAttribute("style","background-image: url(./assets/images/" + imagename + ".jpg.webp");
}

ぐぐると自分言っていた意味がなんとなく分かるかと思います。ちなみに非同期動画(youtube)のおまけとして、背景画像を変える処理のソースコードを書いています。プログラムコードとしては3行ですが、初学者の方はこの3行のソースコードの方が面白いのかもしれません。自分が書いたソースコードを所々、変更して動かしてみてください。そうすることで、徐々にコードの意味が理解してくると思います。

追伸:サンプルサイトの動画は少しお休みします()?

https://358tool.com/sample-site/

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

, 39, addEventListener, btn, click, css, document, gt, html, let, name, no, php, querySelector, querySelectorAl, quot, Text, value, いつ, おまけ, お仕事, , 仕事, , 処理, 初学, 同期, 月曜日, , , 結果,

POSTとGETの考え方について伝えている動画。 #以心伝心

2022.11.12

Logging

おはようございます、11月なのに寒くないって不思議です😗温暖化。

さて、POSTとGETの考え方について無音声(音楽あり)で伝えている動画です、以心伝心で意味が通じると良いですが、それではブログを書いている意味がないので要点だけ解説します。POSTとGETとは、インターネット上でデータの送信を行うのに使用します。POSTの利点はデータを隠して送れることと、比較的に重いデータも送れることにあります。ではGET送信の利点は、SEOに有利と言ったところでしょうか。

htmlとcssとphp-初学POSTとGETの考え方-No.2
htmlとcssとphp-初学POSTとGETの考え方-No.2

今回、POST送信とGET送信を行い、PHPのプログラムでPOSTとGETを受信する方法を動画で伝えています。次回は非同期処理を使用して送受信を行う方法をプログラムで書いていきます。

HTMLとPHPプログラムは下記のソースを参照下さいませ🙇。

<!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>demo site</title>
    <style>
html {
    width: 100vw;
    height: 100vh;
}

body {
    background-color: rgb(0, 0, 0);
    color: aliceblue;
    background-image: url(./assets/images/aig-mid22910-120-xl_TP_V.jpg.webp);
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center;
}

div.box {
    border-color: aliceblue;
    border-style: inset;
    position: absolute;
    width: 300px;
    height: 450px;
    color: white;
    border-radius: 1em;
    padding: 1em;
    top: 50%;
    left: 50%;
    margin-right: -50%;
    transform: translate(-50%, -50%);
    /* background-color: #ffffff80; */
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    overflow-wrap: break-word;
    text-align: center;
}

div>form>p {
    font-weight: bold;
    margin: 13px;
}

input {
    opacity: 0.5;
}

textarea {
    opacity: 0.5;
}

button {
    padding: 5px;
    border-radius: 1em;
    border-style: solid;
    border-color: aliceblue;
    background-color: aliceblue;
    color: rgb(0, 0, 0);
}
button:hover{
    border-color: rgb(255, 255, 255);
    border-style: inset;
    background-color: rgb(27, 76, 119);
    color: aliceblue;
}
.put:nth-child(2){
    overflow: auto;
    height: 120px;
}
    </style>
</head>
<body>
    <div class="box">
        <div id="box2">
            <form action="submit.php" method="post">
                <p>名前:<input type="text" name="name"></p>
                <p><textarea name="text" id="" cols="30" rows="10"></textarea></p>
                <p><button class="btn" type="submit">確認</button></p>
            </form>
        </div>
        <div id="data">
            <p class="put"></p>
            <p class="put"></p>
        </div>
    </div>
    <script src="./assets/js/main.js"></script>
</body>

</html>
<?php
var_dump(xss_d($_POST));
print(xss_d($_POST["name"])."<br>");
print(xss_d($_POST["text"])."<br>");

function xss_d(mixed $val){
    if(!isset($val))return false;

    if(is_array($val)){
        foreach ($val as $key => $value) {
            $val[$key] = strip_tags($value);
            $val[$key] = htmlspecialchars($val[$key],ENT_QUOTES);
        }
    }else{
        $val = strip_tags($val);
        $val = htmlspecialchars($val,ENT_QUOTES);
    }

    return $val;

}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

11, 2, css, DOCTYPE, GET, html, lt, no, php, POST, SEO, インターネット, こと, ソース, データ, ところ, ブログ, プログラム, 下記, 不思議, 今回, 以心伝心, 使用, 処理, 初学, 利点, 動画, 参照, 受信, 同期, 意味, 方法, 有利, 次回, 温暖化, 考え方, 要点, 解説, 送信, 送受信, 音声, 音楽,

Qiitaのfeedを取得して表示するだけのコード。 #php

2022.11.05

Logging

おはようございます、土曜日の朝ですね😗。

今日は文化の日にQiitaにUPしたfeedを取得して表示するだけのコードを書きました。見た目はこんな感じでQiitaの雰囲気を取り入れたデザインにしています。デモ版として実際にサーバーで起動しているモノです、feedを取得しているユーザーは自分を入れて3人です。

表示する人数が多くなるとページを描画する時間が遅くなるので実質、10人が限度かも知れないです。もし何人ものユーザーを取得したいと考えている方は表示部分と処理部分を別けて、尚且つ処理部分は非同期処理で変更することを推奨します。

尚、明日には2つに別けたプログラムコードを別記事として記載しますので、しばしお待ち下さいませ🙇。

今回のソースコードはこんな感じになってます。

<?php
    function get_Qiitafeed(string $feedUrl){
        $xml = @simplexml_load_file($feedUrl);
        if(isset($xml->entry)){
            print("<ul class='qiita_feed-list'>");
            foreach($xml->entry as $key=>$val){
                print("<li><a href='{$val->url}'>".$val->title."</a></li>");
            }
            print("</ul>");
        }
    }
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="Description" content="Enter your description here"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<style>
    .qiita_feed-list > li{
        /* font-weight: bold; */
        color:aliceblue;
    }
    .qiita_feed-list > li > a{
        color:aliceblue;
    }
    body{
        background-color:#60b111;
    }
    .shadow-lg {
        box-shadow: 0 1rem 3rem rgba(255,255,255,.195)!important;
    }    
</style>
<title>Qiita-feed</title>
<?php
    require $_SERVER['DOCUMENT_ROOT'] ."/header_script.php";
?>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <h1 class="text-light">Qiita-feed</h1>
            </div>
        </div>
    </div>
    <div class="container mt-2">
        <?php
            $Id_List = ["taoka-toshiaki","mpyw","suin"];
            foreach ($Id_List as $key => $id) {
            ?>
        <div class="row shadow-lg p-3 mb-5 bg-body rounded">
            <div class="col-12">
                🌿<span class="text-light">://qiita.com/<?=$id?>/feed :[引用]</span>
                <?=get_Qiitafeed("https://qiita.com/".$id."/feed")?>
            </div>
        </div>            
            <?php
            }
        ?>
        Copyright <?=date("Y")?>  <a href="https://358tool.com">358tool.com</a>
    </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.1/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script>
</body>
</html>

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

10, 2, , feed, feedUrl, function, GET, lt, php, qiita, Qiitafeed, string, UP, お待ち, コード, こと, サーバー, ソース, デザイン, デモ版, プログラム, ページ, もの, ユーザー, 人数, 今回, 今日, 何人, 処理, 別記事, 取得, 同期, 土曜日, 変更, 実質, 実際, 感じ, 推奨, 描画, 文化の日, , 明日, 時間, , 自分, 表示, 見た目, 記載, 起動, 部分, 限度, 雰囲気,

Photo by sohail nachiti on Pexels.com

常時ディレクトリ監視を行う方法。 #CPU使用率 #炎上

2022.11.03

Logging

おはようございます。何だかアカウントを作ってまでコメントする人の考えがわからない🤔。

Qiitaに、このコードのsleep関数がないバージョンをアップしたら、何やらアカウントを作ってまでコメントする人が現れる、理由はCPU使用率がMax近くになるのが駄目だからです、そんな事は分かっているのが普通だと思っていたのだけども…例文として掲載するのも駄目だそうです、コピペで運用する人が結構いるのかもしれない。

正直なところ、そこまで叩かれるとは思っていなかったので、正直なところ驚きを隠せない。段々と世間の常識とズレていっている気がします😗。

昔はそういうコードは巷に溢れていたのにな・・・そんな事も出来なくなってきたのか・・・。

トイウコトデ、常時ディレクトリ監視を行い任意の画像ファイルだけ別のディレクトリへ移動するコードです。

nohup php File_Check.php &
├── File_Check.php
├── upload
└── data
<?php
while(true){
    if($result = is_scandir("./upload")){
        foreach($result as $key=>$value){
            rename("./upload/$value","./data/$value");
        }
    }
    sleep(3);
}

function is_scandir(string $dirname="",array $ext_list = ["png","jpg"]){
    $is_filelest = [];
    $result = scandir($dirname);
    foreach($result as $key=>$value){
        $ext = substr($value, strrpos($value, '.') + 1);
        if(in_array($ext,$ext_list,false)!== false){
            $is_filelest[] = $value;
        }
    }
    return count($is_filelest)>0 ? $is_filelest : false;
}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

check, CPU, file, max, nohup, php, qiita, sleep, アカウント, アップ, コード, コピペ, コメント, そこ, ディレクトリ, トイウコトデ, ところ, バージョン, ファイル, 世間, , , 任意, 使用, 例文, , , 常時, 常識, 掲載, 方法, , 普通, 正直, 段々, , 炎上, 理由, 画像, 監視, 移動, 近く, 運用, 関数, 駄目,

staticかdynamicか、php-fpmの話。#php #apache

2022.11.01

Logging

おはようございます、メモリが肥大化して落ちました🤮。

先週の朝、メモリが肥大化して落ちてしまいました。今まではphp-fpmを1時間置きに再起動していましたが、それを変更した途端。メモリを食ってしまい落ちたわけです。

php-fpmの対応はこちらのサイトを参考にしました、尚、対応方法はそちらの記事を参照ください。その記事を読んでいて思ったことはやはりサーバーを増強したいということです。

でもVPSレンタルサーバーはサクサク表示させるには、結構お金がかかってしまいます、だったら固定IPを引いて自宅サーバーで運用した方が良いのかもしれないなってこの頃、思っています。

そうすればメモリはかなり詰めるし処理もそれなりに早くなります。恐らく瞬速で表示されるようになりますが、震災などが起きると忽ちダウンしてしまいますよね。

そう考えると・・・微妙ですね。

やはりVPSサーバーをもう一つ借りて調整するか、VPSサーバーと自宅サーバーを同期して運用するかだと…。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

, Apache, dynamic, IP, php, php-fpm, static, VPS, お金, かなり, こちら, こと, サーバー, サイト, そちら, それ, それなり, ダウン, はり, メモリ, もう一つ, レンタル, わけ, , 先週, 再起動, 処理, 参照, 参考, 固定, 増強, 変更, 対応, 微妙, , 方法, , 瞬速, 自宅, 表示, 記事, , 途端, 運用, 震災, ,

Photo by Aleksandr Slobodianyk on Pexels.com

phpでソケット受信をする事だけ覚えとけば良い。#php #code

2022.10.27

Logging

おはようございます。Socket.ioというサービスをご存知ですか。あれ良いですよね。

さて、Socketとはいう意味は割愛させて頂き、知っていることを前提に話しますとPHPでSocketサーバーは立てれないじゃないかなって今のところ思っています。localhostや0.0.0.0とかならSocketサーバーは立てれるけど、ドメイン有りきでは難しいような気がします。

なので、Socket.ioなんかを使用してnode.jsなんかでサーバーを立てるのが定石かと思います。尚、webSocketのサーバーに対してPHPで送受信は可能です。要するにクライアント側はPHPでも可能ですね。

自分もAPIサーバーに対して常時通信処理を行っています。

PHPライブラリの使用して接続を確立しています、ライブラリはratchetという有名所のライブラリを使用しています。

composer require ratchet/pawl
<?php

require __DIR__ . '/vendor/autoload.php';

\Ratchet\Client\connect('wss://example.com')->then(function($conn) {
    $conn->on('message', function($msg) use ($conn) {
        echo "Received: {$msg}\n";
        $conn->close();
    });

    $conn->send('Hello World!');
}, function ($e) {
    echo "Could not connect: {$e->getMessage()}\n";
});

上記のようなPHPのソースコードで送受信が可能です😋

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

0.0.0.0, API, Code, Composer, io, JS, localhost, node, php, ra, ratchet, require, Socket, webSocket, あれ, クライアント, こと, ご存知, サーバー, サービス, ソケット, ところ, ドメイン, なん, ライブラリ, , , 使用, 処理, 前提, 割愛, 受信, 可能, 名所, 定石, 常時, 意味, 接続, , , 確立, 自分, 送受信, 通信,

制限付きのクロンを無限寿限無にする方法。 #php #無限 #cron

2022.10.12

Logging

おはようございます🦏。昔の文章を読んでくれて今の記事を読まないユーザーさんがいます、凹む😖。

さて、今日はさくらレンタルサーバーでcronを制限以上に使う方法を数年前に書いた記事が未だに読まれたりするのでプログラムコードを直してタイトルも直してQiitaGithubにUPしました。

そのUPした記事があまりアクセスが跳ねなくて少しがっくりしたのがスポーツの日の朝の事です。Qiitaは何だか触りの記事かとても専門性の高い記事が人気を集めるだなって事を、この頃理解したのですが、自分は何方にも寄っていない記事なので跳ねないのかも知れません。

ソースコード貼り付けて置きます。尚、使い方などはQiitaGithubを参照してください。

<?php
date_default_timezone_set('Asia/Tokyo');
class cron
{
    public function __construct(mixed $filepath = "")
    {
        $val = @file_get_contents($this->pval($filepath));
        $obj_ = @json_decode($this->pval($val));
        $obj = (object)[];
        foreach ($obj_ as $key => $value) {
            $obj->name = "month";
            $obj->val = $value->m;
            if ($flg = $this->trigger_check($obj,"m",1,12)) {
                $obj->name = "day";
                $obj->val = $value->d;
                if ($flg = $this->trigger_check($obj,"d",1,31)) {
                    $obj->name = "hour";
                    $obj->val = $value->H;
                    if ($flg = $this->trigger_check($obj,"H",0,23)) {
                        $obj->name = "minutes";
                        $obj->val = $value->i;
                        if ($flg = $this->trigger_check($obj,"i",0,59)) {
                            $obj->name = "week";
                            $obj->val = implode(",", $value->w);
                            if ($flg = $this->trigger_check($obj,"w",0,0)) {
                                $this->command($value->command);
                            }
                        }
                    }
                }
            }
        }
    }
    public function command(mixed $command_val = "")
    {
        $command_val = $this->pval($command_val);
        exec($command_val . " > /dev/null &");
        // print "よろしくお願いします~~~!!".PHP_EOL;
        return true;
    }

    public function pval(mixed $val = "")
    {
        if (is_array($val)) {
            foreach ($val as $key => $value) {
                $val[$key] = strip_tags($value);
            }
        } else {
            $val = strip_tags($val);
        }
        return $val;
    }

    public function trigger_check(mixed $variable = "",mixed $d="",int $min=0 ,int $max=0)
    {
        if (!$variable) return false;
        if ($variable->val === "*") return true;
        switch ($variable->name) {
            case 'week':
                $value = @explode(",", $variable->val);
                return (int)$value[(int)date($d)] === 1 ? true : false;
                break;
            default:
                if (preg_match("/^(\*\/[0-9]{1,})$/", $variable->val)) {
                    $value = @explode("*/", $variable->val)[1];
                    if (is_numeric($value) && $value >= $min && $value <= $max) {
                        return (int)date($d) % $value === 0 ? true : false;
                    }
                }
                if (preg_match("/^([0-9]{1,}\,{1,})/", $variable->val)) {
                    $value = @explode(",", $variable->val);
                    $value = array_map('intval', $value);
                    return in_array((int)date($d), $value, true) === true ? true : false;
                }

                $value = (int)$variable->val;
                if (is_numeric($value) && $value >= $min && $value <= $max) {
                    return $value === (int)date($d) ? true : false;
                }
                return false;
                break;
        }
        return false;
    }
}

if($argv[1]){
    //argv
    new cron($argv[1]);
}


著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

39, Asia, class, cron, date, default, github, lt, php, public, qiita, set, timezone, Tokyo, UP, アクセス, クロン, コード, サーバー, さくら, スポーツ, ソース, タイトル, プログラム, ユーザー, レンタル, , 人気, , 今日, 何方, 使い方, 制限, 参照, 寿限無, 専門性, 少し, , 文章, 方法, , , , 未だ, 無限, 理解, 自分, 記事, ,

WP予約投稿ツイートプラグイン作り方。#php言語 #code #v2

2022.10.11

Logging

おはようございます😤 お仕事に飢えてます…寒い季節ですね…。

さて、今日はWP予約投稿ツイートプラグイン作り方を記載していきます。ワードプレスでプラグインを作る場合はWordPressの下記の場所に任意のフォルダを作り、その中にディレクトリ名(任意名)と同じファイル名でphpファイルを作ります。※昔の名残なので今は命名が違っても動くかも知れませんが・・・。

cd /wp-content/plugins
mkdir mytweets
vi mytweets.php

そして、命名したファイル名を開き、ファイルの上部に下記のコメントを記載します。プラグイン名やプラグインの説明、プラグインバージョンをそれぞれ変更して頂き保存、その後サーバーサイドにアップロードします(フォルダごと)。

<?php
/*
Plugin Name: My tweets
Description: tweets
Version: 1.0
*/

これで何も動作しないプラグインが出来上がります。

後はコマンドラインからプラグインフォルダにcomposerをインストールしtwitteroauthのライブラリを入れます。

此処までが前手順です。此処までで挫折した人は結構いると思います🙄。

因みに此処までの事がすんなりと出来る人は、このブログの情報は必要ないものです。なのでココからはソースコードを記載します。WP予約投稿ツイートプラグインなんてオチャノコサイサイだと思います。

<?php
/*
Plugin Name: My tweets
Description: tweets
Version: 1.0
*/
if (!defined('ABSPATH')) exit;
require_once  "tw-v2-config.php";
require_once  "./vendor/autoload.php";

use Abraham\TwitterOAuth\TwitterOAuth;

function mytweets($new_status, $old_status, $post)
{
    
    if ($new_status == 'publish' && $old_status != 'publish') {
        try {
            $connection = new TwitterOAuth(APIKEY, APIKEYSECRET, ACCESSTOKEN, ACCESSTOKENSECRET);
            $connection->setApiVersion('2');
            $response = $connection->post('tweets', ['text' => get_the_title($post->ID) . "\n" . get_permalink($post->ID)], true);
        } catch (\Throwable $th) {
            //throw $th;
        }
    }
}
add_action('transition_post_status', 'mytweets', 10, 3);

上記のコードを記載した上で上書き保存&アップロードします。その後ワードプレスの管理画面よりプラグインを有効にして出来上がり、今回はtwitteroauthのライブラリを使用しましたがcrulなどのを理解している人はライブラリは特に必要ないのかなとも思います。ライブラリを使用すればお手軽ですが、万が一何かあった時に困るのでライブラリを使用せずにコードを書くという方もいらっしゃると思います。

自分も極力、公式のライブラリしか使わないようにしています🙇。

トイウコデ、ワードプレスのプラグインの作り方でした。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

2, cd, Code, description, lt, mkdir, My, mytweets, name, php, plugin, plugins, Tweets, Vers, vI, WordPress, wp, wp-content, アップロード, お仕事, コメント, サーバー, それぞれ, ツイート, ディレクトリ, バージョン, ファイル, フォルダ, プラグイン, プレス, ワード, 上部, 下記, , 予約, , 今日, 任意, 作り方, 保存, 名残, 命名, 場合, 場所, 変更, 季節, , 投稿, , 言語, 記載, 説明,

数珠繋ぎのツイートシステムに予約機能を付けました😂 #php #code

2022.10.07

Logging

おはようございます、偏頭痛持ちは雨が降るが一番大変です☔。

先日、数珠繋ぎのツイートシステムを作ったのですが、そのシステムに予約機能を付けました。尚、TwitterAPIのバージョン2でスケジュールのパラメーターが今のところ無いですね。これから先、機能が付くかも知れないですが今のところ無いようです。因みにソースコードは近日中にQiitaGithubにUPします。此処ではソースコードの一部を掲載します(※記事を更新しました下へスクロール🫠)。

Twitter API v2 ツイート数珠繋ぎ

尚、crontabでPHPファイルを叩くようにしています、あと注意事項ですが予約を一度した投稿については変更等は出来ません、編集機能等の機能追加の予定はないです。また、予約管理はsqlite3を使用して管理しています。

<?php
date_default_timezone_set('Asia/Tokyo');
ini_set("display_errors",0);
require_once "./data/tw-config-v2.php";
require_once "../vendor/autoload.php";

use Abraham\TwitterOAuth\TwitterOAuth;

class tw
{
    var $connection = null;
    var $pdo = null;
    function __construct()
    {
        $this->connection = new TwitterOAuth(APIKEY, APISECRET, ACCESSTOKEN, ACCESSTOKENSECRET);
        $this->connection->setApiVersion("2");
    }
    function db_connection()
    {
        try {
            //code...
            $res = $this->pdo = new PDO("sqlite:./data/tw-tweets-db.sqlite3");
        } catch (\Throwable $th) {
            //throw $th;
            //print $th->getMessage();
            $res = false;
        }
        return $res;
    }

    function timecheck($timeonoff, $times)
    {
        if (!$timeonoff) return true;
        $n = new DateTime();
        $t = new DateTime($times);
        return $t <= $n ? true : false;
    }

    function pickup_tweets(mixed $tw_text = null, int $timeonoff = 0, mixed $times = null, string $id = "")
    {
        if (!$times) return false;
        $obj = (object)[];
        $times = preg_replace("/\-/", "/", $times);
        $times = preg_replace("/T/", " ", $times);

        if ($this->timecheck($timeonoff, $times)) {
            if (isset($tw_text) && is_array($tw_text)) {
                foreach ($tw_text as $key => $value) {
                    if (preg_replace("/[ | ]/", "", $value)) {
                        $obj = !$key ? ($this->connection->post("tweets", ["text" => $value], true)
                        ) : ($this->connection->post("tweets", ["reply" => ["in_reply_to_tweet_id" => $obj->data->id], "text" => $value], true)
                        );
                    }
                }
                return true;
            }
        } else {
            return $timeonoff ? $this->save_sqlite($tw_text, $timeonoff, $times, $id): true;
        }
    }

    function save_sqlite($tw_text = null, int $timeonoff = 0, mixed $times = null, string $id = "")
    {
        if ($this->db_connection()) {
            try {
                //code...
                if (isset($tw_text) && is_array($tw_text)) {
                    foreach ($tw_text as $key => &$value) {
                        if (preg_replace("/[ | ]/", "", $value)) {
                            $stmt = $this->pdo->prepare("insert into tweets (tw_id,user,times,tw_text)values(:tw_id,:user,:times,:tw_text)");
                            $stmt->bindValue(":tw_id", $key, PDO::PARAM_INT);
                            $stmt->bindValue(":user", $id, PDO::PARAM_STR);
                            $stmt->bindValue(":times", $times, PDO::PARAM_STR);
                            $stmt->bindValue(":tw_text", $value, PDO::PARAM_STR);
                            $stmt->execute();
                        }
                    }
                }
                $this->pdo = null;
                return true;
            } catch (\Throwable $th) {
                //throw $th;
                return false;
            }
        }
    }
    function tweets_load(string $id = "")
    {
        if (!$id) return false;
        try {
            //code...
            $value = null;
            if ($this->db_connection()) {
                $stmt = $this->pdo->prepare("select * from tweets where user = :user order by times,tw_id asc;");
                $stmt->bindValue(":user", $id, PDO::PARAM_STR);
                $res = $stmt->execute();
                $value = $res ? $stmt->fetchAll() : false;
                $this->pdo = null;
            }
            return $value;            
        } catch (\Throwable $th) {
            //throw $th;
            return false;
        }
    }
    function tweets_update(int $key = 0, int $timeonoff = 0, mixed $times = null, string $id = "",mixed $tw_text="")
    {
        try {
            //code...
            if(!preg_replace("/[ | ]{0,}/","",$tw_text))return false;
            if ($this->db_connection()) {
                $stmt = $this->pdo->prepare("update tweets set tw_text = :tw_text where tw_id = :tw_id and user = :user and times = :times");
                $stmt->bindValue(":tw_id", $key, PDO::PARAM_INT);
                $stmt->bindValue(":user", $id, PDO::PARAM_STR);
                $stmt->bindValue(":times", $times, PDO::PARAM_STR);
                $stmt->bindValue(":tw_text", $tw_text, PDO::PARAM_STR);
                $stmt->execute();
                $this->pdo = null;
            }
        } catch (\Throwable $th) {
            //throw $th;
            return false;
        }
        return true;

    }

    function tweets_delete(int $key = 0, int $timeonoff = 0, mixed $times = null, string $id = "")
    {
        try {
            //code...
            if ($this->db_connection()) {
                $stmt = $this->pdo->prepare("delete from tweets where tw_id = :tw_id and user = :user and times = :times");
                $stmt->bindValue(":tw_id", $key, PDO::PARAM_INT);
                $stmt->bindValue(":user", $id, PDO::PARAM_STR);
                $stmt->bindValue(":times", $times, PDO::PARAM_STR);
                $stmt->execute();
                $this->pdo = null;
            }
        } catch (\Throwable $th) {
            //throw $th;
            return false;
        }
        return true;
    }

    function bat_tweets(mixed $value = null)
    {
        if (!$value) return false;
        $obj = (object)[];
        $t = "";
        foreach ($value as $key => $val) {
            if ($this->timecheck(1, $val["times"])) {
                $obj = ($val["times"]<>$t)? ($this->connection->post("tweets", ["text" => $val["tw_text"]], true)
                ) : ($this->connection->post("tweets", ["reply" => ["in_reply_to_tweet_id" => $obj->data->id], "text" => $val["tw_text"]], true)
                );
                $this->tweets_delete($val["tw_id"], 1, $val["times"], $val["user"]);
                $t = $val["times"];
            } else {
              //  var_dump($val);
              //  break;
            }
        }
    }
}

if ($argv[0]) {
    $tw = new tw();
    $value = $tw->tweets_load(xss_d($argv[1]));
    $tw->bat_tweets($value);
}
function xss_d($val = false)
{
    if (is_array($val)) {
        foreach ($val as $key => $value) {
            $val[$key]  = strip_tags($value);
            $val[$key]  = htmlspecialchars($val[$key]);
        }
    } else {
        $val  = strip_tags($val);
        $val  = htmlspecialchars($val);
    }
    return $val;
}

追記:予約編集機能なども付けました🙄。

GithubとQiitaのリンクはこちらです。
Github:https://github.com/taoka-toshiaki/tweets-system-box1
Qiita:https://qiita.com/taoka-toshiaki/items/5ef12b60b267742bf584

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

2, , 39, Asia, Code, crontab, date, default, github, ini, lt, php, qiita, Se, set, Sqlite, timezone, Tokyo, TwitterAPI, UP, コード, これ, システム, スクロール, スケジュール, ソース, ツイート, ところ, バージョン, パラメーター, ファイル, 一部, , 予定, 予約, 事項, , 使用, 偏頭痛, , 先日, 変更等, 大変, 投稿, 掲載, 数珠繋ぎ, 更新, 機能, 機能等, 此処, 注意, 管理, 編集, 記事, 近日, 追加, ,

Photo by Pixabay on Pexels.com

Twitter-API-v2ツイート数珠繋ぎ #コード公開 #php

2022.10.04

Logging

おはようございます。土日祝も関係なくブログは毎日書いています🤮。

さて、今日はPHP言語でTwitterAPIバージョン2(v2)を使用してツイート数珠繋ぎをする方法を抜粋して記載していきます。こういうコードは今のところ出回っていないようです。少し調べれば公式サイトに記載しているのだけども・・・。まだ、日本語に対応した記事が少ないようです。v2でツイートする方法やリツイートする方法は何故かあるのだけどリプライ(Reply)[/statuses/update]する方法が記事としては記載していなかったので?記載します。

<?php
require_once "vendor/autoload.php";
use Abraham\TwitterOAuth\TwitterOAuth;

class tw{
    var $connection = null;
    function __construct()
    {
        $this->connection = new TwitterOAuth(APIKEY, APISECRET,ACCESSTOKEN, ACCESSTOKENSECRET);
        $this->connection->setApiVersion("2");
    }

    function pickup_tweets(mixed $tw_text=null){
         $obj = (object)[];
        if(isset($tw_text) && is_array($tw_text)){
            foreach ($tw_text as $key => $value) {
                if(preg_replace("/[ | ]/","",$value)){
                    $obj = !$key?(
                        $this->connection->post("tweets", ["text" =>$value], true)
                    ):
                    (
                        $this->connection->post("tweets", ["reply"=>["in_reply_to_tweet_id"=>$obj->data->id],"text"=> $value], true)
                    );
                }
            }
            return true;
        }
        return false;
    }
}

最初に結論とコードのアルゴリズムに付いて解説します。まず、tweetsのパラメーターでリプライ出来るように変更されています。v1.1とはそこが変わっているので同じ仕組みを検索しがちですがそれでは検索にヒットしないようです🤔。まずはエンドポイントの変更点の確認が必要みたい👏。

エンドポイントのv1.1からv2への対応表

エンドポイントのv1.1からv2への対応表が公式から出ているので確認してみてください↑。

次にコードの解説ですがまずTwitterOAuthライブラリをインストールを行い、defineなどの設定なども考慮した上で実行してみてください(コードに追記記載が必要)。変数、$tw_textは配列です。また投稿する文字が入っていると考えてください。そしてこのコードを下記のような考え方で実行してみてください。

<?php
       require_once "tw-index.php";
       $tw_text[0] ="test1";
       $tw_text[1] ="test2";
       $tw = new tw();
       if($tw->pickup_tweets($tw_text)){
        $ret["msg"] = "ok";
       }else{
        $ret["msg"] = "NG";
       }
       var_dump($ret);

※前提条件としてtwitter社にAPIの申請を行って受理されている事。

Twitter API v2 ツイート数珠繋ぎ

これで思った通り実行出来たと思います。尚、自分のように管理画面などを作って数珠繋ぎの投稿するのも良いかも知れません🫠。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

2, Abraham, autoload, class, connection, function, lt, null, once, php, quot, Reply, require, statuses, tw, Twitter-API-v, TwitterAPI, TwitterOAuth, UPDATE, use, var, vendor, コード, サイト, ツイート, ところ, バージョン, ブログ, リツイート, リプライ, , 今日, 使用, 公式, 公開, 土日, 対応, 少し, 抜粋, 数珠繋ぎ, 方法, 日本語, 毎日, , 言語, 記事, 記載,

Photo by Markus Winkler on Pexels.com

WPのapply_filtersとadd_filterの説明が難解に書いているサイトが多い事に🤬。 #php #wordpress

2022.09.28

Logging

おはようございます、今月もそろそろ終わります🤔。

さて、来月から毎月一回しか投稿しなかったブログサイトを不定期更新に変更します。指針の変更にあたってブログデザインもデフォルトのテンプレートから無料のcocoonというテンプレートに変えました。

今までYOUTUBE動画URLを記載しているだけの投稿だったので、アイキャッチー画像等は無い状態でした。その為、テンプレートを変えるとノーイメージという画像が表示されるという事象が発生。これをプラグイン側で解決したかったのですが、独自の関数を多く使用しておりプラグイン側だけでは無理だということで、独自のアイキャッチー画像を処理しているコアの部分にapply_filtersを差し込み、プラグイン側でadd_filterで処理するという流れの対応を行いました。

apply_filtersというのはテンプレート側(他のプラグインでも可能)の関数の中に目印(付箋)を付けることが出来る機能(関数)です。
add_filterは目印(付箋)の部分の処理が走った時に、自分が作った処理を割り込ませることが出来る機能(関数)です。

※まずはカッコの中は読まずに理解してください😌。

巷では、これをややこしい例えで解説している所が多いのですが、それだけの話しです。今回、image-funcs.phpファイル(cocoon)の関数get_original_image_tagにapply_filtersを挿入し独自プラグインから呼び出して、ノーイメージの時にYOUTUBEのサムネイル画像を表示させるという事を行っていました。前、次ページのサムネイル画像は現在のページのサムネ画像が表示されるというバグはあるものの、ちゃんと跡のサムネ画像は変わっています。

サンプルコードを掲載します。ご参考程度に😌。

<?php
//オリジナルサムネイルタグの取得
if (!function_exists('get_original_image_tag')) :
  function get_original_image_tag($image_url, $width, $height, $class, $alt = null)
  {
    $html = '<img src="' . esc_url($image_url) . '" alt="' . esc_attr($alt) . '" class="' . esc_attr($class) . '" width="' . esc_attr($width) . '" height="' . esc_attr($height) . '" />';
    $html = convert_all_lazy_load_tag($html);
    $html = apply_filters("youtubeimage",$html);
    return $html;
  }
endif;
<?php
/*
Plugin Name: youtube image
Description: youtube image chg
Version: 1.0
*/
if (!defined('ABSPATH')) exit;
function youtubeimage_chg($imgurl){
    $url = null;
    if(preg_match("/(https:\/\/www\.youtube\.com\/watch\?v=[\-|_|a-zA-Z|0-9]{1,})/",get_the_content(),$matches)){
        $url = "https://img.youtube.com/vi/".preg_replace("/(https:\/\/www\.youtube\.com\/watch\?v=)/","",$matches[0])."/hqdefault.jpg.webp";
        $url = preg_replace("/(src=\"https:\/\/.*no\-image\-[0-9]{2,3}\.png.webp\")/","src=\"".$url."\"",$imgurl);
     }
     return $url?$url:$imgurl;
}

add_filter("youtubeimage","youtubeimage_chg");

余談:この対応はテンプレートが更新(アップデート)際にファイルが上書きされる可能性があります。その際にページが見えなくなるという問題を秘めています🙇。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

Add, apply, cocoon, filter, filters, php, url, WordPress, wp, youtube, あい, イメージ, キャッチー, コア, こと, これ, サイト, デザイン, デフォルト, テンプレート, ノー, プラグイン, ブログ, , 不定期, , 事象, 今月, 使用, 処理, 動画, 変更, 多く, 対応, 投稿, 指針, 更新, 来月, 毎月, , 無料, 状態, 画像, 発生, 表示, 解決, 記載, 説明, 部分, 関数, 難解,

Photo by Vlada Karpovich on Pexels.com

検索されなかったワード埋もれた価値について! #javascript #php

2022.09.26

Logging

おはようございます、今日は引き落とし日です🫠。

さて、今日は検索されなかったキーワードの価値のお話です。此処で言う検索されなかったというのは、エンターキーや検索ボタンを押さなかった、キーワードの価値のお話です、たぶん、その情報をGさんは収集してそうな気がします。GサイトやYサイト等のキーワード収集は基本出来ませんが、自サイトの検索フォームの情報を収集出来ます。

此処からは技術的なお話になりますが、検索ボタンを押した時とは別に文字入力をしたときの挙動を感知するプログラムを導入する事により比較的簡単に導入できるかと思います。例えば下記のようなjavascriptコードを検索フォームに導入します。

document.getElementById("sh").addEventListener("input",(e)=>{
    $.ajax({
        type: "post",
        url: "example.com/sh.php",
        data: {text:this.value},
        dataType: "json",
        success: function (response) {
            
        }
    });
});

あとはPHP側でデータを受信しデータベース等に保存すれば良いだけです。この検索されなかったワードは、結構価値があると思います。より細かな情報を取得したい方はIPアドレスどのページからの情報なのかも取得可能です。

これらのデータを元に販路開拓は十分出来ると思います。情報を保存する際に大量の情報が収集されるので、保存先に一工夫必要になります。JSで制御する手段もありますが、それだとあまり情報収集出来ないですからね。

因みにこのサイトに情報収集の処理は導入していません(今後の導入は未定)。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

addEventListener, ajax, document, getElementById, gt, input, javascript, php, quot, sh, エン, お話, キーワード, コード, サイト, ターキー, とき, フォーム, プログラム, ボタン, ワード, 下記, , 今日, 価値, 入力, 収集, 基本, 導入, 情報, 感知, 挙動, 文字, , , 検索, 此処, , 簡単, ,

Photo by NEOSiAM 2021 on Pexels.com

Sqliteで作った簡易掲示板のコードを配布致します。#php #code

2022.09.20

Logging

おはようございます。台風は過ぎ去りましたがせっかくの三連休が残念です💦。

今日は先日、Sqliteを使用して簡易掲示板を作ってみましたのでコードを配布致します、尚、PHP8の環境下で動作させています(PHP7系でも動作すると思います)。

Sqliteってnow()関数がなかったりだとか、Deleteする時に、noカラムを昇順しlimitを使用して削除出来ないだとか、いろいろとMysqlとは違う所があり、面倒だなと思いながらコードを書きました、尚、SqliteはWebサーバーの階層に置かないように、置いても良いですが・・・。そのままの状態だと誰でもダウンロードが可能になってしまいますのでご注意ください。自分は地下に眠らしています😅。

一応、二重投稿防止の為に20秒経過しないと再投稿出来ないようにしています😌。トライしていない事は禁止ワード等がありません🤔。つけようと思ったのですがまぁ良いかなと、、、。

動作している環境のリンクはこちら。

https://reborn9.sakura.ne.jp/

軸となるPHPのソースコードを2つ貼っときますね。

<?php
session_start();
$toke_byte = openssl_random_pseudo_bytes(16);
$csrf_token = bin2hex($toke_byte);
$_SESSION['csrf_token'] = $csrf_token;
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="Description" content="Enter your description here" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <link rel="stylesheet" href="assets/css/style.css?<?= time() ?>">
    <title>掲示板</title>
</head>

<body class="p-3 text-white">
    <div class="p-4 shadow rounded" style="background-color:#d6dbdf;">
        <div class="container mt-5">
            <div class="row">
            <div class="col-12 text-center">
                <h1 class="shadow" style="color:#195a57;">掲示板::version 2.5</h1>
            </div>
                <div class="col-12">
                    <div class="input-group shadow rounded">
                        <div class="input-group-append">
                            <span class="input-group-text bg-dark text-white" id="my-addon">ニックネーム</span>
                        </div>
                        <input class="form-control" type="text" name="name" placeholder="ニックネームを入力" aria-describedby="my-addon">
                    </div>
                    <div class="form-group shadow rounded">
                        <label for="my-textarea">コメント</label>
                        <textarea id="my-textarea" class="form-control" name="comment" rows="7"></textarea>
                    </div>
                    <button id="btn" class="mt-2 btn btn-info text-white shadow rounded" type="button">投稿する</button>
                </div>
            </div>
        </div>
        <div class="container mt-5">
            <div class="row">
                <div id="view" class="col-12"></div>
            </div>
        </div>
    </div>
    <footer>
        <a href="/">TOP</a> :: © Reborn9.sakura.ne.jp <?=date("Y")?>
    </footer>
    <input type="hidden" name="csrf_token" value="<?= $csrf_token ?>">
    <script src="https://code.jquery.com/jquery-3.2.1.min.js" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.2/umd/popper.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/js/bootstrap.min.js"></script>
    <script src="assets/js/main.js?<?= time() ?>"></script>
</body>

</html>
<?php
class db
{
    var $pdo = null;
    function __construct()
    {
        try {
            $this->pdo = new PDO("sqlite:../../bbs.sqlite3");
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);        //code...
        } catch (\Throwable $th) {
            //throw $th;
            print $th->getMessage();
        }
    }
    function select_limit()
    {
        if($this->pdo){
            $stmt = $this->pdo->prepare('select * from bbs order by no desc limit 0,5');
            $stmt->execute();
            $result = $stmt->fetchAll();
            $stmt = null;
            $this->pdo = null;
            return new view($result);
        }
    }
    function insert($name,$comment,$sns_cnt=0)
    {

        try {
            $stmt = $this->pdo->prepare('INSERT INTO bbs (`time`,`name`,`comment`,sns_cnt)values(strftime(\'%Y年%m月%d日 %H時%M分%S秒\',CURRENT_TIMESTAMP, \'localtime\'),:name,:comment,:sns_cnt)');
            $stmt->bindParam(':name', $name, PDO::PARAM_STR);
            $stmt->bindParam(':comment', $comment, PDO::PARAM_STR);
            $stmt->bindParam(':sns_cnt', $sns_cnt, PDO::PARAM_INT);
            $stmt->execute();
            $stmt = $this->pdo->prepare('DELETE FROM bbs WHERE bbs.no = (SELECT no from bbs ORDER BY no ASC LIMIT 1);');
            $stmt->execute();
            $stmt = null;
            $this->pdo = null;
            return true;
        } catch (\Throwable $th) {
            print $th->getMessage();
            return false;
        }
    }
}

class view{
    var $item = null;
    function __construct($item)
    {
        $this->item = $item;        
    }
    function view_item($item="")
    {
        try {
            $item = $item?$item:$this->item;
            ob_start();
            ?>
            
            <?php
            foreach($item as $key=>$value){
                ?>
                <div class="mt-2 row txtbox shadow rounded">
                <div class="col-3 name_<?=$value["no"]?> rounded-start fs-6">
                    ニックネーム::<?=$value["name"]?>さん
                </div>
                <div class="col-9 time_<?=$value["no"]?> fs-6">
                    投稿日時::<?=$value["time"]?>
                </div>
                <div class="col-12 comment_<?=$value["no"]?>">
                    <?= nl2br($value["comment"])?>
                </div>
                <div class="col-12 sns_cnt_<?=$value["no"]?>">
                    <!-- <?=$value["sns_cnt"]?> -->
                </div>
                </div>
                <?php
            }        
            ?>
                
            <?php
            $ret["view"]= ob_get_clean();
            $ret["msg"]= "done";
    
        } catch (\Throwable $th) {
            //throw $th;
            $ret["msg"] = "error";
        }
        return $ret;
    }
}

session_start();
$ret = null;
$mode =  xss_defence($_POST["mode"]);
// $time =  ;
$name =  xss_defence($_POST["name"]);
$comment =  xss_defence($_POST["comment"]);
$sns_cnt =  (int)xss_defence($_POST["sns_cnt"]);
if (isset($_POST["csrf_token"]) 
 && $_POST["csrf_token"] === $_SESSION['csrf_token'] && (function($t){
    return time() - $t > 20?true:false;
 })($_SESSION["save"])) {
    if($mode==="save"){
        $name = !preg_replace("/[ | ]/","",$name)?"匿名":$name;
        $comment = !preg_replace("/[ | ]/","",$comment)?"":$comment;
        if($comment){
            $db = new db();
            $db->insert($name,$comment);
            $_SESSION["save"] = time();
        }
    }
    $db = null;
    $db = new db();
    $ret = $db->select_limit()->view_item();
    print  json_encode($ret);
}
function xss_defence($value){
    if(is_array($value)){
        foreach($value as $key=>$val){
            $value["$key"] = strip_tags($val);
            $value["$key"] = htmlspecialchars($value["$key"],ENT_QUOTES);
        }

    }else{
        $value = strip_tags($value);
        $value = htmlspecialchars($value);
    }
    return $value;
}

配布コードはこちらです。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

20, 7, 8, Code, Delete, LIMIT, MYSQL, no, Now, php, Sqlite, web, いろいろ, カラム, コード, ご注意, サーバー, せっかく, そのまま, ダウンロード, トライ, ワード, 三連, , , 今日, , 使用, 先日, 削除, 動作, 可能, 台風, 地下, , 投稿, 掲示, 昇順, , 残念, , 状態, 環境, 禁止, 簡易, 経過, 自分, , , 配布, 関数, 防止, 階層, 面倒,

一週間の予約が出来るデモコードです。良かったらどうぞ😌。 #php #code

2022.09.17

Logging

おはようございます、今日から台風接近らしいですね。この投稿は昨日書きました。

さて、一週間の予約(時刻表から)が出来るデモコードを書きました。これを書いたキッカケは昔の職場の方がこんな感じのUIを作られていたのを見て、自分も書いてみようと思いDEMOコードを朝起きて調べながら書きました。調べたことは選択を解除する方法だけで、後はオリジナルコードです、設計書も何もなく組み立ていきましたので、欠陥があるかもです。また、Qiitaにも記載しましたが、コメントをほぼ書いていません。書かずともプログラマーなら分かるだろうという感覚です。

予約ー時刻表DEMO

肝心の確認部分は記載していないのにも訳があります。営業妨害になっては駄目だからです。そういう理由で確認部分以降は書いていません。

こちらにもソースコードを掲載しときますね。

<?php
ini_set("display_errors",0);
/**
 * @param array $holiday
 * @return string $str
 */
function fn_header($holiday = [])
{
    $str = "";
    $date = new DateTime();
    for ($i = 0; $i < 7; $i++) {
        !$i ? "" : $date->modify('+1 day');
        $w = $date->format("w");
        $tabindex = $i*7;
        $ho = (function ($days, $holiday = []) {
            return (array_search($days, $holiday) !== false) ? "holiday" : "";
        })($date->format("Y-m-d"), $holiday);
        $str .= "
        <th tabindex=$tabindex>
            <span class='header_no week_no_$w $ho'>" . $date->format("Y-m-d") . "</span>
        </th>";
    }
    return $str;
}
/**
 * @param int $h_min
 * @param int $h_max
 * @param int $m_interval
 * @param array $cnt
 * @param array $reserve
 * @param array $holiday
 * @return string $str
 */
function fn_time($h_min, $h_max, $m_interval,$cnt=[],$holiday = [], $reserve = [])
{
    $str= [];
    for ($h = $h_min; $h <= $h_max; $h++) {
        for ($m = 0; $m < 60; $m = $m + $m_interval) {
            print("<tr>\n");
            $date = new DateTime();
            for ($i = 0; $i < 7; $i++) {
                $cnt[$i]=!$cnt[$i]?(((($h_max - $h_min)+1)*(60/$m_interval))*($i))+7:(++$cnt[$i]);
                !$i ? "" : $date->modify('+1 day');
                $w = $date->format("w");
                $ho = (function ($days, $holiday = []) {
                    return (array_search($days, $holiday) !== false) ? "holiday" : "";
                })($date->format("Y-m-d"), $holiday);
                $time = sprintf("%02d:%02d",$h, $m);
                if ($ho) {
                    print("
                        <td class='' tabindex={$cnt[$i]}>
                            <span class='header_no week_no_$w $ho'>" . $time . "</span>
                        </td>");
                } else {
                    $r = (function ($days, $reserve = []) {
                        return (array_search($days, $reserve) !== false) ? "reserve" : "";
                    })($date->format("Y-m-d") . "_" . $time, $reserve);
                    if (!$r) {
                        print("
                            <td class='date_" . $date->format("Y-m-d") . "_{$time}' tabindex={$cnt[$i]} data-date='" . $date->format("Y-m-d") . "_{$time}'>
                                <a class='time_{$m}_" . $date->format("Y-m-d") . "_{$time}' data-sortno={$cnt[$i]}  href='#?data=" . $date->format("Y-m-d") . "_{$time}'><span class='header_no week_no_{$w} {$h}'>{$time}</span></a>
                            </td>");
                    } else {
                        print("
                            <td class='' tabindex={$cnt[$i]}>
                                <span class='header_no week_no_$w $r'>" . $time . "</span>
                            </td>");
                    }
                }
            }
            $date = null;
            print("</tr>\n");
        }
    }
    return "";
}
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="Description" content="Enter your description here" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
    <title>予約-時刻表(デモ版)</title>
    <style>
        table,tr,td{
            user-select: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12 text-center">
                <h1 class="display-1">予約-時刻表<br></h1>
                <h5>{予約:時刻をクリックするか、<br>
                    左クリック選択状態で複数選択可能です<br>
                    (日付またぎは禁止しています)}</h5>
                <h5>{ダブルクリックすると予約画面に遷移します。<br>
                    ※DEMO版ですので予約登録画面は御座いません}</h5>
            </div>
        </div>
    </div>
    <div class="container-fluid  text-center">
        <div class="row">
            <div class="col-12">
                <table class="shadow-lg table table-hover table-bordered">
                    <thead>
                        <tr>
                            <?= fn_header() ?>
                        </tr>
                    </thead>
                    <tbody>
                        <?=fn_time(10, 20, 10,[],["2022-09-18","2022-09-23"],["2022-09-19_10:40","2022-09-19_10:50"]) ?>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.2/umd/popper.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.0/js/bootstrap.min.js"></script>
    <script src="./assets/js/main.js?<?=time()?>"></script>
</body>
</html>
let date_obj = document.querySelectorAll("td");
let submit_url = "https://example.com";
let is_date_data = [];
let cnt = 0;

date_obj.forEach(function (elm, key) {
    elm.addEventListener("mouseout", select_in_value);
    elm.addEventListener("click", sp_select_in_value);
    elm.addEventListener("touchend", sp_select_in_value);
    elm.addEventListener("dblclick", select_out_value);
});
function check_value(o, e) {
    if (is_date_data.length === 0) {
        return true;
    }
    let d = o.getAttribute("data-date");
    return d ? ((d) => {
        let f = is_date_data.find(element => {
            let pattern = new RegExp(d.split("_")[0]);
            return !element.match(pattern);
        }) ? false : true;
        if (!f) {
            select_clear(o, e);
            is_date_data = [];
            cnt = 0;
        }
        return f;
    })(d) : false;
}
function select_in_value(e) {
    if (e.buttons === 1 && check_value(this, e)) {
        if (this.getAttribute("data-date")) {
            this.style.backgroundColor = "#555";
            this.children[0].style.color = "#fff";
            if (is_date_data.indexOf(this.getAttribute("data-date")) && is_date_data.indexOf(this.getAttribute("data-date"))) {
                is_date_data[cnt] = this.getAttribute("data-date");
                cnt++;
            }
        }
    }
}
function sp_select_in_value(e) {
    if (check_value(this, e)) {
        if (this.getAttribute("data-date")) {
            this.style.backgroundColor = "#555";
            this.children[0].style.color = "#fff";
            if (is_date_data.indexOf(this.getAttribute("data-date")) && is_date_data.indexOf(this.getAttribute("data-date"))) {
                is_date_data[cnt] = this.getAttribute("data-date");
                cnt++;
            }
        }
    }
}
function select_out_value(e) {
    if (is_date_data.length) {
        let is_data = is_date_data.map(function (elm, index) {
            return "date[" + index + "]=" + elm;
        });
        window.location.href = submit_url + "?" + is_data.join("&");
    }
}
function select_clear(o, e) {
    let is_ClassName = [];
    is_ClassName = is_date_data.map(function (d) {
        return "date_" + d;
    });
    is_ClassName.map(class_name => {
        document.getElementsByClassName(class_name)[0].style.backgroundColor = "#fff";
        document.getElementsByClassName(class_name)[0].children[0].style.color = "#0d6efd";
    })
}

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

0, Code, com, demo, https, ligaLgY-uZ, php, qiita, UI, watch, www, youtube, オリジナル, キッカケ, コード, こちら, こと, コメント, これ, ソース, デモ, プログラマー, , 予約, 今日, 台風, 営業, 妨害, , 感じ, 感覚, 投稿, 接近, 掲載, , 方法, , 昨日, 時刻表, , 欠陥, 理由, 確認, 職場, 肝心, 自分, 解除, 記載, 設計書, , 選択, 部分, 駄目,

Photo by Stas Knop on Pexels.com

若気の至り若気の過ちか?Mr.ROBOT🤖

2022.09.11

Logging

こんばんは、深夜便で東京に向かってます(嘘です)。

今日は緊急で動画廻してます(記事を書いています)。私が昔書いたコードに大きな脆弱性が合ったので、そのコードの穴だけ塞ぎました。まだ、色々な所に穴があるかもしれないですが・・・。

この脆弱性に関しては知っていたのですが、昔のコードをそのままにしていたのを失念していたのです、それが大きな過ち…。仕事では重大インシデントになりますね😱。

<?php
 function defence_xss($data=""){
    if(is_array($data)){
        foreach ($data as $key => $value) {
            $data[$key] = strip_tags($value);
            $data[$key] = htmlspecialchars($data[$key],ENT_QUOTES);
        }
    }else{
        $data = strip_tags($data);
        $data = htmlspecialchars($data,ENT_QUOTES);
    }
    return $data;
}

今回、塞いだのは初歩の脆弱性です、、、POSTやGETで送られるデータに悪意のあるコードなどを埋め込んでハッキングを行う手法です。またセッションジャックとかそういうのもありますので、気になる方は調べてみてください。

SQLインジェクション判決、オニギリペイ、これらをつなぐセミナーにかける思いを語る
徳丸浩のウェブセキュリティ講座

追記して書いときます。昔勤めていた会社でも何度か、この手の手法でハッキングに合いました。脆弱性が解消されているかは分かりません。XSS攻撃は防げても、これではSQLインジェクション攻撃は防げません、昔のコードで動いているとしたら修正箇所は無数にあるので一日では直せないでしょう。

昔勤めていた会社はShopifyへシステムを移行しているようですが、それが良いのかは分かりません、自分だったら物足りなさを感じると思います😌。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

array, as, data, defence, foreach, function, gt, htmlspecialchars, if, is, key, lt, Mr, php, quot, ROBOT, strip, tags, value, xss, インシデント, コード, それ, 今日, 仕事, 動画, , 失念, , , 東京, 深夜便, , , 緊急, 脆弱性, 色々, 若気, 記事,

1万件のCSVを読み込みテーブルに保存する雛形コード #PHPCode

2022.09.08

Logging

おはようございます、徐々に秋ぽっい日差しになってきましたね(まだ暑いけども😌)。

今日は、1万件のCSVを読み込みテーブルに保存する雛形コードを昨日、ちょちょっと書きましたので記載します。ファイルをダウンロードして使いたい方はGithubのリンクを下に貼っときますので、ご使用頂けたらと思います。尚、テーブルなどはCSVを参考にご自身で構えてください。

※動作環境はPHP8系です、なのでPHP7系では一部エラーが出ます。fgetcsv…nullを0へ変更。

Githubのリンクはこちら

Qiitaの方に記載しようかどうしようか、迷ったのですが第一弾目がアクセス数がそこそこ伸びたのでこれ以上、注目されるのは嫌なのでブログの方に記載しました。1万件のCSVを簡単に読み込ませる方法はPHPコードを書くのではなく、SQLのコマンドで実行した方が実は早いですけど・・・。

https://twitter.com/taoka_toshiaki/status/1567489169919975424
有言実行

早いですけど、その場合、CSVがちゃんとしたファイルではないと上手くテーブルに保存されない場合や、そもそもコマンドラインで操作出来ない場合もあったりしてPHPコードなどで制御しないと駄目な事もあります。そんな時に、このコードをサンプルとして使って頂ければ良いなと思い作りました。

1万件のCSVを読み込ませるPHPコード雛形。

そんなにコードを書かなくてもまぁ動くんですよ。ちなみにソースコードには、あまりコメントを書いていないですが、プログラマーなら大体の人が理解できるレベルかと思います。

<?php
//ini_set("display_errors","On");
session_start();
require "db_config.php";

//読み込みCSVファイル名セット
class csv
{
    /**
     * @param string $filename
     * @param int $cnt
     * @return Object
     */
    public function ini_csv($filename = "", $cnt = 0)
    {
        return new csv_read($filename, $cnt);
    }
}

//CSVデータを読み込ます
class csv_read
{
    var $max = 10000;
    var $cnt = 0;
    var $handle = null;
    /**
     * @param string $filename
     * @param int $cnt
     */
    public function __construct($filename = "", $cnt = 0)
    {
        $this->cnt = $cnt;
        $this->handle =  fopen($filename, "r");
        $_SESSION["offset"] ? fseek($this->handle, $_SESSION["offset"]) : $this->handle;
    }
    /**
     * @param int $header_skip
     * @return Object
     */
    public function reader($header_skip = 0)
    {
        if ($this->handle !== FALSE) {
            $response = null;
            $data = fgetcsv($this->handle, null, ",");
            if (!$header_skip || $_SESSION["offset"]) {
                if ($data !== FALSE) {
                    $_SESSION["offset"] = ftell($this->handle);
                    $response["data"] = $data;
                    $response["cnt"] = $this->cnt > $this->max ? 0 : ($this->cnt + 1);
                    $flag = true;
                } else {
                    $_SESSION["offset"] = null;
                    $flag = false;
                }
            } else {
                $_SESSION["offset"] = ftell($this->handle);
                $response["cnt"] = $this->cnt > $this->max ? 0 : ($this->cnt + 1);
                $flag = false;
            }
        } else {
            $_SESSION["offset"] = null;
            $flag = false;
        }
        return new table_save($flag, $response);
    }
}

//tableにCSVデータを保存
class table_save
{
    var $flag = false;
    var $result = null;
    /**
     * @param boolean $flag
     * @param array  $response
     * @return void
     */
    public function __construct($flag, $response)
    {
        $this->flag = $flag;
        $this->result = $response;
        $this->column_name = "name,,...";
    }
    /**
     * @param string  $column_name
     * @return void
     */
    public function tbl_save($column_name = "")
    {
        if ($this->flag) {
            $column = $column_name ? $column_name : $this->column_name;
            $is_column = explode(",", $column);
            foreach ($is_column as $key => $val) {
                $is_value[$val] = $this->result["data"][$key];
            }
            try {
                $pdo = new PDO(DSN, USERNAME, PASSWORD);
                $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $sql = (function ($is_column) {
                    $INSERTFIRST = null;
                    $INSERTLAST = null;
                    foreach ($is_column as $key => $val) {
                        $INSERTFIRST[] = "$val";
                        $INSERTLAST[] = ":$val";
                    }
                    $INSERTSQL = "(" . implode(",", $INSERTFIRST) . ")values(" . implode(",", $INSERTLAST) . ")";
                    $UPDATESQL = null;
                    foreach ($is_column as $key => $val) {
                        $UPDATESQL[] = "$val = :$val";
                    }
                    return "INSERT INTO " . TABLENAME . $INSERTSQL . " ON DUPLICATE KEY UPDATE " . implode(",", $UPDATESQL) . ";";
                })($is_column);

                $stmt = $pdo->prepare($sql);
                foreach ($is_value as $key => &$value) {
                    $is_type = ($key === "test3" || $key === "test13") ? PDO::PARAM_INT : PDO::PARAM_STR;
                    $stmt->bindValue(":$key", $value, $is_type);
                }
                $this->result["sql"] = $stmt->execute();
            } catch (\Throwable $th) {
                //throw $th;
                $this->result = null;
                print $th->getMessage();
            }
        }
        print json_encode($this->result);
    }
}

//RUN...POST DATA
if (isset($_POST["csrf_token"])  && d_xss($_POST["csrf_token"]) === $_SESSION['csrf_token']) {

    $_SESSION["offset"] = (int)d_xss($_POST["reset_flag"]) === 1 ? null : d_xss($_SESSION["offset"]);
    $filename = d_xss($_POST["filename"]);
    $cnt = (int)d_xss($_POST["cnt"]);

    $column_name = "test1,test2,test3,test4,test5,test6,test7,test8,test9,test10,test11,test12,test13,test14,test15";
    $header_skip = 1;

    $csv = new csv();
    $csv->ini_csv($filename, $cnt)->reader($header_skip)->tbl_save($column_name);
    $csv = null;
} else {
    print "";
}
function d_xss($data){
    $data = strip_tags($data);
    $data = htmlspecialchars($data,ENT_QUOTES);
    return $data;
}
<?php
 // ログインした状態と同等にするためセッションを開始します
 session_start();
 // 暗号学的的に安全なランダムなバイナリを生成し、それを16進数に変換することでASCII文字列に変換します
  $toke_byte = openssl_random_pseudo_bytes(16);
  $csrf_token = bin2hex($toke_byte);
  // 生成したトークンをセッションに保存します
  $_SESSION['csrf_token'] = $csrf_token;
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="Description" content="Enter your description here"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<title>CSV</title>
</head>
<body>
    <input type="hidden" name="csrf_token" value="<?=$csrf_token?>">
    <span class="h3" id="cnt"></span><br><br>
    <span class="h4" id="read_csv"></span><br><br>
    <span class="h4" id="debug"></span><br><br>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.1/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script>
<script>
    window.onload = function(){
        read_csv(0,1);
    };
    function read_csv(cnt,reset_flag){
        try{
            $.ajax({
            type: "post",
            url: "./assets/php/class_csv.php",
            async: false,
            data: {csrf_token:document.getElementsByName("csrf_token")[0].value,reset_flag:reset_flag,filename:"dummy.csv",cnt:cnt},
            dataType: "json",
            success: function (response) {
                    if(response){
                        cnt = response.cnt;
                        document.getElementById("cnt").innerText = cnt;
                        if(response.data){
                            document.getElementById("read_csv").innerText = response.data[0] + response.sql;
                            document.getElementById("debug").innerText = cnt ===21?response.data:document.getElementById("debug").innerText;
                        }
                        setTimeout(function(){read_csv(cnt)},0);
                    }
                }
            });
        }catch(e){
            console.warn(e);
            read_csv(cnt);
        }
    }
</script>
</body>
</html>

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

0, , 7, 8, CSV, fgetcsv, github, null, php, PHPCODE, qiita, SQL, アクセス, エラー, コード, こちら, コマンド, これ, ご使用, ご自身, ダウンロード, ちょ, テーブル, ファイル, ブログ, リンク, , 一部, , , 今日, 保存, 動作, 参考, 変更, 実行, , 方法, 日差し, 昨日, 有言実行, 注目, 環境, , 簡単, 記載, 雛形,

Excel(API)の関数WEBSERVICEの作り方と考え方。

2022.09.01

Logging

おはようございます。昨日の雷はかなりヒヤヒヤドキドキものでした😭(パソコンが壊れるのではないかと)。

さて、本日は巷で流行っているExcel(API)の関数WEBSERVICEの作り方と考え方です。考え方はURLにパラメーター付きの値を渡して返却した値を受け取るという考え方です。多分、このサイトを訪れた方は返却処理を自作したいと考えている方だと思います。

返却処理を自作したい場合はローカルサーバーもしくは、レンタルサーバーが必要になります。

Excel API WEBSERVICE(URL)の作り方(サンプル)

また、WEBサーバーでphpやPythonなどの言語が動作する環境が必要になります。尚、レンタルサーバーの場合、最安値のサーバーでもPHPは動作します。例えばさくらレンタルサーバーライト版でも動作します。そういう環境下でPHP言語やPython言語を動作出来るスキルがまず前提条件で必要です。

それが出来る方は下記のサンプルコードの意味が理解出来ると思います、APIと言っても簡単です。受け取ったパラメーター(GET値)を内部で処理しているだけです。クロスドメインエラーを回避する記述を先頭行に書き、その後はGET値からご自身が処理したいコードを記載し最後に結果をprintで出力しているだけです。

<?php
//すべてのドメインからのリクエストを許可
header("Access-Control-Allow-Origin: *");
$first =  strip_tags($_GET["first"]) ? strip_tags($_GET["first"]) : "";
$last = strip_tags($_GET["last"]) ? strip_tags($_GET["last"]) : "";
$word = $first . strip_tags($_GET["word"]) . $last;

print $word;

社内にシステムエンジニア(SE)部門がある方は、処理してほしい内容を依頼してみてはどうでしょうか。恐らく承諾してくれると思います。出来ないSEはいないと思います…🤔。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

$last, Excel, FIRST, lt, php, print, Python, quot, quot;Access-Control-Allow-Origin, quot;first&quot, quot;last&quot, quot;word&quot, strip_tags, Word, クロスドメインエラー, パラメーター, レンタルサーバー, ローカルサーバー, 許可 header, 関数WEBSERVICE,

Photo by Andree Brennan on Pexels.com

WPでWeb サーバーにアクセスする必要がありますの対処編:インフラ周り。

2022.07.03

Logging

おはようございます。WP(ワードプレス)でテーマや更新の際にFTPやSFTPのパスワードを求められたときの対処を記載します。この問題はApacheサーバーでもエンジンエックス(Nginx)でも対応は同じです。巷ではApacheグループに任意のユーザー名を付与しなさいという記載がありますが、其れだけでは駄目な場合があるのです。

gpasswd -a [ユーザー名] [グループに追加したいユーザー名]
gpasswd -a hoge apache

なので、phpのphp-fpm.dのディレクトリ配下にあるwww.confファイルの記載(user名とグループ名)を変更してあげる必要があります。変更後、php-fpmとhttpdを再起動してあげてください。

sudo vi /etc/php-fpm.d/www.conf
sudo systemctl restart php-fpm
sudo systemctl restart httpd

そうすれば、「Web サーバーにアクセスする必要があります」というような文言は非表示なり問題なく動作すると思います。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

A`, Apache, conf, etc, FTP, gpasswd, hoge, httpd, nginx, php, php-fpm, restart, SFTP, sudo, System, systemctl, user, vI, web, wp, www, アクセス, インフラ, エックス, エンジン, グループ, サーバー, テーマ, ディレクトリ, とき, パスワード, ファイル, プレス, ユーザー, ワード, 付与, 任意, 其れだけ, 再起動, , 周り, 問題, 場合, 変更, 対処, 対応, , 必要, 更新, 記載, 追加, 配下, , 駄目,

Photo by Глеб Коровко on Pexels.com

E_ERROR | E_WARNING | E_PARSE🐸

2022.06.15

Logging

おはようございます。果報は寝て待て😌。果報(かほう)を家宝だと思い込んでいました・・思い込みって怖いですね。

先日、記載した「更新に失敗しました。 返答が正しい JSON レスポンスではありません。」ですがphp.iniのワーニング(警告表示)が問題でした。そこをE_ERROR | E_WARNING | E_PARSEに修正してあげることで難無く解決済みです。JSONの返却の際に警告表示も返却され正しい値が取得出来ていなかったことに問題があったようです。

因みにこの頃は警告表示も意識してコードを書く機会が多くなりました。その理由はそちらの方がスマートかなって思うからです。数式が美しいと思うように綺麗なコードというものはあります。まだまだ、プログラムのコードは美しく書けませんが意識することによりそれに近づける事は大事になると思っています。

尚、php.iniは大体、/etc/php.iniにあります?、無ければコマンドラインからかコードに下記のように記載してphp.iniは何処に保存しているか調べてみてください。

php -r "echo phpinfo();" | grep "php.ini"
<?php
echo phpinfo();

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

Error, etc, ini, json, parse, php, WARNING, かほう, コード, こと, スマート, そこ, そちら, それ, プログラム, もの, レスポンス, ワーニング, , 修正, , 先日, 取得, 問題, 大事, 大体, 失敗, 家宝, 意識, 数式, , 更新, 果報, 機会, 理由, 綺麗, 表示, 解決済み, 記載, 警告, 返却, 返答, , ,

Photo by Kevin Ku on Pexels.com

サーバーを移行しました、行き着く先はここだった。

2022.06.14

Logging

おはようございます。先日、一日もかけてサーバーサイドを某サーバーに移行しました。移行しましたがまだ不具合などが存在しているのです。例えば「更新に失敗しました。 返答が正しい JSON レスポンスではありません。」などと頻度に表示されます。

ここらへんを早急に対応したいと思っています。

お待ち下さい~。

因みにPHPのバージョンは8にアップデートしました。そしてエンジンエックスからApacheに土台を変えました。今回、エンジンエックスを数ヶ月使用してApacheサーバの方がやはり歴史が長いので、かゆいところに手が届く仕様になっていることに気づきました。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

8, Apache, json, php, アップデート, エックス, エンジン, ここ, ここら, こと, サーバ, サーバー, ところ, バージョン, べん, レスポンス, , 不具合, 今回, 仕様, 使用, , 先日, 土台, 失敗, 存在, 対応, , , , 更新, 歴史, 移行, 表示, 返答, 頻度,

そろそろPHPのバージョン引き上げしないと駄目。WPの話。

2022.06.09

Logging

おはようございます。お腹が痛くなるとそれが一週間ほど続いたりします😭。

今日のタイトルは「自分のサーバーのPHPバージョンをアップさせない駄目。WPの話」です。いつの間にかWordPressのバージョンが6になりましたよね。いまの推奨環境ではPHP7.4以上になっています。ワードプレスのロードマップがどうなっているかは知りませんが、そのうちPHP7.4は非推奨になり何れ動作しなくなることは目に見えているので、近々、PHPのバージョンアップを行いたいと思います。

その際はサーバーを停止することもあるので、表示されないという事象が起こる可能性があります。

尚、cgi-binを使用して動かすようになると思います。エンジンエックスでcgi-binを使用するのは初めてですので、長い間、サーバーが不安定な状態になるかもしれません。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

6, 7.4, cgi-bin, php, WordPress, wp, アップ, いま, うち, エックス, エンジン, お腹, こと, サーバー, それ, タイトル, バージョン, プレス, マップ, ロード, ワード, , 不安定, 事象, 今日, 何れ, 使用, 停止, 初めて, 動作, 可能性, 推奨, 状態, 環境, , 自分, 表示, , , , 駄目,

Photo by Luciann Photography on Pexels.com

今頃になってdocker(ドッカー)を勉強していたりしている。

2022.04.30

Logging

おはよう御座います。4月も今日が最後になってしまいました。

皆さんGW(ゴールデンウィーク)は何処か行きますか?、自分はしれっと仕事しているかも知れません。明日は休みですが・・・。

さて、今頃になってdocker(ドッカー)を勉強していたりしてします。dockerとはなんぞやという人はエンジニアでは恐らくないと思います😭。知らない方はググってくださいな。

今までdockerなんて使わなかった、バーチャルボックスがあれば何でも出来ると今でも思っていますが、まぁ一応、dockerも触らないといけないなとか思いましてdockerを始めました。

dockerでイメージを作ってdocker Hubで公開しようと思います。公開する内容は、PHP5系から8系までの環境を構築出来る提供するつもりです。

公開したら追記としてURLを記載しますので、しばしお待ち下さい。来月の半ばまでには構築出来る環境を提供するつもりです。

尚、dockerのCUIなどの操作方法はこちらを参照すると良いですよ。

追記出来ました(5月を待たずして):https://hub.docker.com/r/zip358com/rockylinux-php-56-81-apache

docker pull zip358com/rockylinux-php-56-81-apache
docker run -d -p 80:80 --privileged --name 任意のコンテナ名 zip358com/rockylinux-php-56-81-apache /sbin/init

cgi-binを見てください。PHP5.6からPHP8.1まであります😌。

Apacheの設定、php-cgiを使用する方法はこんな感じです😀

<Directory "/var/www/cgi-bin">
    AllowOverride All
    Options FollowSymLinks
    Order allow,deny
    Allow from all
</Directory>
Action php-cgi-7.1.9 /cgi-bin/php-cgi-7.1.9
<Directory "/var/www/html/xxxx.site">
    Options +ExecCGI
    AddHandler php-cgi-7.1.9 .php .html
    AddType application/x-httpd-php .php
</Directory>

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

4, 5, 8, docker, GW, Hub, php, url, イメージ, エンジニア, お待ち, カー, ゴールデンウィーク, しれっと, つもり, バーチャル, ボックス, , , 今日, 今頃, 仕事, 休み, 公開, 内容, 勉強, 半ば, 提供, , 明日, 最後, 来月, 構築, 環境, 皆さん, 自分, 記載, 追記,

お店のホームページ(サイト)の作り方その弐

2022.03.05

Logging

おひさしぶりです。
ブログを数日休んでいました。こらからは不定期という感じでブログを書いてきます。
このブログはお店のホームページ作り方その壱の続きになります。

下記が予約ボタンと地図の作成手順です、こちらの変更部分をindex.phpのファイルを書き換えてください。予約には予約システムSelectType (セレクトタイプ)を使用しているのでアカウントを作りご自身のお店に合わして管理画面から設定してみてください。

会社の地図に関しては、GoogleMapを使用しています、こちらをindex.phpに貼り付けるのですが必要ない部分があるのでその部分を削除して貼り付けています。動画を注視してみるとわかるかと思います。

予約ボタン
ぐーぐるまっぷ・ お店の地図

今回はここまでです。次回はさくらレンタルサーバにファイルをアップロードする方法とSSLの設定を行い完了となります。

著者名  @taoka_toshiaki

※この記事は著者が40代前半に書いたものです.

Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki

タグ

6, com, GoogleMap, https, index, php, SelectType, SSL, vMSy-CCthA, watch, www, youtube, アカウント, アップロード, お店, ここ, こちら, ご自身, サーバ, サイト, さくら, システム, セレクト, タイプ, ファイル, ブログ, ホームページ, ボタン, レンタル, 下記, 不定期, 予約, 今回, 作り方, 作成, 使用, 削除, 動画, 地図, , 変更, , 感じ, 手順, 数日, 方法, 次回, 注視, 画面, 管理, 設定, 部分,