20200727のMySQLに関する記事は13件です。

Node.jsとMySQLをDockerComposeで組んでみた

初めてのDockerネットワーク
これから先僕が環境構築する際、思い出せるようにするための、です。

事前準備

まずDockerHubから二つのイメージをpullするところから
それぞれ12系と5.7系を使うのでバージョン指定

$ docker run -it node:12
$ docker run -it mysql:5.7

runはpull,create,startを一気に行ってくれる

control+p+qでコンテナから出る

その後$ docker ps -aで一度止めて、
コンテナが作成されているかを確認する(Upなら一度stopしてExitedにしておく)
これからは$docker start [コンテナID]で起動できる

$ docker rename [古いコンテナ名] [新しいコンテナ名]
しておいた方がわかりやすい

正しいバージョンのものが入っているかの確認は起動後
$ docker exec -it [コンテナ名] bash
attachと違うのはコンテナを起動したまま抜けることができるのかできないのかが違うexecは起動したまま抜けることができる
でコンテナに入り、バージョン確認...

MySQLが起動しない...

先人様がいらっしゃいました。ありがとうございます。↓
https://qiita.com/takepan/items/0cbf13af3a0bb2c243ab

よしこれで確認できた

...でどうやってつなげるん??

Docker Composeとは

複数のコンテナを組み合わせてシステムを構成するための仕組みに用いるのがDocker Composeと呼ばれるもので、予めコンテナの起動方法やボリューム、ネットワークの構成などが書かれている

こんなものがあるのか、今まで一つのコンテナを独立させて動かしていたので、全く知りませんでした...

事前知識でDockerネットワークやマウントのことを知らなければならないとのことで書籍を借りて軽く頭に入れておきました。
全然知らないままDockerを使っていたのだなと反省

そしてこれを書いていく...docker-compose.ymlを作ってバージョン決めて、サービスの中身にnode.jsとmysql使いますよってこととかそれぞれの設定など、先人のymlファイルを参考にゴリゴリ書いていく...

書き方を丁寧に載せてる先人様の記事はこちらです。ありがとうございます。↓
https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

かけたら、docker-compose up で起動
しばし待つ

...しばし待つ

終わらねえ

db  | Version: '5.7.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

ここで止まって一向に動かない...

仕方ないので、control+cで一度抜けました

docker-compose psで確認すると動いといて欲しいdb(mysql)が動いてない...

一か八かでdocker start dbを試すと...

stateがExitからUpに
一件落着

ていうかこのやり方だと最初にコンテナは立ち上げなくても、なんならimageもpullしてこなくて急にdocker compose書いてあげた方がよかったのね...

じゃあ他のコンテナもたてます
今回はフロント、バック、dbの三つのコンテナを用意します。

docker-compose start

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

Node.jsとMySQLをDockerComposeで組みつつ、React,Express,MySQLの環境構築を躓きながらやっていく

初めてのDockerネットワーク
これから先僕が環境構築する際、思い出せるようにするための、です。

事前準備

まずDockerHubから二つのイメージをpullするところから
それぞれ12系と5.7系を使うのでバージョン指定

$ docker run -it node:12
$ docker run -it mysql:5.7

runはpull,create,startを一気に行ってくれる

control+p+qでコンテナから出る

その後$ docker ps -aで一度止めて、
コンテナが作成されているかを確認する(Upなら一度stopしてExitedにしておく)
これからは$docker start [コンテナID]で起動できる

$ docker rename [古いコンテナ名] [新しいコンテナ名]
しておいた方がわかりやすい

正しいバージョンのものが入っているかの確認は起動後
$ docker exec -it [コンテナ名] bash
attachと違うのはコンテナを起動したまま抜けることができるのかできないのかが違うexecは起動したまま抜けることができる
でコンテナに入り、バージョン確認...

MySQLが起動しない...

先人様がいらっしゃいました。ありがとうございます。↓
https://qiita.com/takepan/items/0cbf13af3a0bb2c243ab

よしこれで確認できた

...でどうやってつなげるん??

Docker Composeとは

複数のコンテナを組み合わせてシステムを構成するための仕組みに用いるのがDocker Composeと呼ばれるもので、予めコンテナの起動方法やボリューム、ネットワークの構成などが書かれている

こんなものがあるのか、今まで一つのコンテナを独立させて動かしていたので、全く知りませんでした...

事前知識でDockerネットワークやマウントのことを知らなければならないとのことで書籍を借りて軽く頭に入れておきました。
全然知らないままDockerを使っていたのだなと反省

そしてこれを書いていく...docker-compose.ymlを作ってバージョン決めて、サービスの中身にnode.jsとmysql使いますよってこととかそれぞれの設定など、先人のymlファイルを参考にゴリゴリ書いていく...

書き方を丁寧に載せてる先人様の記事はこちらです。ありがとうございます。↓
https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

かけたら、docker-compose up で起動
しばし待つ

...しばし待つ

終わらねえ

db  | Version: '5.7.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

ここで止まって一向に動かない...

仕方ないので、control+cで一度抜けました

docker-compose psで確認すると動いといて欲しいdb(mysql)が動いてない...

一か八かでdocker start dbを試すと...

stateがExitからUpに
一件落着

ていうかこのやり方だと最初にコンテナは立ち上げなくても、なんならimageもpullしてこなくて急にdocker compose書いてあげた方がよかったのね...

じゃあ他のコンテナもたてます
今回はフロント、バック、dbの三つのコンテナを用意します。

docker-compose start

動かない...

それもそのはず、docker-composeに必要なコマンドを書いてなかったからなんですね
いやymlファイルに書くコマンド全然わからん...ってなった僕はとりあえずdocker-compose run [コンテナ名] bashで中に潜り込んで、reactの環境を作ることに...

node -v,npm -vでバージョンを確認
npm install -g create-react-appでcreate-react-appをインストール

create-react-app [プロジェクトを入れるディレクトリ名]
しばしまつ...

Happy hacking!これで完了

(docker-compose run [コンテナ名] bashで中に潜り込んで作ったせいで、docker-compose upでローカルに作られたディレクトリの中に[プロジェクトを入れるディレクトリ名]のディレクトリができてしまったので削除しておく)

では改めて...docker-compose start

ンンンン?

stateがExitから変わらない...
全部docker-composeに書いてるはずなんだけどな...

ダメそうなので、docker-composeでdockerfileを参照することにする
docker-composeでimageを直接引っ張ってきてた部分をbuildで参照し、コマンドを書いたり〜、作業するディレクトリを書いたり〜

よしこれで、わかりやすくなった気がする
docker-compose start

はい、ダメー

どうすればいいのだ...と助けを求めると、
docker-compose upで立たない?
って言われハッとした

そういえば...

かけたら、docker-compose up で起動
しばし待つ
...しばし待つ
終わらねえ
db | Version: '5.7.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
ここで止まって一向に動かない...
仕方ないので、control+cで一度抜けました

これが原因じゃないの

ってことでもう一度
docker-compose up
...
Compiled successfully!

動いた!!!!

ということで無事コンテナが起動し、localhost:3000にアクセスすると、reactがくるくるしとる!

stopしてからのstartでも起動できることが確認できた
よかったよかったこれでフロント(react)とdb(mysql)が動いた。

次はバック(express)のコンテナを立てるぞ

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

Node.jsとMySQLをDockerComposeで組みつつ、React(TS),Express,MySQLの環境構築を躓きながらやっていく

初めてのDockerネットワーク
これから先僕が環境構築する際、思い出せるようにするための、です。

事前準備

まずDockerHubから二つのイメージをpullするところから
それぞれ12系と5.7系を使うのでバージョン指定

$ docker run -it node:12
$ docker run -it mysql:5.7

runはpull,create,startを一気に行ってくれる

control+p+qでコンテナから出る

その後$ docker ps -aで一度止めて、
コンテナが作成されているかを確認する(Upなら一度stopしてExitedにしておく)
これからは$docker start [コンテナID]で起動できる

$ docker rename [古いコンテナ名] [新しいコンテナ名]
しておいた方がわかりやすい

正しいバージョンのものが入っているかの確認は起動後
$ docker exec -it [コンテナ名] bash
attachと違うのはコンテナを起動したまま抜けることができるのかできないのかが違うexecは起動したまま抜けることができる
でコンテナに入り、バージョン確認...

MySQLが起動しない...

先人様がいらっしゃいました。ありがとうございます。↓
https://qiita.com/takepan/items/0cbf13af3a0bb2c243ab

よしこれで確認できた

...でどうやってつなげるん??

Docker Composeとは

複数のコンテナを組み合わせてシステムを構成するための仕組みに用いるのがDocker Composeと呼ばれるもので、予めコンテナの起動方法やボリューム、ネットワークの構成などが書かれている

こんなものがあるのか、今まで一つのコンテナを独立させて動かしていたので、全く知りませんでした...

事前知識でDockerネットワークやマウントのことを知らなければならないとのことで書籍を借りて軽く頭に入れておきました。
全然知らないままDockerを使っていたのだなと反省

そしてこれを書いていく...docker-compose.ymlを作ってバージョン決めて、サービスの中身にnode.jsとmysql使いますよってこととかそれぞれの設定など、先人のymlファイルを参考にゴリゴリ書いていく...

書き方を丁寧に載せてる先人様の記事はこちらです。ありがとうございます。↓
https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

かけたら、docker-compose up で起動
しばし待つ

...しばし待つ

終わらねえ

db  | Version: '5.7.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

ここで止まって一向に動かない...

仕方ないので、control+cで一度抜けました

docker-compose psで確認すると動いといて欲しいdb(mysql)が動いてない...

一か八かでdocker start dbを試すと...

stateがExitからUpに
一件落着

ていうかこのやり方だと最初にコンテナは立ち上げなくても、なんならimageもpullしてこなくて急にdocker compose書いてあげた方がよかったのね...

じゃあ他のコンテナもたてます
今回はフロント、バック、dbの三つのコンテナを用意します。

docker-compose start

動かない...

それもそのはず、docker-composeに必要なコマンドを書いてなかったからなんですね
いやymlファイルに書くコマンド全然わからん...ってなった僕はとりあえずdocker-compose run [コンテナ名] bashで中に潜り込んで、reactの環境を作ることに...

node -v,npm -vでバージョンを確認
npm install -g create-react-appでcreate-react-appをインストール

create-react-app [プロジェクトを入れるディレクトリ名]
しばしまつ...

Happy hacking!これで完了

(docker-compose run [コンテナ名] bashで中に潜り込んで作ったせいで、docker-compose upでローカルに作られたディレクトリの中に[プロジェクトを入れるディレクトリ名]のディレクトリができてしまったので削除しておく)

では改めて...docker-compose start

ンンンン?

stateがExitから変わらない...
全部docker-composeに書いてるはずなんだけどな...

ダメそうなので、docker-composeでdockerfileを参照することにする
docker-composeでimageを直接引っ張ってきてた部分をbuildで参照し、コマンドを書いたり〜、作業するディレクトリを書いたり〜

よしこれで、わかりやすくなった気がする
docker-compose start

はい、ダメー

どうすればいいのだ...と助けを求めると、
docker-compose upで立たない?
って言われハッとした

そういえば...

かけたら、docker-compose up で起動
しばし待つ
...しばし待つ
終わらねえ
db | Version: '5.7.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
ここで止まって一向に動かない...
仕方ないので、control+cで一度抜けました

これが原因じゃないの

ってことでもう一度
docker-compose up
...
Compiled successfully!

動いた!!!!

ということで無事コンテナが起動し、localhost:3000にアクセスすると、reactがくるくるしとる!

stopしてからのstartでも起動できることが確認できた
よかったよかったこれでフロント(react)とdb(mysql)が動いた。

次はバック(express)のコンテナを立てるぞ

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

yps並走備忘録 Task2 MySQL(5.7)~nginx(v1.18)~PHP(7.3)~Laravelインストール

yps Task 2 アプリを動かす準備

今回の流れ
1. MySQLインストール
2. Nginxインストール
3. PHPインストール
4. Laravelインストール
5. VS CodeでSSH接続してサーバーにあるファイルを編集

-----用意するもの-----
VS Code
折れない心(笑)

MySQL5.7のインストール&設定

アプリでデータベース管理を司るMySQLをインストール、設定していきます。

まずはインストール

sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
sudo yum install -y mysql-community-server -y

動作確認

mysqld --version
(正常に完了していればMySQLの情報が表示される)

sudo systemctl enable mysqld(MySQLを自動で起動する設定)
sudo systemctl start mysqld (MySQLを起動)
sudo systemctl status mysqld (MySQLの状態を確認、起動できていれば「active(Running)」という緑の文字が出てくるはず)
sudo systemctl stop mysqld (一旦MySQLを停止)

MySQLへログイン・パスワード変更・文字コードを設定

sudo cat /var/log/mysqld.log | grep -i root (仮で設定されたパスワードを表示、root@localhost: xxxxxxと表示されるはず)
sudo systemctl start mysqld
mysql -u root -pと打つとPassword:という表示になる、ここで上記の仮パスワードを入力するのですが、Linuxの仕様で入力しても何も表示されないので注意!
ミスタイプがないように打って、Enterを押すと、正しい場合はMySQLに入れ、表示がmysql>となるはず。

パスワード変更

SET PASSWORD = PASSWORD('パスワードをここに入力')
-------------注意事項-------------
- 8文字以上、英字の大文字・小文字・数字・記号を全て混ぜないといけない
- #はエラーに基になるので使用しない

変更できたらexitと打つとサーバーのターミナルへ戻れる

日本語を扱えるように文字コードを変更

sudo vi /etc/my.cnf

最終行にcharacter-set-server=utf8mb4を追記

sudo systemctl restart mysqld(MySQLを再起動して設定を反映)
mysql -u root -p(MySQLにログイン)
Password:設定したパスワード

mysql> show variables like "chara%";(文字コードの設定が反映されているか確認)

MySQLのインストールここまで


Nginxのインストール&設定

補足:nginxとは? 参考url:

インストール

1. インストール用のyumレポジトリ作成
sudo vi /etc/yum.repos.d/nginx.repo
開いたファイルに以下を記述
[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

2. 以下のコマンドを打ってインストール
sudo yum install nginx -y

完了したらバージョンを確認
nginx -v

nginxを自動で起動できるように設定
sudo systemctl enable nginx

3. AWSマネジメントコンソールからインバウンドルールにhttp、httpsポートを追加
http = 80
https = 443

nginxを再起動して設定を反映
sudo systemctl nginx

ブラウザにEC2インスタンスのIPを入れてWelcome to Nginxが表示されればインストール完了

4. nginxのrootディレクトリ変更
sudo mkdir /var/www wwwディレクトリを作成
sudo mkdir /var/www/html wwwディレクトリの中にhtmlディレクトリを作成
sudo chown -R centos:nginx /var/www /var/www以下の権限をcentosからnginxに移譲

5. nginxの設定変更
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.org 元々の設定をorgファイルでバックアップ保存
sudo vi /etc/nginx/conf.d/default.conf 設定ファイルを編集

--------編集する場所----------
rootのパスを変更
#root /usr/share/nginx/html;  ⇒ root /var/www/html;

Nginx構文チェック
sudo nginx -t 何も表示されなければOK!

Nginxを再起動
sudo systemctl restart nginx

ブラウザで再度EC2のIPアドレスを開いて(or更新して)403エラーになっていればOK

nginxのインストール&設定ここまで


PHP 7.3のインストール&設定

お次はいよいよPHPを動かせるように必要なものをインストールしていきます

1. yum レポジトリのインストール&アップデート

EC2にインストールするためのプログラムが古いのでアップデートします。
sudo yum install epel-release -y
sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm -y
sudo yum update -y

2. PHPのインストール

sudo yum -y install --enablerepo=epel,remi,remi-php73 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt php-fpm php-mysql php-mysqlnd zip unzip

バージョンの確認
php -vで以下が表示されればOK

PHP 7.3.20 (cli) (built: Jul 7 2020 07:53:49) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.20, Copyright (c) 1998-2018 Zend Technologies

3. PHPとNginxを連携させます

php-fpmの設定

sudo cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.org 恒例、元のファイルバックアップ
sudo vi /etc/php-fpm.d/www.conf 設定ファイル編集

変更する場所
user = nginx
group = nginx
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

php-fpmの設定ここまで


Nginxの設定

sudo vi /etc/nginx/conf.d/default.conf

まずは10行目くらいにあるindexのところに追記します
index index.php(←追記) index.html index.htm;
そのすぐ下に下記も追記
try_files $uri $uri/ /index.php?$query_string;

さらにlocation / 以下に下記を追記します
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

終わるとこんな感じ
image.png

上記連携が終わったら…

配下のディレクトリもnginxへ所有者変更(使えるようにする)
sudo chown -R centos:nginx /var/www/ /var/www/

php-fpmの自動起動
sudo systemctl enable php-fpm

nginx再起動
sudo systemctl restart nginx

php-fpm起動
sudo systemctl start php-fpm

ここまでできればあとちょっと!

テスト表示用のindex.phpファイルを作成
vi /var/www/html/index.php

ファイルに以下を記述
<?php echo phpinfo();?>

:wqで保存したらnginxとphp-fpmを再起動
sudo systemctl restart nginx
sudo systemctl restart php-fpm

ブラウザを更新してPHPのバージョン情報が見られれば完了です


Laravelのインストール&設定

一時フォルダに移動

cd/tmp

Laravelのインストールに必要なComposerをインストール

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

Composerがどこでも使えるようにします

sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer

Laravelを構築します

cd /var/www/html
composer create-project --prefer-dist laravel/laravel yps ※ypsの部分はもちろん任意の名前でOK

※phpをインストールした時にzip unzipがちゃんとインストールされていないとここで躓く可能性があります

無事Laravelの構築が終わったら設定をしましょう

cd yps Laravelのフォルダへ移動
php artisan key:generate composerでlaravelアプリ用の暗号化キーの生成
cp -p .env.example .env
.envファイルの下記の部分を変更します
APP_URL= EC2のIPアドレス
DB_PASSWORD= MySQLのパスワード

node.jsとnpm(パッケージ管理システム)をインストール

多分後日フロント周りをいじるとき用…かな?
sudo yum install npm node -y
composer install
npm install

下記のコマンドを打てば設定は一段落

sudo chorn-R centos:nginx /var/www/
sudo chmod -R 777 storage/ bootstrap/cache/

laravelのWelcome画面表示

vi /etc/nginx/conf.d/default.conf

/var/www/html;
となっているところを
/var/www/html/yps/public;
に変更して…

nginxとphp-fpmを再起動
sudo systemctl restart nginx
sudo systemctl restart php-fpm

最後にEC2インスタンスのIPアドレスをブラウザに入力すればLaravelのWelcome画面が見られるはずです。

さらにここからVS Codeで編集できるようにします

  1. VS Codeを起動して、拡張機能のRemote-SSHをインストール
  2. 左の「リモートエクスプローラーアイコンをクリック」
  3. SSH TARGETSと書いてあるところにカーソルを合わせると出てくる歯車アイコンをクリック
  4. 画面中央上部にSelect SSH configuration file to updateと出るのでC:\users\ユーザー名.ssh\configをクリック
  • Host: 表示名、後ほどコマンドプロンプトからSSH接続をするのにも利用できる
  • Port: AWSで作成したPort番号
  • User: centos
  • HostName: EC2のIPアドレス
  • IdentifyFile: .ssh/xxxx.pem(秘密鍵ファイル)
  1. 入力後に右下の緑色の「リモートウインドウを開く」をクリック
  2. Remote-SSH Connect to Host...をクリック
  3. 上記で作成した表示名をクリック
  4. 画面中央上部にLinux, Windowsとか選択肢が3つくらい出てくるのでLinuxを選択
  5. しばらくするとVS Code Serverが立ち上がる
  6. 完了すると右下にHost名が出る
  7. エクスプローラを開いてresources ⇒ views ⇒ welcome.blade.phpを開く
  8. 84行目にあるウェルカムメッセージを変更して保存
  9. ブラウザをリロードするとウェルカムメッセージが更新されている(ハズ)

以上でTask2完了です。

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

PHPにおけるページネーションの方法

初投稿です。
PHPのページネーションに関して、以前実装したものの知識が抜けていたので、アウトプットがてら復習したいと思います。何かのお役に立てれば幸いです。

要件
・各ページで5つずつ表示する
・ページの前後には「前へ」「次へ」を表示。複数ページある場合はリンクになり、それぞれのボタンを押すと前後のページへジャンプする
・ページ番号は5つまで表示。基本的に現在表示されているページの前後2つを表示させる
・ページ数が表示されてる部分にあわせて「○件中○〜○件目の商品」と記載する

なお、今回はLaravelなどのフレームワークは使わずに、生のPHPで実装します。

イメージとしてはこんな感じです。

スクリーンショット 2020-07-27 22.36.07.png

DB関連

function get_db_connect(){
  $dsn = 'mysql:dbname='. DB_NAME .';host='. DB_HOST .';charset='.DB_CHARSET;

  try {
    $dbh = new PDO($dsn, DB_USER, DB_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  } catch (PDOException $e) {
    exit('接続できませんでした。');
  }
  return $dbh;
}


function fetch_all_query($db, $sql, $params = array()){
  try{
    $statement = $db->prepare($sql);
    $statement->execute($params);
    return $statement->fetchAll();
  }catch(PDOException $e){
    set_message('データ取得に失敗しました。');
  }
  return false;
}

①modelで必要な要素をselectで抽出する

$db = get_db_connect();

function get_items_list($db, $limit = 5, $offset = 0){
  $sql = '
    SELECT
       --selectする要素を記載
    limit ?
    offset ?';

  return fetch_all_query($db, $sql, array($limit, $offset));
}

このとき、$limit=5で表示させる件数を予め限定させておく。

また、全体の件数も知っておきたいので、countを使って実装。

function get_items_count($db) {
  $sql = '
    SELECT
        count(*)
    FROM
        テーブル名'

    $result = fetch_all_query($db, $sql);

    return $result[0]['count(*)'];
}

②view画面の実装

<?php 

foreach($items as $value) {

--ここにget_items_list関数から表示させたいアイテムを表示

} 

echo $items_count. '件中'.$page_ini. "〜" .$page_fin. "件目の商品";

// リンクをつけるかの判定
if($now > 1){ 
    print '<a href=\'../html/〜.php?page_id='.($now - 1).'\')>前へ</a>'. ' ';
} else {
    print '前へ'. ' ';
}

for($i = 1; $i <= $max_page; $i++){
    if($i >= $now - $range && $i <= $now + $range) {
        if ($i == $now) {
            print '<a class="current_page" href=\'〜.php?page_id='.$now.'\')>'. $now. '</a>'. ' ';
        } else {
            print '<a href=\'../html/〜.php?page_id='.$i. '\')>'. $i. '</a>'. ' ';
        }
    }
}
// リンクをつけるかの判定
if($now < $max_page){ 
    print '<a href=\'../html/〜.php?page_id='.($now + 1).'\')>次へ</a>'. ' ';
} else {
    print '次へ';
}
?>

まず、〜件中○〜○件目の商品の部分から。

$items_countに関しては、modelで記述したget_items_count関数を使って表示させます。

page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、getで取得するページidによって、offsetの値が定義され、それにより表示されるページが変わるといった感じ。

「前へ」「次へ」に関しては、クリックするとgetしたページid+1がgetで渡される。

表示されるページの数に関しては、for文にて表示。

$rangeに関しては、ページidが1、もしくは最後のページのときは4、id=2、最後のページから1つ前のときは3、それ以外は2となるように設定しています。

//ページネーションの表示数
if((int)$now === 1 || (int)$now === (int)$max_page) {
    $range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
    $range = 3;
} else  {
    $range = 2;
}

③controllerの記載

viewで指定した変数をそれぞれ定義する。

if(get_get('page_id')) {
  $now = $_GET['page_id'];
} else {
  $now = 1;
}

$offset = ($now - 1) * 5;

$items = get_items_list($db, $limit = 5, $offset);

$items_count = get_items_count();

$max_page = ceil($items_count / 5);

$page_ini = ($offset + 1);

if(count($items) === 5) {
  $page_fin = ($offset + 5);
} else {
  $page_fin = $items_count;
}

if((int)$now === 1 || (int)$now === (int)$max_page) {
    $range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
    $range = 3;
} else  {
    $range = 2;
}

まずGETで受け取ったページidを定義する(get_getはユーザー定義関数)

//viewからのidをgetしたとき
if(get_get('page_id')) {
  $now = $_GET['page_id'];
} else {
  //設定されてない場合は1ページ目にする
  $now = 1;
}

定義したら、その変数($now)を使ってoffsetを定義する

//ここでoffsetの定義
$offset = ($now - 1) * 5;

modelで実装したselect文もここで定義しておく。

$items = get_items_list($db, $limit = 5, $offset);
$items_count = get_items_count();

ceil関数を使って、小数点になる場合は繰り上げを行う。

$max_page = ceil($items_count / 5);

前述の通り、page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、offsetの値により表示されるページが変わる。

//最初
$page_ini = ($offset + 1);

//最後(1ページに表示されるアイテム数が5つの場合とそうでない場合で条件分岐)
if(count($items) === 5) {
  $page_fin = ($offset + 5);
} else {
  $page_fin = $items_count;
}

あとはLaravelでもページネーションを実装してみたいな。

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

Mysql2::Error::ConnectionErrorが出た場合

localhost:3000で出たエラーを解決させました

自作アプリの開発中に起きたエラーを紹介します。

環境

・macOS
・Rails 5.2.4.3
・Ruby 2.5.1

今日(投稿日)はエンゼルスの大谷投手が693日ぶりに登板と言う事で、めちゃくちゃテレビを見たい気持ちを抑えて、いつも通りの朝活を行う事に。。。

そして、自作アプリを開くとこんな画面に遭遇しました。
スクリーンショット 2020-07-27 7.32.29.png

へ?

何だこれは??

一瞬頭が真っ白になってしまいました。

なかなか自作アプリ開発が思う様に進まない中で、もはや自分でアプリを見ることすら出来ないのかと愕然。

5分くらい絶望した後に、取り敢えずエラーの解析から始めました。

Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)って何??

エラーの内容を調べていると結構同じ様なエラーに遭遇されている方が多かったので、その記事を見ていくと、

クライアント(自分のPC) → /var/lib/mysql/mysql.sock にデータを見に行こうとしたら、そんな場所ないじゃん。って感じのエラーなんだと理解。

socketとは

プログラムとネットワークを結ぶ接続口。仲介役。仲介業者。仲人。合コンで言う幹事。
14102808098_o.jpg

って事で正しい出入り口(ソケット)を探す旅に

socketってどこにあんの??

他の記事を読み漁り、socketの存在を調べました

特に参考にさせてもらった記事
Can't connect to local MySQL server through socket '/tmp/mysql.sock'

記事を読み比べる中で

'/tmp/mysql.sock'
'/var/lib/mysql/mysql.sock' 

と言う2つのソケットを見比べて、

「自分のエラーの場合は'/var/lib/mysql/mysql.sock'に行こうとしたが、そんな場所はないと言われているので、そこを見つけて修正すれば良いのか!!」と推測。

で、どこに書いてあんの?

解決法

この記事を読んで私も解決しました
【Rails】ローカル環境におけるmysql接続エラー対処法【Can't connect to local MySQL server through socket】

database.yml
#修正前
development:
  <<: *default
  database: データベース名_development
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

#修正後
development:
  <<: *default
  database: データベース名_development
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /tmp/mysql.sock

/var/lib/mysql/mysql.sock → /tmp/mysql.sock に変更してます

コードの修正を行ったので、再起動させます。

rails s

これでソケット名が正しくなったので、無事に閲覧が出来ました!!

原因

database.ymlですが、特に自分で何かを記述した訳ではなくて、何かしらの教材や記事を
コピペしてしまう事で、起きやすい事象なのかと思いました。
その分、最初はすごく焦りましたが、今まで気にしなかった所を考えたり、エラー文を調べていく中で、同じ様なエラーに遭遇されている方が多かった事も、自分の中では収穫でした。ymlを一度見てもらうのも良いかも知れません。

最後にsocketの

'/tmp/mysql.sock'
'/var/lib/mysql/mysql.sock' 

の箇所ですが、使われている方によっては、

/tmp/mysql.sock → /var/lib/mysql/mysql.sock

が正解のパターンも多くあると思いますので、まずは自身のsocketの所在を確認してみてください!!

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

Equalumがやって来た!(余談編・・)

唐突ですが、今回はリアルタイム・ストリーミングで流れ作業の匿名化処理を検証してみます!

お陰様で個人的に幾つかEqualumに関する質問等を頂けるようになり、その中でデータの一部のカラム情報に関して、全自動で匿名化処理(アスタリスク列等に置き換える)は出来る??・・・という内容がありました。

今回の検証では、極めてシンプルで単純な方法ですが、リアルタイムで連続挿入されてくるデータの「特定のカラム情報を全て自動的に」アスタリスク10個の文字列に置き換える作業を行ってみたいと思います。

イメージとしては、Equalumのエージェントが遠隔で稼働中のデータソースに加えられた操作を検出し、CDC+kafka/Spark連携を駆使したリアルタイム・ストリーミング処理でそのメッセージをターゲット側に伝える際に、そのメッセージの一部(今回の匿名処理対象)を自動的に特定の情報(10個のアスタリスク)に置き換えて送る・・という感じになります。

ポイントは、纏めてドン!のバッチ系で処理をするのではなく、オリジナルに対象データが挿入されたタイミングで高速変換を自動的に実施し、ターゲット側のデータベースにリアルタイムで反映させる・・・という作業を、Equalum得意のプログラム無しで実現してみるという点になるかと思います。

では、一気に匿名化処理の検証を実施します!!

最初の作業は、今まで実施してきた検証と同じく上流側のデータソースに対して、ストリーミング処理を定義する事から始めます。ここでEqualum内部でのkafka/Spark処理連結が「プログラム無し」で行われ、以降の各種データ処理に対してCDCを最大活用したリアルタイム・ストリーミング処理を提供する事が出来るようになります。kafkaとの連携を実施する為に、ユニークな名称を設定するだけでOKです。
a1.jpg

まず始めに、データが挿入される上流側のデータソースを設定します。先ほどの手続きで準備済みのデータソース(トピック)を選択します。
a2.jpg

次に編集メニューからトランスフォームを選択します。
a3.jpg

匿名化の設定は非常に簡単で、上流側のデータベースに入ってきたデータの「特定のカラム」を全てアスタリスク10個で置き換えるようにトランスフォームを設定するだけです。今回の検証では、識別しやすいように変換後のカラム名に対して「AN_」を頭に付ける事にしました。またその際の処理はシンプルにダブルクォーテーションで囲ったアスタリスク列でOKです。
a5.jpg

今回の匿名化作業に必要な置き換え用のカラム情報の設定が完了しました。(表の下側に纏めておきました)
a6.jpg

メニューからターゲット側のデータソースを選択して、着地側の必要情報を設定します。
a7.jpg

以前の検証で行った様に、最終のターゲットテーブルに対する必要な設定を行います。今回の匿名化検証では最後の「マッピング」設定が肝になりますので、以下はその部分にフォーカスして手順を紹介します。
a8.jpg

最後にターゲット側のテーブルに対する、流し込み対象のカラム情報のマッピングを行います。1:1の様なケースでは、何も確認せずにそのまま「OK」ボタンを選択すれば良いのですが、今回の匿名化処理では事前に定義した幾つかの項目に対しての、最終テーブル上の各カラムに向けたマッピング変更を行わなければなりません。
a9.jpg

まずは、カード番号の情報を先ほど設定したカラムに置き換えます。
a10.jpg

全てのマッピングを適切に匿名化側の情報に向けて設定変更します。この辻褄が合えばEqualum的にはリアルタイム・ストリーミング処理で匿名化を実行しながら、最終段に設定されているターゲットのデータベース上の所定のテーブルに、リアルタイムで順次着地させていきます。このマッピング作業は、Equalumを活用するうえで重要なチェック項目になりますので、他のケースも含めて確実に実施する必要があります。
a11.jpg

今回設定したEqualumのFLOWはこのような感じになります。(間に匿名化の為のTransformを1段挟んだだけの、非常に簡潔明瞭な形です)
a12.jpg

今回検証に使用したスクリプトが、上流側のMySQLに挿入した結果がこちら側になります。形式的には今までの検証で使用している内容になりますので、個人情報(実際はFakerが作りだしている内容になりますが・・・)がそのまま各カラムに入ってきています。
b2.jpg

こちらがEqualumでストリーミング処理を行いながら匿名化を実施した結果になります。綺麗にアスタリスクに置き換わっている事が確認できます。
b1.jpg

Equalumのリアルタイム・ストリーミング処理により、ターゲットデータベース上のテーブルは自動的に必要情報がアスタリスク列に置き換わり、実質的に上流部のオリジナル情報(こちら側はエビデンス側として保全対象)の処理とほぼ同時に、下流側のターゲットデータベース上に対して、必要な情報項目の匿名化が実施済みの形で処理されるようになります。

今回のまとめ

昨今の情報利活用や広域情報共有等の際には、この種の情報匿名化作業が必要になるケースが出てくると思います。Equalumを活用する事で、データを流しながら必要処理を完了させて、ターゲット側に着地させたと同時に利活用や、その後に必要な処理(この場合は複数のテーブル(サイロ化されたデータベースから引き抜かれてくる情報)を跨いだケースが多くなるので、その処理の高速化の為に「インメモリ&スケールアウト型のデータベース」を使う事が増えてきています。これは、Equalumで高速化しても、その後の処理が遅いと投資対効果が極端に悪化するとか、IoT系の仕組みが既存系のデータ待ち状態になって、同じ様に投資対効果を下げる事を避ける意味での採用事例になります。

利活用系のターゲットデータは、今後の活用形態や規模の変化が読みにくいケースが多いので、前述のスケールアウトが可能な物や、クラウド提供されるサービスを活用するケースが増えてくると思います。

既存の現業系データシステムに無用のトランザクション・ロードを追加せずに、Equalumとその着地側のデータソースの柔軟な組み合わせで、「同じ時間帯」で、「同じデータ」に対して「創造的なアプローチを気兼ねなく行える」環境を構築できるのが、Equalumの強みの一つなのではないかと感じました。

謝辞

本検証は、Equalum社の特別の許可を得て実施しています。この貴重な機会を設定して頂いたEqualum社に対して感謝の意を表すると共に、本内容とEqualum社の公式ホームページで公開されている内容等が異なる場合は、Equalum社の情報が優先する事をご了解ください。

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

Node.js+Express+MySQLでWebAPIを作成してみる①

はじめに

NodeでReactを用いてフロントの作業をしていて、せっかくならバックエンドもNodeつかってJavaScriptで作ってみようということでWebApiサーバーを作ってみました。

実行環境

  • CentOS7
  • Node.js 8.17.0

Expressの動作確認

npm install expressでインストール

以下のサンプルソースを任意のフォルダに保存

index.js
var exp = require("express");
var app = exp();

app.get("/",function(req,res){
    res.send("Hello,World");
})

app.listen(3000,function(){
    console.log("成功")
})

保存したフォルダに移動し、node index.jsで実行した後http://localhost:3000/にアクセス。
image.png
サーバーが起動し、GETリクエストのレスポンスが返ってきました。

MySQLの設定

まずはMySQLにログイン。その後
create database ApiTest;
use ApiTest;
create table api_tbl(id int(5),name varchar(10));
insert into api_tbl values(2,'test');
上記のコマンドで、データベースとテーブルを作成、レコードを追加。

データの取得

作成したテーブルデータをGETリクエストで実際に取得してみます。

index.js
var exp = require("express");
var app = exp();

var mysql = require("mysql");
var connection = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "****",
    database: "ApiTest"
});



app.get("/", function (req, res) {
    connection.query('select * from api_tbl', function (error, results, fields) {
        if (error) throw error;
        res.send(results);
    });
});

//任意のポート番号
app.listen(****, function () {
    console.log("成功");
})

上記のソースを保存し、node index.jsを実行。Postmanを使用してレスポンスを確認します。
image.png

先ほど登録したデータがちゃんと返ってきたので成功です。

感想

Expressを使うことでとても簡単にWebApiが作成できて感動しました!
今回は初めてということでGETリクエストのみの実装でしたが、今後CRUDすべてのAPIを実装し、フロント側もReactなどで開発することで1つのWebアプリケーションを作ろうと考えております。

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

Spring Bootで書籍管理Webアプリを作ろう part1

はじめに

どうも、プログラミング勉強中の大学生、@Ikuto19です。今回は勉強がてらにJavaのSpring Bootを使った簡易的な書籍管理webアプリを作ろうと思います。
以前、JavaではなくPythonで作成したんですが個人的に納得のいかない点があったので、作り直そうを思いました。その納得がいかない点というのは下記のようなものです。

  • Pythonはサーバーサイド言語として不向き
  • 無料で自作アプリを公開したい

サーバーサイドのプログラミング言語として使われているのはRuby、Java、PHPの三つが多い気がします。ネットで調べてもこの三つどれかが使われているのが大半みたいです。(個人調べ)

Pythonはサーバーサイドではなく、AIやディープラーニングといったものやデータサイエンスが得意なプログラミング言語です。なのにwebアプリのサーバーサイド言語として使っても、あまり使わないのであれば勉強にならないと思ったので、今回はJavaで作り直すという考えに至ったわけです。あと無料で自作アプリを公開できないかな?と調べた結果、Herokuというサービスがあることを知ったのも理由の一つです。

もし、載せている情報が間違っていたり、説明不足があれば、気にせず指摘してくださって構いません。この記事は自分の勉強のためであり、僕と同じように躓いている人に向けたものです。ですので、よろしくお願い致します。

前提条件

  • macOS Catalina(バージョン10.15.5)
  • Eclipse Version: 2020-03
  • サーバーサイド言語: Java
  • フロントエンド言語: HTML、CSS、Javascript(jQuery)
  • データベース: MySQL(HerokuではclearDBというアドオンからMySQLを使用)
  • Webアプリケーションフレームワーク: Spring FrameworkのSpring boot
  • ビルドツール: maven
  • 書籍管理API: openBD
  • webアプリの公開サービス: heroku

各ツールやプロジェクトについて

Spring Frameworkについて

公式サイト → https://spring.io/
Spring FrameworkはJavaによる開発をスピーディーに安全に開発するためのフレームワークで、Springというふうに読んだりもするみたいです。このSpringは「DI:依存性注入」と「AOP:アスペクト指向プログラミング」を特徴にもっています。

mavenについて

公式サイト → https://maven.apache.org/
mavenは複数あるビルドツールうちの一つです。他にはGradleやAntがありますが、今回はHerokuに完成したアプリをデプロイするのでmavenを選びました。pom.xmlに依存関係を記述することで、いろんなパッケージを扱えるようになります。

openBDについて

公式サイト → https://openbd.jp/
このopenBDは書誌情報や表紙を誰でもアクセスできる無料のAPIです。
今回はjavascriptのjQueryでこのAPIを使って書籍情報にアクセスします。

herokuについて

公式サイト → https://jp.heroku.com/about
コンテナベースのクラウド型PaaSで、多数のプログラミング言語から選んでき、自作アプリをデプロイ・管理することができるサービス。

ツールの導入

インストール済みのeclipseへSpring プロジェクトをインストール

  1. eclipse起動後、ヘルプ > eclipse マーケットプレースからSpring Tools 4(aka Spring Tool Suite 4) 4.7.0.RELEASEをインストール
  2. 全てのチェックボックスにチェックしたまま、確認
  3. 「使用条件の条項に同意します」にチェックを入れて完了
  4. 「再起動しますか?」と聞かれるのでそのまま再起動する。

もし、セキュリティ警告で「信頼性または有効性を確立できない署名されていないソフトウェアをインストールします。インストールを続行しますか?」と表示されたら、インストールボタンをクリック。

Herokuへの登録およびクレカの登録

Herokuでアカウント作成

サインアップ → https://signup.heroku.com/login
1. 上記で必要項目を入力し、アカウント作成
2. 確認メールが来るので、クリックしてパスワードを設定

ここまでできていると、ダッシュボード画面になっていると思います。

MySQL利用のためにクレジットカードの登録

HerokuではデフォルトのデータベースがPostgreSQLなので、MySQLにする際はclearDBという無料のアドオンを追加する必要があります。ですが、そのためにはクレジットカードの登録をする必要があるので、登録します。

  1. ダッシュボード画面から右上端のアイコンからAccount settingsをクリック
  2. BillingタブからBilling Informationの「Add credit card」をクリック
  3. 必要項目を入力して、Save Detailsをクリック

テストアプリの作成・実行とherokuでの公開

テストアプリの作成

一応、作成手順を載せておきますが、GitHubにプロジェクトをあげているので、以下のコマンドダウンロードしてくださっても構いません。

terminal
$ git clone https://github.com/ikuto19/test-webapp.git
作成手順
  1. eclipse起動後、パッケージ・エクスプローラーで右クリック
  2. 新規 > プロジェクトをクリック
  3. Spring BootのSpring スターター・プロジェクトを選択し、「次へ」をクリック
  4. 名前を「webapp-test」、グループとパッケージを「com.app」にして、「次へ」をクリック
  5. 依存関係のテンプレート・エンジンからThymeleafとwebからSpring Webにチェックして、「完了」をクリック

プロジェクトの中身を確認すると、以下の画像のような構成になっていると思います。もし、templatesフォルダがなければ追加で作っておいてください。
スクリーンショット 2020-07-26 16.35.59.png

次に以下の構成で新規のファイルを作成または既存のファイルを削除します。
スクリーンショット 2020-07-27 13.38.23.png

各ファイルの中身は以下のように記述します。

App.java
package com.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
IndexController.java
package com.app.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {

    @GetMapping("/")
    public String getIndexPage(Model model) {
        String message = "Hello, World!!";
        model.addAttribute("message",message);
        return "index";
    }
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8">
<head>
<title>テストアプリ</title>
</head>
<body>
    <p th:text="${message}"></p>
</body>
</html>
Procfile
web: java $JAVA_OPTS -jar target/*.jar --server.port=$PORT

実行確認

パッケージ・エクスプローラーのApp.javaを選択したまま右クリックで、実行 > Spring Bootアプリケーションをクリックして、実行。
webブラウザで http://localhost:8080/ にアクセスすると、下記のような画像が表示される。
スクリーンショット 2020-07-26 17.13.10.png

Herokuへデプロイ

以下のコマンドを順に実行
「heroku login」を実行後に何かキーを押すと、webブラウザにとばされるので、「Log IN」ボタンをクリック

terminal
$ brew tap heroku/brew && brew install heroku
$ heroku login

createコマンドで「Name test-webapp is already taken」のようなエラーが出る場合、アプリ名を変えてください。他の人に使われている見たいなので。僕はアプリ名を「test-webapp01」としました。

terminal
$ cd (eclipseのワークペースがあるパス)/webapp-test
$ git init
$ heroku create test-webapp01
$ git add .
$ git commit -m "first upload"
$ git push heroku master (もしくは git push -f heroku master)

スクリーンショット 2020-07-27 14.37.58.png
このようにBUILD SUCCESSと出ていると、成功していると思います。
以下コマンドで開いて確認してください。今回はここまでにします。

terminal
$ heroku open

終わりに

今回は書籍管理アプリを作るための準備とテストアプリの作成・公開しました。
コードの詳しい説明などは次回以降にやっていく予定で、いよいよ書籍管理アプリを作っていこうと思います。

次回へ続く > Spring Bootで書籍管理Webアプリを作ろう part2

参考サイト

EclipseでSpring Frameworkを利用してみる

Heroku初心者がHello, Herokuをしてみる

Heroku初心者がJavaで作成したWebアプリをGitHub連携でデプロイする時つまずいた4つのこと

SpringBootを使ってWebアプリを作るまでを丁寧に解説

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

Spring Bootで書籍管理Webアプリを作ろうpart1

はじめに

どうも、プログラミング勉強中の大学生、ikuto19です。今回は勉強がてらにJavaのSpring Bootを使った簡易的な書籍管理webアプリを作ろうと思います。
以前、JavaではなくPythonで作成したんですが個人的に納得のいかない点があったので、作り直そうを思いました。その納得がいかない点というのは下記のようなものです。

  • Pythonはサーバーサイド言語として不向き
  • 無料で自作アプリを公開したい

サーバーサイドのプログラミング言語として使われているのはRuby、Java、PHPの三つが多い気がします。ネットで調べてもこの三つどれかが使われているのが大半みたいです。(個人調べ)

Pythonはサーバーサイドではなく、AIやディープラーニングといったものやデータサイエンスが得意なプログラミング言語です。なのにwebアプリのサーバーサイド言語として使っても、あまり使わないのであれば勉強にならないと思ったので、今回はJavaで作り直すという考えに至ったわけです。あと無料で自作アプリを公開できないかな?と調べた結果、Herokuというサービスがあることを知ったのも理由の一つです。

もし、載せている情報が間違っていたり、説明不足があれば、気にせず指摘してくださって構いません。この記事は自分の勉強のためであり、僕と同じように躓いている人に向けたものです。ですので、よろしくお願い致します。

前提条件

  • macOS Catalina(バージョン10.15.5)
  • Eclipse Version: 2020-03
  • サーバーサイド言語: Java
  • フロントエンド言語: HTML、CSS、Javascript(jQuery)
  • データベース: MySQL(HerokuではclearDBというアドオンからMySQLを使用)
  • Webアプリケーションフレームワーク: Spring FrameworkのSpring boot
  • ビルドツール: maven
  • 書籍管理API: openBD
  • webアプリの公開サービス: heroku

各ツールやプロジェクトについて

Spring Frameworkについて

公式サイト → https://spring.io/
Spring FrameworkはJavaによる開発をスピーディーに安全に開発するためのフレームワークで、Springというふうに読んだりもするみたいです。このSpringは「DI:依存性注入」と「AOP:アスペクト指向プログラミング」を特徴にもっています。

mavenについて

公式サイト → https://maven.apache.org/
mavenは複数あるビルドツールうちの一つです。他にはGradleやAntがありますが、今回はHerokuに完成したアプリをデプロイするのでmavenを選びました。pom.xmlに依存関係を記述することで、いろんなパッケージを扱えるようになります。

openBDについて

公式サイト → https://openbd.jp/
このopenBDは書誌情報や表紙を誰でもアクセスできる無料のAPIです。
今回はjavascriptのjQueryでこのAPIを使って書籍情報にアクセスします。

herokuについて

公式サイト → https://jp.heroku.com/about
コンテナベースのクラウド型PaaSで、多数のプログラミング言語から選んでき、自作アプリをデプロイ・管理することができるサービス。

ツールの導入

インストール済みのeclipseへSpring プロジェクトをインストール

  1. eclipse起動後、ヘルプ > eclipse マーケットプレースからSpring Tools 4(aka Spring Tool Suite 4) 4.7.0.RELEASEをインストール
  2. 全てのチェックボックスにチェックしたまま、確認
  3. 「使用条件の条項に同意します」にチェックを入れて完了
  4. 「再起動しますか?」と聞かれるのでそのまま再起動する。

もし、セキュリティ警告で「信頼性または有効性を確立できない署名されていないソフトウェアをインストールします。インストールを続行しますか?」と表示されたら、インストールボタンをクリック。

Herokuへの登録およびクレカの登録

Herokuでアカウント作成

サインアップ → https://signup.heroku.com/login
1. 上記で必要項目を入力し、アカウント作成
2. 確認メールが来るので、クリックしてパスワードを設定

ここまでできていると、ダッシュボード画面になっていると思います。

MySQL利用のためにクレジットカードの登録

HerokuではデフォルトのデータベースがPostgreSQLなので、MySQLにする際はclearDBという無料のアドオンを追加する必要があります。ですが、そのためにはクレジットカードの登録をする必要があるので、登録します。

  1. ダッシュボード画面から右上端のアイコンからAccount settingsをクリック
  2. BillingタブからBilling Informationの「Add credit card」をクリック
  3. 必要項目を入力して、Save Detailsをクリック

テストアプリの作成・実行とherokuでの公開

テストアプリの作成

一応、作成手順を載せておきますが、GitHubにプロジェクトをあげているので、以下のコマンドダウンロードしてくださっても構いません。

terminal
$ git clone https://github.com/ikuto19/test-webapp.git
作成手順
  1. eclipse起動後、パッケージ・エクスプローラーで右クリック
  2. 新規 > プロジェクトをクリック
  3. Spring BootのSpring スターター・プロジェクトを選択し、「次へ」をクリック
  4. 名前を「webapp-test」、グループとパッケージを「com.app」にして、「次へ」をクリック
  5. 依存関係のテンプレート・エンジンからThymeleafとwebからSpring Webにチェックして、「完了」をクリック

プロジェクトの中身を確認すると、以下の画像のような構成になっていると思います。もし、templatesフォルダがなければ追加で作っておいてください。
スクリーンショット 2020-07-26 16.35.59.png

次に以下の構成で新規のファイルを作成または既存のファイルを削除します。
スクリーンショット 2020-07-27 13.38.23.png

各ファイルの中身は以下のように記述します。

App.java
package com.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
IndexController.java
package com.app.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {

    @GetMapping("/")
    public String getIndexPage(Model model) {
        String message = "Hello, World!!";
        model.addAttribute("message",message);
        return "index";
    }
}
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8">
<head>
<title>テストアプリ</title>
</head>
<body>
    <p th:text="${message}"></p>
</body>
</html>
Procfile
web: java $JAVA_OPTS -jar target/*.jar --server.port=$PORT

実行確認

パッケージ・エクスプローラーのApp.javaを選択したまま右クリックで、実行 > Spring Bootアプリケーションをクリックして、実行。
webブラウザで http://localhost:8080/ にアクセスすると、下記のような画像が表示される。
スクリーンショット 2020-07-26 17.13.10.png

Herokuへデプロイ

以下のコマンドを順に実行
「heroku login」を実行後に何かキーを押すと、webブラウザにとばされるので、「Log IN」ボタンをクリック

terminal
$ brew tap heroku/brew && brew install heroku
$ heroku login

createコマンドで「Name test-webapp is already taken」のようなエラーが出る場合、アプリ名を変えてください。他の人に使われている見たいなので。僕はアプリ名を「test-webapp01」としました。

terminal
$ cd (eclipseのワークペースがあるパス)/webapp-test
$ git init
$ heroku create test-webapp01
$ git add .
$ git commit -m "first upload"
$ git push heroku master (もしくは git push -f heroku master)

スクリーンショット 2020-07-27 14.37.58.png
このようにBUILD SUCCESSと出ていると、成功していると思います。
以下コマンドで開いて確認してください。今回はここまでにします。

terminal
$ heroku open

終わりに

今回は書籍管理アプリを作るための準備とテストアプリの作成・公開しました。
コードの詳しい説明などは次回以降にやっていく予定で、いよいよ書籍管理アプリを作っていこうと思います。

次回へ続く > 近々投稿

参考サイト

EclipseでSpring Frameworkを利用してみる

Heroku初心者がHello, Herokuをしてみる

Heroku初心者がJavaで作成したWebアプリをGitHub連携でデプロイする時つまずいた4つのこと

SpringBootを使ってWebアプリを作るまでを丁寧に解説

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

Railsのmysql接続でユーザー権限がなくconnection errorになるときの対処法

ユーザー作成

CREATE USER 'test-user'@'localhost';

ユーザー確認

SELECT user, host FROM mysql.user;

権限確認

SHOW GRANTS;

権限付与

grant all on *.* to 'test-user'@'localhost';
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gRPC, Spring Boot, Kotlin,MySQLで作ったSNSアプリ(通話、チャット)のAPIサンプル

どんなアプリのAPIか。

  • チャット、通話機能があるSNSアプリのAPIです。
  • ユーザー登録、プッシュ通知、ブロック・通報機能などのsnsアプリに必要な一通りのAPIを実装しています。

システムの構成

  • フレームワーク:Spring Boot
  • 言語:Kotlin
  • API:Protocol Buffersで定義、gRPCで実装。
  • DB:MySQL

コード

https://github.com/yusuke-imagawa/talking-sns-api-sample

コメント

  • gRPC, Protocol Buffersがどんなものかは他に沢山情報があるので省略します。
  • 画像ファイルのアップロードはこのサンプルに含みません。
  • iOSプッシュ通知の用のp8ファイルや、その他の認証用の文字列は無効なものになっています。

APIの一覧

アカウント

  • ユーザー登録
  • プロフィール編集
  • 退会

ユーザー情報:

  • ユーザーのリスト取得
  • 指定したidのユーザーを取得

通話

  • 通話を開始。(電話を掛ける)
  • 通話を受ける。
  • 通話を切る。
  • 通話が継続していることを記録。
  • 通話のステータス受信(開始、通話中、終了)

チャット

  • メッセージ送信
  • メッセージ受信
  • すべてのメッセージを取得

プッシュ通知

  • デバイストークン_iOS / 登録, 更新
  • ON/OFF更新

その他

  • ユーザーをブロック
  • ユーザーを通報

Protocol BuffersによるAPI仕様定義

API(gRPC)のコントローラークラス

https://github.com/yusuke-imagawa/talking-sns-api-sample/tree/master/src/main/kotlin/com/talking/api/grpc

build.gradle: protoファイルから、APIのソースを生成

https://github.com/yusuke-imagawa/talking-sns-api-sample/blob/master/build.gradle

group 'com.talking'

// gRPCのコード生成コマンド: ./gradlew generateProto

// ドキュメント: gRPCの実装
// https://github.com/LogNet/grpc-spring-boot-starter

buildscript {
    ext.kotlin_version = '1.3.61' // Required for Kotlin integration
    ext.spring_boot_version = '2.2.0.RELEASE'
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // Required for Kotlin integration
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" // See https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support
        classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version"

        classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.5"
    }
}

apply plugin: 'kotlin' // Required for Kotlin integration
apply plugin: "kotlin-spring" // https://kotlinlang.org/docs/reference/compiler-plugins.html#spring-support
apply plugin: 'org.springframework.boot'
apply plugin: 'com.google.protobuf'

def grpcVersion = '1.25.0'

repositories {
    mavenCentral()
}

sourceSets {
    main.kotlin.srcDirs += 'src/main/kotlin'
    main.java.srcDirs += 'src/main/java'
    main.java.srcDirs += 'src/main/generated-proto'
}

dependencies {
    compile("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version")
    compile("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version")
    // testCompile('org.springframework.boot:spring-boot-starter-test')

    // for web
    compile("org.springframework.boot:spring-boot-starter-web:$spring_boot_version")
    compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8")

    // for db
    compile("org.springframework.boot:spring-boot-starter-data-jpa:$spring_boot_version")
    runtime("mysql:mysql-connector-java:8.0.15")

    compile("org.springframework.boot:spring-boot-starter-security:$spring_boot_version")

    // grpc
    compile("io.github.lognet:grpc-spring-boot-starter:3.5.0")
    compile "io.grpc:grpc-api:${grpcVersion}"
    compile "io.netty:netty-codec-http2:4.1.42.Final"
    compile "io.grpc:grpc-core:${grpcVersion}"
    compile "io.grpc:grpc-protobuf:${grpcVersion}"
    compile "io.grpc:grpc-stub:${grpcVersion}"

    // cache
    compile(group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '2.8.1')
    // iOSプッシュ通知
    compile(group: 'com.eatthepath', name: 'pushy', version: '0.13.11')

}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:3.5.0"
    }

    plugins {
        grpc {
            artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
        }
    }

    generateProtoTasks {
        all().each { task ->
            task.builtins {
                java {
                    outputSubDir = 'generated-proto'
                }
            }
            task.plugins {
                grpc {
                    outputSubDir = 'generated-proto'
                }
            }
        }
    }

    generatedFilesBaseDir = "$projectDir/src/"
}

ddl

https://github.com/yusuke-imagawa/talking-sns-api-sample/blob/master/docs/DB/ddl.sql

テーブル

  • ユーザー
  • プロフィール画像
  • チャット
  • 通話履歴
  • 通報
  • ブロック
  • プッシュ通知デバイストークン_iOS

工夫したところ

ログインしているユーザーしか利用できないAPIの認証処理を共通化

AuthInterceptor内でrequestのheader内のtoken,userIdで認証。

https://github.com/yusuke-imagawa/talking-sns-api-sample/blob/master/src/main/kotlin/com/talking/api/grpc/interceptor/AuthInterceptor.kt

@Component
class AuthInterceptor : ServerInterceptor {

    @Autowired
    private lateinit var userService: UserService

    // 参考ソース:
    // https://github.com/saturnism/grpc-by-example-java/blob/master/metadata-context-example/src/main/java/com/example/grpc/server/JwtServerInterceptor.java

    override fun <ReqT : Any?, RespT : Any?> interceptCall(
        call: ServerCall<ReqT, RespT>,
        headers: Metadata,
        next: ServerCallHandler<ReqT, RespT>
    ): ServerCall.Listener<ReqT> {

        val userId = headers.get(GrpcConstant.USER_ID_METADATA_KEY)?.toLong() ?:
                throw StatusRuntimeException(Status.UNAUTHENTICATED, headers)

        val apiToken = headers.get(GrpcConstant.API_TOKEN_METADATA_KEY) ?:
                throw StatusRuntimeException(Status.UNAUTHENTICATED, headers)

        val user = userService.findByIdAndToken(userId, apiToken) ?:
            throw StatusRuntimeException(Status.UNAUTHENTICATED, headers)

        val ctx = Context.current().withValue(GrpcConstant.AUTH_USER_CONTEXT_KEY, user)
        return Contexts.interceptCall(ctx, call, headers, next)
    }
}

認証処理を利用したいAPIのクラスにAuthInterceptorを設定
https://github.com/yusuke-imagawa/talking-sns-api-sample/blob/master/src/main/kotlin/com/talking/api/grpc/AccountGrpcService.kt

@GRpcService(interceptors = [AuthInterceptor::class])
class AccountGrpcService: AccountServiceGrpc.AccountServiceImplBase() {
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLでユーザーを作成するときにパスワードを簡単なものに設定できるようにする

MySQLのバージョン確認

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.19    |
+-----------+

ユーザーを追加する

mysql> create user dbuser01@localhost identified by '6AVAkig2';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

password : 6AVAkig2

ランダムに選んだ文字列。
かつ
数字、大文字、小文字が入っていますが、エラーになります。

mysql> set global validate_password.policy=Low;

これにすれば文字数だけ満たせば大丈夫。
8文字以上なら小文字だけでも大丈夫なはず。

デフォルト値は変更できない

いったんMySQLを終了してからもう一回管理者で入ってユーザーを作成しようとしても、

alidate_password.policyの値がMidiumに戻って、特殊文字も入れないといけない設定に戻っちゃう。困っちゃう。

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