20201117のPHPに関する記事は15件です。

PHPの勉強でポートフォリオ投稿サイトを作ってみた

はじめに

新卒でウェブ制作会社に就職し、コードの量産に嫌気が差し営業に転職。
趣味で作りたいもののために勉強しているウェブエンジニアです、こんにちは。

今まではWordpressを使用しウェブサイトを作ってきましたが、ウェブサービスを作りたく思いバックエンドの勉強を開始しました。
その時、悩んだこと、作ったサービスを簡単に書こうと思います。

「PHP」を選択するか、あるいは「Laravel」選択するか

結果的にタイトルにあるようにPHPを選択しましたが、すごい悩みました。
というのもPHPはあまりいい噂を聞きません。
「やれ、古い」「やれ、汚い」挙句の果てに「オワコン」なんて言葉も見つけました。

それに比べてLaravelはかっこいい。
なんかモダンな香りがしますよね。
PHP勉強してるより、Laravel勉強してる」の方がかっこいい。

形から入るタイプの私はすごい悩みました。
通勤電車中、仕事中、食事中、ずっと考えました。
考えて考えて考え抜いた結果、「とりあえず手を動かそう、早く作ろう」という結論に至りました。

そうすると環境構築するのも面倒くさいので、もうPHPでいいやと吹っ切れました。

結果的にPHPのことが良く知れたので正しい選択をしたと思っています。
たぶんLaravelの勉強の役にもたったんじゃないかと思い込むようにしています。

勉強開始~制作完了まで

言語選択に時間をかけ過ぎました。
勉強を始めてみるとPHPは確かに学習コストがそこまで高くなく、いい感じで進むので楽しく作成することができました。
学習期間は、ほとんど作りながらの学習だったので、2020年8月20日~2020年10月20日。
丸2か月かかりました。
結構かかりましたが、データベースとPHPをまるっと学べることができたので、有意義な時間でした。
作っているものが形になっていく過程は相変わらず、面白いですね。

ポートフォリオ投稿サイト

作ったのはポートフォリオ投稿サイトです。
機能は見ていただけるとわかりますが簡単にリスト化すると

  • ログイン
  • 投稿
  • イイネ
  • コメント
  • 投稿削除
  • ログアウト

こんな具合。
まあ、多くの投稿サイトと同じ機能を持っていると思います。

サイトは下記URLになりますので、よろしければ投稿してみてください。
またアドバイスもお待ちしております。ぜひとも、何卒。

ポートフォリオ投稿サイト

作ってみた感想と今後

とにかく物を作りたいという欲求を満たすことができました。
学習コストの低いPHPそういった入り口として非常にいい言語なのかもしれません。

ただ実力不足でサービスとしては物足りない部分も多く、例えばセキュリティー対策も最低限しかできていないですし、イイネ機能の非同期通信も結局、実装せずに満足してしまいました。投稿された画像の軽量化とかもしたかった。

そしてにより、作っただけのサービスになってしまいましたので、そこも反省材料として血肉にしていこうと思います。

次はLaravelを使用し、サービスとして確立できるものを作りたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP:条件分岐】if文、else文、elseif文の3つを具体例付きで解説!【初学者向け】

プログラミングをProgateドットインストール、勉強はじめた時は、覚える関数が多くて

「どの関数を使うかわからない!」
「そもそも関数多くて覚えてられない!」

などと悩んだことが多かったです。

しかし、Progateドットインストールで紹介されている関数は網羅的なので、正直あまり使われない関数も多いです。と言うことで、この記事ではまず最初に抑えたいif文と言う関数を3つご紹介します。

if_else_elseif文 (超頻出)

書き方

<?php

  if (/* 条件式① */) {
    /* 条件式①を満たした場合の処理 */
  } elseif (/* 条件式② */) {
    /* 条件式①を満たさず、条件式②を満たした場合の処理 */
  } else {
    /* 全ての条件式を満たさなかった場合の処理 */
  }

?>

因みにelseif以下の部分と、else以下の部分は書いても書かなくてもOKで、その都度利用していく感じです。

具体例①

<?php

  $a = 10;
  $b = 20;

  if ($a < $b) {
    echo "Hello";
  }

  if ($a > $b) {
    echo "World";
  }

?>

出力①

Hello

具体例①の場合、一つ目のif文は条件を満たしているので処理が実行されますが、二つ目のif文は条件を満たしていない為、処理の実行はされません。


具体例②

<?php

  $a = 10;
  $b = 20;

  if ($a > $b) {
    echo "Hello";
  } else {
    echo "World";
  }

?>

出力②

World

具体例②の場合、if文の条件を満たしていませんが、後ろにelse文が入ってるので、そっちの処理が実行されます。(if文の条件を満たしている場合は、if文の処理が実行され、else文の処理は実行されません。)


具体例③

<?php

  $a = 10;
  $b = 20;
  $c = 30;

  if ($a > $b) {
    echo "Hello";
  } elseif ($c > $b) {
    echo "World";
  } else {
    echo "PHP";
  }

?>

出力③

World

具体例③の場合、if文の条件は満たしていませんが、その後のelseif文の条件は満たしている為、そっちの処理が実行されます。なおこの場合、else文の処理は無視されます。(if文の条件とelseif文の条件の、両方とも満たしていない場合は、else文の処理が実行されます。)


まとめ

if文は様々な教材などで扱われる練習用のWebアプリ制作でも、かなり頻出します。またこう言うのは「習うより慣れろ!」なので、ぜひ実際にコードを書いて練習してみてください。

最後までご覧いただき、ありがとうございました!

筆者:yuki|学習10日目で初案件獲得→現在はフルスタックエンジニア転職に向けて学習中
Qiita:https://qiita.com/yuki4839
Twitter:https://twitter.com/yuki35522891

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel基礎】フォームの入力内容を制限する方法【バリデーションとフォームリクエスト】

概要

Laravel学習で自分がつまずいた部分を備忘録としてまとめています。
今回はフォームの入力内容の制限に関する記事です。

つまずいたポイント

指定条件以外のフォーム入力を弾いてくれるバリデーション
そんなバリデーションですが、アクション事に毎回指定するのが面倒くさい。。
効率的な方法が無いか調べました。

どうやら、フォームリクエストなるものを使うと
一括でバリデーションを指定出来るとのこと。

バリデーションの復習もかねて、下記の2つを記事にしました。

①バリデーション

②フォームリクエスト

以下、記事内容です!

バリデーション

まずはバリデーションの復習。
保存や編集などの、フォーム内容を受け取るアクション内で、
$this->validate($request,[条件]);を入力。
第2引数の入力内容が、フォームの入力条件になります。

■コントローラ

PostsController
    public function store(Request $request) {  

      //バリデーションで条件を指定
       $this->validate($request, [
        'title' => 'required|min:3',
        'body' => 'required'
      ]);

      $post = new Post();
      $post->title = $request->title;
      $post->body = $request->body;
      $post->save();
      return redirect('/');
    }

上記の場合だと、
title => 3文字以上 , body => 入力必須
て感じですね。
この条件以外の内容がフォームから送信されると、バリデーションが弾いてくれます。

フォームリクエスト

次はフォームリクエストです。
バリデーションはアクション毎にフォームの入力内容を指定していましたが、
フォームリクエストではそれを一括で指定することが出来ます。
以下、手順です。

ターミナル
php artisan make:request PostRequest

フォームリクエストはphp artisan make:request 〜Requestで作成出来ます。
今回はPostRequestと名付けました。
作成したRequestはApp\Http\Requestsの中にあります。

■フォームリクエスト

PostRequest.php
   //①
   public function rules()
    {
        return [
            'title' => 'required|min:3',
            'body' => 'required'
        ];
    }

    //②
    public function messages() 
    {
        return [
            'title.required' => 'タイトルを入力して下さい。'
       ];
    }

フォームリクエスト上での主な指定内容は2つ。
1つは入力内容の条件、もう1つはバリデーションのメッセージです。

まずは入力内容の条件から。rulesメソッドを使う事で条件指定できます。(①)
中身は先ほどのバリデーションと同じですね。

そしてmessagesメソッドでは、
バリデーション適用時のメッセージを指定する事ができます。(②)
デフォルトでは英文が指定されているので、わかり易くするには日本語に変えておいた方が良いかもですね。

■コントローラー

PostsController
//①
use App\Http\Requests\PostRequest;

    //②
    public function store(PostRequest $request) {   
      $post = new Post();
      $post->title = $request->title;
      $post->body = $request->body;
      $post->save();
      return redirect('/');
    }


コントローラでは、フォームリクエストをuseで使えるようにしましょう。(①)
そしてアクションの引数にフォームリクエストを入力。(②)
フォームリクエストで指定した内容が適用されるようになります。
バリデーションを書かないで良いので楽ですね。

フォームリクエストは以上です!
1.ターミナルからフォームリクエストを作成
2.フォームリクエストの条件を指定
3.コントローラ+アクションでフォームリクエストを適用
という流れですね。

ちなみに、何でアクションの引数にrequestを入れるだけでフォーム内容が受け取れるのか?
疑問に思って調べましたが、「サービスコンテナ」やら「メソッドインジェクション」やら「DI(Dependency Injection = 依存性注入)」なる単語まで出てきて、脳がフリーズしたので一旦忘れます。いつかちゃんと調べて記事にします。多分。。。

まとめ

以上、Laravelでフォームの入力内容を制限する方法でした。
最後まで読んで頂きありがとうございました。
フォームリクエストの方がコードの量が少なくなるので楽ちんですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

5分で作るDocker+Laravel PHP+Vue.js開発環境構築

開発環境
macOS Big Sur

下記の記事を参考に環境構築を行ったのですが、
やれwgetコマンドが無いだの、apt-getコマンドが無いだの初心者の方への導入への障壁がいくつかあったため、
それを乗り越えるための記事にしたいと思います。(※注:下記の記事は決して悪くありません。)

タイトル リンク
5分で作るLaravel+Vue.js開発環境(docker-compose) https://qiita.com/yusukeito58/items/37bd551560e495dbd1b8

wgetコマンドインストール

タイトル リンク
Mac - wgetコマンドをインストール(使えるようにする) https://qiita.com/th4inf/items/f85c1b91065d85af67b9

apt-getコマンドインストール ←apt-getコマンドが無いかと思い調べてが結果的にいらないのでやらんで良い

タイトル リンク
install apt-get to Mac https://qiita.com/th4inf/items/f85c1b91065d85af67b9

docker-compose up -d --build時にmysql-clientのエラーがでたら

エラー内容

E: Package 'mysql-client' has no installation candidate
ERROR: Service 'app' failed to build : The command '/bin/sh -c apt-get update     && apt-get install -y zlib1g-dev mysql-client libpng-dev libjpeg-dev gnupg curl wget     && docker-php-ext-configure gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include     && docker-php-ext-install zip pdo_mysql gd' returned a non-zero code: 100
タイトル リンク
docker-compose buildするときにbundle installやmysql-clientでコケた話 https://qiita.com/aseanchild1400/items/d3580366054fee3d2703

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

転生できないからVimで2つのファイルの差分を確認してみた

状況

案件の対応で先方の都合?で
Bitbucketでコードの管理を行い
完成したコードをFTPを使って直接サーバーにコードをアップする
その際にコードの改修をする場合に仮にclone(pull)したコードが
先方のサーバーにあるコードと相違があった場合に意図しない処理が
先方のサーバーに上がってしまいトラブルの原因となってしまうので
その確認のために差分を見ることを実施したのでその忘備録

参考サイト
https://nanasi.jp/articles/howto/diff/diff_text.html

改修を予定しているAファイルを開いて下記コマンドを実行

:vertical diffsplit 差分を取りたいファイル

今回はBファイルと照らし合わせるとした場合には

:vertical diffsplit Bファイル

こうすることで画面が縦に2分割されて差分がみれる
なお自分がやったときには差分が無かった為
一行ほどに文言が書かれているだけだった。

もしこれで差分があった場合には
Bitbucketにあるファイルが古いのか
または先方のサーバーにあるファイルが古いのか
と気づけてその対応をすることによって
事前にトラブルを防ぐことができる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS BeanstalkでLaravelをデプロイするときにCloudwatch Logsにログを転送する

前提のBeanstalk環境

PHP 7.4 running on 64bit Amazon Linux 2/3.1.3

やること

  • lavavel.logのパーミッション設定
  • EC2にCloudwatch Logsのロググループ作成のためのサービスロールを追加
  • 設定ファイル(.ebextensions)の作成

1. lavavel.logのパーミッション設定

$ chmod 0664 /var/www/html/storage/logs/laravel.log

2. lavavel.logのパーミッション設定

  • Beanstalk環境のIAM インスタンスプロフィールに設定されているIAMロールに、CloudWatchLogsFullAccessのポリシーを追加 (Codepipelineでデプロイしている場合は、そのロールにも同様にCloudWatchLogsFullAccessのポリシーを追加)

3. 設定ファイル(.ebextensions)の作成

  • PHP Platformでデフォルトで追加されるログの設定

参考: https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/AWSHowTo.cloudwatchlogs.html

.ebextensions/4-eblog.config
option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true

  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false

  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: RetentionInDays
    value: 7
  • カスタムログでlaravel.logを設定する

参考: https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/instance-configuration/logs-streamtocloudwatch-linux.config

.ebextensions/5-laravellog.config
packages:
  yum:
    awslogs: []

files:
  "/etc/awslogs/awscli.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [plugins]
      cwlogs = cwlogs
      [default]
      region = `{"Ref":"AWS::Region"}`

  "/etc/awslogs/awslogs.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [general]
      state_file = /var/lib/awslogs/agent-state

  "/etc/awslogs/config/logs.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [/var/www/html/storage/logs/laravel_log]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "var/www/html/storage/logs/laravel_log"]]}`
      log_stream_name = {instance_id}
      file = /var/www/html/storage/logs/laravel*

commands:
  "01":
    command: systemctl enable awslogsd.service
  "02":
    command: systemctl restart awslogsd

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

でかいデータのAjaxリクエストを圧縮して軽くしてPHPで受け取る

数MBくらいあるデータをリクエストボディに載せたいけど、少しは軽くしたいのでゴニョゴニョ。

JS側

import pako from 'pako'
import axios from 'axios'

const bigObject = { /* 超でかいObject */ }
const json = JSON.stringify(bigObject)
const gzipped = pako.gzip(json, { to: 'string' })
const base64Encoded = btoa(gzipped)
axios.post('/api/foo', { compressed: base64Encoded })
  • JSONにする
  • pako を使ってgzip圧縮する
  • btoa() を使ってBase64エンコードする
  • 文字列としてリクエストする

PHP側

$gzipBinary = base64_decode($_POST['compressed']);
$json = gzdecode($gzipBinary);
$data = json_decode($json, true);

余計な処理は入るけど、リクエストボディが 1.5MB から 250KB くらいまでは小さくなったので満足。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel passportのログイン失敗のエラーを飛ばさないようにする

Laravel passportを使うときデフォルトでは、ユーザーのログイン認証に失敗するだけでエラーを投げるようになっている。
エラートラッキングツール(Sentryなど)を使っていると、ユーザーがログイン失敗するだけで通知が来てしまうのが面倒。

Handler.pnpに、下記のように追記するとエラーが飛ばないようにできる。

app/Exceptions/Handler.php
protected $dontReport = [
    \Laravel\Passport\Exceptions\OAuthServerException::class,
];
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel基礎】データの受け渡し方 【①ルートパラメータ②Implicit Binding】

概要

Laravel学習で自分がつまずいた部分を備忘録としてまとめています。
今回はデータの受け渡しに関する記事です。

つまずいたポイント

記事投稿型の簡易アプリ作成時につまずいた問題です。

記事一覧ページ→記事の詳細ページに移る際、
ビュー→コントローラに投稿のデータを渡すにはどうしたら良いのか?
下記2つの方法で解決出来たので記事にしてみました。

①ルートパラメータ

②Implicit Binding

以下、記事内容です!

ルートパラメータ

まず渡し方の1つがルートパラメータを用いた方法です。

■ビュー

index.blade.php
 @foreach ($posts as $post)
    <li>
       <a href="/posts/{{ $post->id }}">{{ $post->title }}</a>
    </li>
 @endforeach

まず、ビュー上でURLを用いて、ルーティングに投稿のIDを渡します。

■ルーティング

web.php
Route::get('/posts/{id}','PostsController@show')

ここからがルートパラメータを用いた方法です。URLの中に{ }を設定します。
この{ }の中身がパラメータと言う扱いになり、アクション内でこのパラメータが使用可能になります。
仮で{ }の中身を{id}と設定していますが、中身にはビューで設定した$post->idが入ってきます。
※{ }は変数扱いなので、中身の文字はわかりやすい単語でOK

【例】'/post/test'でアクセスした場合 → 「test」がパラメータ扱い
   '/post/1'でアクセスした場合  → 「1」がパラメータ扱い

■コントローラ

PostsController
    //アクションの引数にパラーメータを設定
    public function show($id) {
          //パラメータをアクション内で使用出来る
          $post = Post::find($id);
          return view('posts.show')->with('post', $post);
        }

アクションの引数の中に先ほどのパラメータを代入する事で、
アクション内でそのパラメータが使用可能になります。

上記のshowアクションでは、
パラメータを元にfindメソッドで該当の記事データを再取得→
記事データを渡しつつ投稿の詳細画面を表示することが出来ました。

Implicit Binding

次はImplicit Bindingです。
ルートパラメータの場合、URLに書かれた文字列だけをコントローラに渡しました。
Implicit Bindingの場合は、投稿を丸ごと渡すことが出来ます。
下記、その手順です。

■ビュー

index.blade.php
@foreach ($posts as $post)
    <li>
       <a href="/posts/{{ $post }}">{{ $post->title }}</a>
    </li>
@endforeach

URLに$postを指定します。

■ルーティング

web.php
Route::get('/posts/{post}', 'PostsController@show')

先述のルートパラメータで{post}を指定します。

■コントローラー

PostsController
public function show(Post $post) {
              return view('show')->with('post',$post);
            }

アクションの引数を(Post $post)に指定→投稿の中身を$postで使用できます。

先ほどと違い、アクション内で投稿を再取得せずに$postをそのまま記事詳細画面に渡すことが出来ました。楽ちんですね。

まとめ

以上、Laravelにおけるビュー→コントローラへデータの渡し方でした。
Implicit Bindingの方が書くコードの量が少なくなるので効率的ですね。

最後まで読んで頂きありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

InterventionImageで編集した画像ファイルをbase64変換してMySQLに保存する

やりたいこと

InterventionImageで編集した画像ファイルをバイナリーに変換してMySQLに保存したい
もちろん画像ファイルは/public配下やS3などのファイルシステムに保存するのが定石なのは承知の上で、今回は手軽さを優先してDBに画像ファイル自体をtextカラムに保存する

環境


% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H2

% docker version
Client: Docker Engine - Community
 Cloud integration: 1.0.1
 Version:           19.03.13
 API version:       1.40

# php -v
PHP 7.4.7 (cli) (built: Jun 11 2020 18:41:17) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans

# php artisan -v     
Laravel Framework 7.26.1

# mysql --version
mysql  Ver 14.14 Distrib 5.7.30, for Linux (x86_64) using  EditLine wrapper

Intervention Image とは

ImageMagikの上位互換?のモダンな画像編集パッケージ
リサイズ、トリミング、フィルターとなんでも手軽にできるっぽい
詳しくは公式doc参照

MySQLに画像バイナリを保存する

UserController
    public function update(Request $request, User $user)
    {
        // InterventionImageで加工&保存
        $file = $request->file('profile_img');
        $img = Image::make($file);
        $img->fit(400); //400px * 400px にトリム&リサイズ
        $bin = base64_encode($img->encode('png'));

        $user->profile_img = $bin;
        $user->save();
        return redirect()->route('user.index');
    }

ポイントは$bin = base64_encode($img->encode('png'));の1行。
base64_encodeする前に一度InterventionImageインスタンスをエンコードしている。
この処理がないとbase64_encodeしても空文字が生成される。なぜかはよくわからない。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バイト ビット について strlen関数mb_strlen関数で実証

学習した事をアウトプットするためいんQiita投稿しています。
学習中ユーザーが書いた記事になります。

[ビット・バイト]について学習した理由は、
strlen関数、mb_strlen関数(簡単に文字列を数える)関数について理解を深めたかったから。

ビットとは

ビットとは、0か1が入る箱の事。

つまり、

1ビット・・・0、1(2通り)

2ビット・・・01、10、00、11 (4通り)

3ビット・・・000、001、010、011、100、101、110、111(8通り)

4ビット・・・16通り

5ビット・・・32通り

それでは問題。

16ビットは何通りでしょうか。

ヒント:
・1ビットで表現できるのは0、1の2通り
・ビットパターンは0、1の2通り

正解は下記 「【基本】シングルバイトとは」に記載。

上記を見ていただいたら分かる通り、1ビット増えるごと、倍のデータ量となります。

【基本】バイトとは

バイトとは、0か1が入る箱(ビット)が8つくらい入る大きな箱の事。

補足:
基本的には1バイト=8ビット
ただ、
・1バイト=9ビット
・1バイト=7ビット
ともなるようですが、「基本的」の部分だけ学習して覚えていきます。

【基本】マルチバイトとは

2バイト以上のこと。
マルチとは複数という意味です。つまり、2バイト以上(複数)でマルチバイトと呼びます。

1バイト=256通りで表現出来ない情報量をマルチバイトと呼びます。

【基本】シングルバイトとは

シングルバイトとは、1バイトの事を呼びます。
シングルとは一つという意味です。
1バイトで表現できる情報量は8ビット=256通りです。

16ビットの答えは
「65536通り」

strlen関数,mb_strlen関数

冒頭でお伝えした
strlen関数、mb_strlen関数を使用してビット、バイト理解を深める。

補足:読み方間違えてるかもしれませんが、
・strlen(ストアレン)関数
・mb_strlen(マルチバイトストアレン)関数

strlen関数とは・・・文字列の長さのバイト数を返す(出力する)。

mb_strlen関数とは・・・日本語などのマルチバイト(複数)の文字列をカウントする。

strlen関数と、mb_strlen関数ではどのように違うのか実証!

mb_strlen関数

    $i = '初めまして';

    var_dump(mb_strlen($i,'utf8'));

出力結果:int(5)
ーーーーーーーーーーーーーーーーーーーーーーー

    $i = 'ABC123A';

    var_dump(mb_strlen($i));

出力結果:int(7)

strlen関数


    $i = '初めまして';

    var_dump(strlen($i));

出力結果:int(15)

ーーーーーーーーーーーーーーーー
    $i = 'ABC123A';

    var_dump(strlen($i));

出力結果:int(7)

アルファベットはしっかり文字列がカウントされているのに対して、
日本語は違う結果が返ってきました。
初めまして=5文字です。
mb_strlen関数では5文字とカウントされているのに対して、
strlen関数は15文字とカウントされています。

どうして?

多くの日本語は1文字=3バイト[24ビット]の情報量となっています。

また、半角英数字・・・1文字=1バイト[8ビット]
となっています。

つまり、

strlen関数・・・上記で説明した様に、[バイト数]を返すため日本語1文字3バイトのため
日本語文字数5*1文字3バイト=結果(15)と返ってくる。

mb_strlen関数・・・マルチバイト文字列に対して[文字列の長さ]を返すため結果(5)

ただし、mb_strlen関数 気をつける事

こちらにも記載しています。
https://www.php.net/manual/ja/function.mb-strlen.php

第二引数にエンコードを指定した方が良いよって事です。

これについて他記事も見ましたが、つまりは

第二引数は省略可能ですが、その場合は内部エンコーディングを使用するため
内部エンコーディングと文字エンコーディングが異なっている場合違った結果が返ってくる場合があるよって事です。

だから、第二引数を指定してあげた方が安全で安心ですよって事です。
var_dump(mb_strlen($i,○));
※○の部分( 第二引数)。
※エンコード指定の際にスペルミス等不明なエンコード指定した場合、エラーになります。

補足:今回私の環境で行った際にはこちらの記事通りの結果が返ってきました。
他記事を見ていると、記事の中には日本語1文字=2バイトといった結果が返ってきている場合もあるようです。

まとめ

バイト・ビットについて学習をして、実際に関数を用いて実証する事で理解が深まりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ESP32とMySQLとXAMPPを使ってWiFi強度(RSSI)をリアルタイムで閲覧したい

たまにネットワークが途切れるがどのネットワークが強いのか接続しないと分からないなぁ。のひとことから勉強のつもりで作ってみました。
esp32でRSSIを取得するコードがなかなかみつからなかったのでここに残します。
arduino ideのソースコードに関してはほぼ初心者でhtmlは今回の件で初めて触りました。
自分で見てもかなり見にくいのでアドバイスもいただけますと幸いです。
もちろん市販品のほうが性能もよく見やすいのは承知です。

今回の目標

①esp32でRSSIを取得しMySQLへ蓄積。
②MySQLに蓄積されたデータをxamppを使い社内のみブラウザで閲覧できるようにする。

①の攻略

まずソースコードは以下の通り。
環境設定をしたarduino ideへ。

esp32_wifi_power_complete.ino
 #include <SPI.h>
#include <WiFi.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

const char ssid[] = "*******";
const char pass[] = "*******";

//ESP32のIPアドレス
IPAddress ip(***, **, **, ***);
IPAddress gateway(***, **, **, *);
IPAddress subnet(255, 255, 255, 0);

// Wifi 通信用
WiFiClient client;

// SQLサーバーのIPアドレス
IPAddress server( ***, **, **, ***);
// SQLユーザー名
char user[] = "*******";
// SQLパスワード
char password[] = "*********";

// SQLコマンド用
MySQL_Connection conn ((Client *)&client);

char INSERT_SQL[] = "INSERT INTO schemas名.テーブル名(要素①, 要素②, 要素③, RSSI) VALUES('***', '***', '****', %ld)";

long get_current(void);
void insert_data(long);


void setup()
{

 Serial.begin(115200);

 WiFi.config(ip, gateway, subnet);

 WiFi.begin(ssid, pass);

 Serial.println("WiFi connecting");

 Serial.println(WiFi.localIP());

 //SQLサーバへの接続
 Serial.println("Connecting Database");
 if (conn.connect(server, 3306, user, password)) {
   delay(10000);
 }
 else {
   Serial.print("Connection failed!");

 }
 //SQLサーバの切断
  conn.close();

}

void loop () {

  int i;

  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Couldn't get a wifi connection");
    WiFi.begin(ssid, pass);
    delay(1000);

  }

  long rssi = WiFi.RSSI();
  Serial.print("RSSI:");
  Serial.println(rssi);
   Serial.println(ssid);
  delay(1000);

    //SQLサーバへの接続
  Serial.println("Connecting Database");
  if (conn.connect(server, 3306, user, password)) {
    delay(1000);
    //データの書き込み
    insert_data(rssi);
  }
  else {
    delay(1000);
    Serial.print("Connection failed!");

  }

  conn.close();

  //26秒待つ
  for (i = 0; i < 26; i++) {
    delay(1000);
  }

}

//SQLサーバへの書き込み
void insert_data(long rssi)
{

  char buf[600];

  Serial.print("Recording data=");
  Serial.println(rssi);

  sprintf(buf, INSERT_SQL, rssi);

  //SQLの書き込みオブジェクトの作成
  MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  //SQLの書き込み
  cur_mem->execute(buf);
  //SQLの書き込みオブジェクトの開放
  delete cur_mem;

}

MySQLの使い方やarduino ideでのESP32の環境設定などはわかりやすいサイトが多くありますのでそちらをご覧ください。

いろんなところから引き抜いてきたコードなので不要な箇所もあるかもしれませんが一応正常に動作しています。

以前まで動作中にWiFi接続が切れてしまうことやMySQLへの接続がきれてしまうことがありましたが、このプログラムに変更してから切断されても再接続できるようになりました。

私は初心者なのでMySQL Workbenchで確認をしていますがもちろんコマンドプロンプトからも可能です。

データが送られていることが確認できれば①は攻略です。

自分の努力の割に説明することが少ないので不明な点はご質問ください。

随時更新します。

②の攻略

MySQLにデータを蓄積することは今までも経験があったのですが、正直そこで満足していました。
でもせっかく時間があるので社内のみで見れないかな~と考えていた時に出会ったのがxamppです。
xamppについては以下のページが鬼分かりやすかったのでリンクを貼っておきます。

markdown:https://www.adminweb.jp/xampp/
Markdown:https://techacademy.jp/magazine/1722

これらの基礎を踏まえて以下のコードになりました。

test.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>タイトル</title>


<style>

h1{ color: blue; }

h1{ background: white}

body{ background: black }

body{ text-align: center }

.first{ border: double 10px brown }

h1{ border-bottom: dotted 5px brown }

.side{ display: flex;
 justify-content: space-around; }

body{ color: white;}

</style>

</head>

<body>

<h1>表題</h1>

<div class="first">
<h2>強度の見方</h2> 
<p>RSSI=0 ・・・世界最強</p>
<p>RSSI=-50 ・・・結構いい</p>
<p>RSSI=-75 ・・・普通</p>
<p>RSSI=-100 ・・・接続不可</p>
</div>

<div class="data">

<h2>Shinto 1F</h2>

<?php

$dsn = 'mysql:dbname=*******;host=localhost';
$user = '******';
$password = '*******';

try{
    $dbh = new PDO($dsn, $user, $password);

    $sql = 'select * from **** where **** = "*********" order by PK desc limit 1';
    foreach ($dbh->query($sql) as $row) {
        print($row['*****'].' *****');
        print($row['*****'].' *****');
        print($row['****']);
        print('<br />');
    }
}

catch (PDOException $e){
    print('Error:'.$e->getMessage());
    die();
}
?>

</div>

</body>
</html>

そして
http://*****/test.phpにアクセスするとまあ見れるぐらいのものが表示されるはずです。

終わりに

もし興味があればご連絡下さい。
一応ほぼ0からの素人が0から作ったのである程度は説明できると思うのですが投稿するのになれてなさ過ぎてなにを書けばいいかさっぱりです。
連絡いただければ必ず返答しますのでお許しください。。。

今後はHTMLの勉強をしてかっこいいページをつくりたいですね

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】画面出力する際にechoとprintどちらを使うか

PHPの初学者です。ふと疑問に思いました。

画面出力する際にechoとprintのどちらを使うか

結論: どちらを使っても、大した違いはありません。

(但し、厳密には異なります。)

echo
1つ以上の文字列を出力します。
返り値・・・値を返しません。
print
文字列を出力する
返り値・・・常に1を返します。

つまり...

echo → 返り値がない
print → 返り値がある
でも、printで出力した場合、常に返り値が1であるため、それを使って何かをすることはありません。

結局は、echoで出力すると良い

今までの説明で、echoもprintも違いはあれども、大した違いは無いということはわかっていただけだかと思われます。

それでもechoを使うと良いのです!

理由はパラメーターの違いです。echoはパラメーターを複数指定できます。
先程出てきましたが、
echoは1つ以上の文字列を出力し、printは単に文字列を出力します。

test.php
<?php
echo 1, 2, 3, 4;
?>

次のようになります。
1234

test.php
<?php
print(1, 2, 3, 4);
?>

次のようになります。
Parse error: syntax error, unexpected ','
printにはカンマは使わないのに、強引に書いた為に、構文エラーになってます。

echoの場合、文字列と整数を併記することも可能

echoはパラメーターを複数指定が可能ですが、文字列と整数を混合させて記述することもできます。

test.php
<?php
echo "2+5=", 2+5;
?>

次のようになります。
2+5=7

まとめ

  • PHPにおいて、画面出力する際にechoとprintのどちらを使っても、大した違いはありません。
  • 但し、echoはパラメーターを複数指定することができ、文字列と整数を併記することも可能です。
  • よって、echoを使うのが良いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プリザンターから自前アプリの画面を開く

概要

プリザンターから情報を引き継いで、自前アプリの画面を開く方法を調査。
例えば、プリザンターでログインした後に、特定のデータだけは自前アプリを作って表示するといった使い方を想定。

前提条件

  • 環境
    • OS: Windows10
    • ローカル環境に構築したプリザンター
  • 以下の詳細説明は省略
    • プリザンター
    • php

結論

プリザンターから自前アプリの画面を開けることを確認できた。
スクリプトでPOSTして自前アプリに画面遷移させる方式。
プリザンターの情報の引継ぎも可能。

詳細

自前アプリを準備

phpで簡単なページを作って、簡易サーバを起動しておく。
POSTで受け取った以下3つの情報を表示するだけの画面。

  • userId
  • userName
  • loginId

↓簡単なページ

index.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test</title>
</head>
<body>
    <h1>Test Page</h1>
    <p>
        userId: <?= $_POST['userId'] ?><br/>
        userName: <?= $_POST['userName'] ?><br/>
        loginId: <?= $_POST['loginId'] ?><br/>
    </p>
</body>
</html>

↓簡易サーバ起動

>php -S localhost:8030

プリザンターにスクリプトを設定

プリザンターにフォルダを作成し、スクリプトを追加。
フォルダを開いたときに、自前アプリにPOSTするスクリプト。
プリザンターで用意されている3つの情報をPOST。

↓フォルダを作成

image.png

↓スクリプトを追加
image.png

↓スクリプトのソース

post.js
let url = 'http://localhost:8030/index.php';
// POST用のフォームを生成
let html = '<form method="post" action="' + url + '" id="form_post" style="display: none;">';
html += '<input type="hidden" name="userId" value="' + $p.userId() + '" >';
html += '<input type="hidden" name="userName" value="' + $p.userName() + '" >';
html += '<input type="hidden" name="loginId" value="' + $p.loginId() + '" >';
html += '</form>';
// bodyに追加
$("body").append(html);
// POSTで送信
$("#form_post").submit();

動作確認

ログアウトして、再度ログイン。
「他のページに遷移」のフォルダを開くと、自前アプリの画面が表示されることを確認。

image.png

↓フォルダを開くと。。。

image.png

ログインユーザの情報を自前アプリで表示できることを確認できた!

補足

上記のスクリプトを設定すると、フォルダ自体の設定ができなくなるので注意。
設定したいときはURLを直指定で設定画面を開くこと。
URLの例: http://192.168.10.10/pleasanter/items/12423/edit

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

表示件数を1ページ目だけ変えるページネーションの実装

はじめに

表示件数が1ページ目だけ異なるページネーションの実装をまとめました。
紹介した内容以外でもっと良い方法がありましたら教えてもらえると助かります!

解説

1ページ目に3件、2ページ目以降は10件ずつ表示する場合で解説していきます。
(件数は適当なので、各自好きな数字で調整してみて下さい)

ページの取得件数を設定

$post_per_page = $paged > 1 ? 10 : 3;

ページの取得件数を設定しています。1ページ目なら3、2ページ目以降なら10を設定します。
SQLのLIMIT句$post_per_pageを設定すれば、テーブルから取得するデータ件数を指定できます。

取得するデータの開始位置を設定

if ( $paged > 1 )
    $add_args['offset'] = 3 + ( $paged - 2 ) * 10;

2ページ目以降は1ページ目の3件+1ページごとに10件読み飛ばします。
例:2ページ目は4件目から、3ページ目は14件目からデータを取得

ここでの$add_args['offset']OFFSET句に指定することで、テーブル上でどの位置からデータを主とするのかを指定できます。

合計ページ数を計算

$comment_count = 20    //コメント総数
$max_page = ceil(($comment_count - 3) /  10) + 1

まず、表示件数の異なる1ページ目をコメント総数から引きます。
引いた結果、2ページ目以降で合計何ページあるか産出されます。
そして、最後に1ページ目を足しています。

参考

[WordPress] 1ページ目だけ表示件数が異なるページネーションの実装
取得するデータの数と開始位置を指定(LIMIT句, OFFSET句)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む