20200524のMySQLに関する記事は11件です。

Django+MySQLのアプリケーションをAWSのElastic Beanstalkにデプロイする (UTokyo Project Sprint 用)

UTokyo Project Sprint 用の記事です。主に、Django Sprint で構築した方を想定して書かれています。

この記事では EB CLI は使用せずに、コンソールからデプロイします。
また、この記事の内容は一例で、もちろんアプリ内で使用するフレームワークや、ライブラリによって異なりますので、適宜自分のプロジェクトに対応させてください。

目次

  1. requirements.txt の修正
  2. Elastic Beanstalkのアプリケーションと環境を作成する
  3. データベースの設定を行う
  4. アプリケーションソースバンドルを準備する
  5. アプリケーションソースバンドルを作成する

0. requirements.txt の修正

requirements.txtDjangomysqlclient のバージョンを以下のように書き換えてください。

requirements.txt
...
Django>=2.1,<2.2
mysqlclient==1.3.12
...

1. Elastic Beanstalkのアプリケーションと環境を作成する

AWS マネジメントコンソール にログインしてください。
ただし、AWS Educate のアカウントからの場合はこの記事を参考にしてください。

Elastic Beanstalk を選び、Create Application からアプリケーションを作成します。

  • アプリケーション情報 > アプリケーション名 : 自身のアプリ名
  • アプリケーションタグ : 任意。
  • プラットフォーム : 今回は、プラットフォームPythonプラットフォームのブランチPython 3.6 running on 64bit Amazon Linuxプラットフォームのバージョン2.9.10 を選択しました。
  • アプリケーションコード : とりあえず「サンプルアプリケーション」を選んでおきます。あとから自分のソースをアップロードします。

[アプリケーションの作成] を押します。あとは自動で環境まで作成してくれるので数分待っておきます。
無事終了したら、その環境のダッシュボードのような画面になると思います。左のメニューの、「環境に移動する」をクリックするとサンプルアプリケーションの画面が出てきます。
出てきたURLの http:// などの部分を除く XXX.YYY.ZZZ.elasticbeanstalk.com が自身のアプリのドメインになります。
あとでこれを使うので控えておいてください。

2. データベースの設定を行う

左のメニューから 設定 を選びます。一番下の データベース の右の 編集 ボタンを押します。
データベース設定 の各欄について以下の選択をします。Amazon RDS DB に作成されます。

  • エンジン : mysql
  • エンジンバージョン : 5.7.22 を選択
  • インスタンスクラス : db.t2.micro を選択
  • ストレージ : 5
  • ユーザー名 : 各自作成して(一応)覚えておいてください。
  • パスワード : 各自作成して(一応)覚えておいてください。
  • 保持期間 : スナップショットの作成
  • アベイラビリティー : 低(1つのAZ)

[適用] を押してください。変更が反映されるまで待っておいてください。

3. アプリケーションソースバンドルを準備する

ここから主にローカルでの作業に移ります。以下、cms というアプリを作成している前提で進めているで、適宜自分のアプリ名に置き換えてください。
最初に、このセクションをすべて終えたときに出来上がるディレクトリ構造の一例を以下に示します。適宜参考にしてください。

├─ .ebextensions         # Added
│  └─ python.config      # Added
├─ requirements.txt
├─ manage.py             # Updated
├─ cms
│  ├─ management         # Added
│  |  ├─ commands        # Added
|  |  |  ├─ createsu.py  # Added
|  |  |  └─ __init__.py  # Added
|  |  └─ __init__.py     # Added
│  ├─ templates
|  ︙
│  └─ views.py
├─ config
│  ├─ __init__.py
│  ├─ settings           # Added (settings.py removed)
|  |  ├─ common.py       # Added
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
│  ├─ urls.py
│  └─ wsgi.py            # Updated
├─ docker-compose.yml
└─ Dockerfile

3-1. .ebextensions ディレクトリを作成する

Elastic Beanstalk にデプロイする際に必要となるディレクトリです。
プロジェクトのディレクトリ直下に .ebextensions ディレクトリを作成し、その中に python.config というファイルを作成してください。そのファイルに、以下を書き込んでください。一例なので、適宜書き換えてください。

なお、このファイルのインデントはtabだとエラーが出るので必ずspaceを使用してください。(コピペするとtabになると思うので、spaceに直してください。)

.ebextensions/python.config
container_commands:
  01_migrate:
    command: 'python manage.py migrate'
    leader_only: true
  02_collectstatic:
    command: 'python manage.py collectstatic --noinput'
  03_createsu:
    command: 'python manage.py createsu'
    leader_only: true

option_settings:
  'aws:elasticbeanstalk:application:environment':
    DJANGO_SETTINGS_MODULE: 'config.settings.production'
    PYTHONPATH: '$PYTHONPATH'
  'aws:elasticbeanstalk:container:python':
    StaticFiles: '/static/=www/static/'
    WSGIPath: 'config/wsgi.py'

以下、上記の内容の解説です。

3-1-1. container_commands

01_migrate ではマイグレーション
02_collectstatic 静的ファイルの処理
03_createsu スーパーユーザーの作成
のコマンドを実行しています。なお、03_createsupython manage.py createsu については後述します。

3-1-2. option_settings

DJANGO_SETTINGS_MODULE の部分で、後ほど作成する、 production.py を読み込むように環境変数を設定しています。
WSGIPathStaticFiles などについては、コンソールの設定のところでも変更可能です。
option_settings について詳しく知りたい方は、以下を参照してください。

3-2. settings.py を分割する

次に、/config/settings.py を、開発用(Local)と本番用(Production)に分割します。
/config/settings.py は、Local 環境と Production 環境で別々のものを読み込む必要があるのですが、毎回書き換えていると大変なので、自動で切り替わるようにします。
具体的には、
1. common.py に Local 環境と Production 環境で共通の設定項目を書き込む
2. local.py は、 common.py の内容に加えて、Local 環境固有の設定項目を書き込む
3. production.py は、 common.py の内容に加えて、Production 環境固有の設定項目を書き込む
4. manage.pywsgi.py を修正する

どちらの環境にも共通している設定項目は、 common.py に書き込みます。

個別に設定すべき内容

Local 環境と Production 環境でそれぞれ固有の設定は例えば以下のようなものです。

  • DEBUG
  • DATABASE
  • ALLOWED_HOSTS
  • MEDIA_ROOT
  • STATIC_ROOT
  • LOGGING

ただし、common.py に書いている設定項目に、local.pyproduction.py で追加したい場合は、例えば以下のようにします。(配列に追加)

INSTALLED_APPS += (
    'django.contrib.admin',
)

3-2-1. common.py, local.py, production.py を作成する

まず、 /config 直下に、 settings というディレクトリを作成し、その中に /config 下の settings.py を移動させ、 common.py にリネームしてください。
また、 /config/settings ディレクトリの中に local.py, production.py の2つのファイルを新規に作成してください。
以下のようなディレクトリ構造になっていることを確認してください。

...
├─ config
│  ├─ settings           # Added
|  |  ├─ common.py       # Added (settings.py をリネームしたもの)
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
...

3-2-2. BASE_DIR を修正する

common.py の最初のほうにある BASE_DIR を以下のように変更してください。

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
...

3-2-3. local.py にLocal 環境固有の設定を書き込む

local.py に、 common.py の内容に加えて、Local 環境で固有の設定項目を書き込みます。
common.py の内容を以下のようにimportします。

/config/settings/local.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。
これを踏まえると、 local.py は例えば以下のようになります。
これはローカルでPostgreSQLを使っていた場合なのですが、各自ローカルで使っていたDBの設定をそのまま移していただいて結構です。

/config/settings/local.py
from .common import *

DEBUG = True

ALLOWED_HOSTS = [
    '0.0.0.0',
    '127.0.0.1',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD': 'somepassword',
    }
}

3-2-3. production.py にProduction 環境固有の設定を書き込む

production.py に、 common.py の内容に加えて、Production 環境で固有の設定項目を書き込みます。
local.py と同様に、 common.py の内容を以下のようにimportします。

/config/settings/production.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。以下の項目は一例です。自身の環境に合わせて、適宜対応してください。

3-2-3-1. DEBUG

Production 環境では、DEBUGFALSE にします。

/config/settings/production.py
...
DEBUG = False

3-2-3-2. ALLOWED_HOSTS

ALLOWED_HOSTS に自身のアプリのドメインを追加します。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
...
ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

3-2-3-3. DATABASES

DATABASES を、本番環境の RDS のものに書き換えます。 'RDS_~' という変数を使えば、Elastic Beanstalk のほうで勝手に書き換えてくれます。
'ENGINE'local.py とは変わっていることに注意してください。

/config/settings/production.py
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ['RDS_DB_NAME'],
        'USER': os.environ['RDS_USERNAME'],
        'PASSWORD': os.environ['RDS_PASSWORD'],
        'HOST': os.environ['RDS_HOSTNAME'],
        'PORT': os.environ['RDS_PORT'],
    }
}

3-2-3-4. STATIC_ROOT

STATIC_ROOT を追加します。

/config/settings/production.py
...
STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

以上を踏まえると、全体として production.py は例えば以下のようになります。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
from .common import *

DEBUG = False

ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.environ['RDS_DB_NAME'],
        'USER': os.environ['RDS_USERNAME'],
        'PASSWORD': os.environ['RDS_PASSWORD'],
        'HOST': os.environ['RDS_HOSTNAME'],
        'PORT': os.environ['RDS_PORT'],
    }
}

STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

3-2-5. common.py を修正する

common.py の、Local 環境とProduction 環境に 個別に設定すべき内容 の項目とその値(中身)をすべて削除してください。
例えば今回であれば、 DEBUGALLOWED_HOSTSDATABASES などが該当します。

3-2-6. common.pySTATIC_URL を追加する

common.py に以下を追記します。すでにある場合は飛ばして構いません。

/config/settings/common.py
...
STATIC_URL = '/static/'
...

なお、Djangoの静的ファイルの扱いについては、この記事がとても分かりやすいので、是非読んでみてください。

3-2-7. manage.pywsgi.py を修正する

ルート直下の manage.py と、/config 直下の wsgi.py の以下の部分を修正します。

...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
...

manage.py
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
/config/wsgi.py
...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
...

3-3. スーパーユーザー作成用のコマンドを準備する

最後に、スーパーユーザー作成用のファイルを作成していきます。スーパーユーザーの作成は、Local 環境であれば、

$ python manage.py createsuperuser

などとして、ユーザー名、メールアドレス、パスワードを入力したと思いますが、今回はサーバーに実行してもらうため、それらを手動で入力することができません。なので、事前に入力する値を設定しておいて、それを実行させます。それが前述の 3-1-2 で出てきたものです。

3-3-1. createsu.py を作成する

cms(アプリ名なので置き換えてください。)の下に management フォルダ、その下に commands フォルダを作成し、そこに createsu.py を作成してください。そのファイルに以下を書き込んでください。

8行目の XXX、9行目の XXXYYYZZZ は各自で書き換えて、どこかに控えておいてください。また、8行目の XXX と 9行目の XXX は一致させてください。
これがスーパーユーザーアカウントになります。複数作りたい場合は、 if 文の数を増やせばよいだけです。

cms/management/commands/createsu.py
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import get_user_model

User = get_user_model()

class Command(BaseCommand):
    def handle(self, *args, **options):
        if not User.objects.filter(username="XXX").exists():
            User.objects.create_superuser(username="XXX", email="YYY", password="ZZZ")
            self.stdout.write(self.style.SUCCESS('Successfully created new super user'))

3-3-2. __init__.py を作成する

次に、作成した management, commands フォルダそれぞれの直下に __init__.py というファイルを作成してください。これらのファイルは作成するだけで、中身は何も書き込みません。

これで「アプリケーションソースバンドルの準備」は完了です。このセクションの最初にお見せした、ディレクトリ構造と同じようになっているかどうかを確認してください!

4. アプリケーションソースバンドルを作成する

あとは、作成したものを zip にして、デプロイするだけです。

4-1. zip ファイルを作成する

何も難しいことはないかと思いますが、 zip にする対象について。
基本的にプロジェクト直下のファイル、フォルダをまとめて zip にします。(プロジェクトのディレクトリそのものzip にするわけではない)
ただし、例えば git を使っているのなら、 .git フォルダや、 .gitignore などのファイルがあると思いますが、それらは含めません。アプリケーションに必要なものだけを対象にしてください。
必要であれば以下を参照してください

Mac, Linux の場合

例えばプロジェクトのルートディレクトリで、以下のようなを実行すれば、プロジェクトの一つ上の階層に myapp.zip が生成されます。( . から始まるものは、 .ebextensions しか含まれないので、ほかに含める必要のあるファイルやフォルダがあれば適宜対応してください。)

$ zip ../myapp.zip -r * .ebextensions

Windowsの場合

コマンドプロンプトやPowershellからもできますが、コマンドが長すぎるのと、含めないファイル(フォルダ)の設定がややこしいのでGUIでやります。以下のように、必要なファイルとフォルダを選択して、
右クリック→送る→圧縮(zip形式)フォルダー
とすれば作成できます。

image.png

4-2. アップロードしてデプロイする

いよいよ、サーバーにアップロードしてデプロイします。
コンソールの実行バージョンの下の、「アップロードとデプロイ」をクリックして、先ほど作成した zip ファイルを選択します。
バージョンラベルは自分でバージョンを区別できるわかりやすいものを付けると良いでしょう。

あとは、「デプロイ」ボタンを押して完了です。
最初のデプロイは完了までに数分かかることがあるので辛抱強く待ってください。

エラーが出ていなければデプロイ完了です。自身のアプリのURLにアクセスして、スーパーユーザーアカウントにログインできるか、などを確認してみましょう。

以上です。お疲れさまでした。

参考

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

Eclipseを使ってJavaからMySQLへ接続する

JavaでMySQLを操作する方法について解説していきます。
今回はWindows環境にXAMPPをインストールしてMySQLを使用します。

事前準備

・JDKのインストール
・Eclipseのインストール
・XAMPPのインストール
・JDBCドライバの準備

Eclipseの準備

1.Javaプロジェクトを作成

左上の「ファイル(F)」>「新規(N)」>「Javaプロジェクト」 で今回使う新規プロジェクトを作成します。
image.png
プロジェクト名はわかりやすく「MysqlTest」とでもしておきましょう。「完了(F)」をクリックして作成します。

image.png

2.プロジェクトにJDBCドライバを組み込む

プロジェクトが作成できたらプロジェクト上で右クリックをし、 「ビルド・パス(B)」>「外部アーカイブの追加(V)…」を選択してJDBCドライバ(mysql-connector-java-8.0.19.jar)を開きます。
image.png
image.png
プロジェクト直下の「参照ライブラリ」にmysql-connector-java-8.0.19.jarが追加してあれば大丈夫です。

MySQLの準備

XAMPPを起動し、MySQLを「Start」させます。
image.png
Startできたら右にある「Shell」をクリックして起動させます。
起動出来たら以下のコマンドを入力し、rootユーザーでMySQLに接続します。パスワード等の設定はこちらの記事を参考にしてください。

mysql -u root -p

接続ができたら、以下のコマンドでデータベースを作成します。今回は「test_db」という名前のデータベースを作成します。

CREATE DATABASE test_db;

無事に作成できたら、以下のコマンドで今作ったデータベースに接続します。

USE test_db;

ここまでの流れは以下の画像のとおりです。
image.png

次にテーブルを作成し、データを格納していきます。今回は「test」というテーブルを作成します。以下のコマンドを入力してください。※コンマを忘れないように!もし、入力ミスをした場合は「\c」で中断して新しく入力し直してください。

CREATE TABLE test(
    id VARCHAR(3),
    name VARCHAR(10)
);

テーブルが作成できたらデータを格納していきます。今回はデータを3行格納してみましょう。

INSERT INTO test VALUES('001', 'みかん');
INSERT INTO test VALUES('002', 'りんご');
INSERT INTO test VALUES('003', 'ぶどう');

ここまでの流れは以下の画像のようになります。
image.png

きちんとデータが格納されたかどうか以下のコマンドで確認してみましょう。

SELECT * FROM test;

image.png
これでMySQLの準備は完了です。

JavaからMySQLに接続

さて、以上で準備は整いました。ここからはJavaプログラムを作成して、先ほど作成したデータベースにアクセスし、テーブルのデータを表示させてみましょう。

まず、最初に作った「MysqlTest」プロジェクトの中にある「src」を右クリックし、「新規(W)」>「パッケージ」で「java_mysql」というパッケージを作成します。
image.png

次に、今作ったパッケージを右クリックし、「新規(W)」> 「ファイル」「Test.java」というファイルを作成します。

image.png
ここまで出来たら「Test.java」の中身を書いていきます。 コードの意味はコメントで書いておきました。

Test.java
package java_mysql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Test {

    public static void main(String[] args) {

    // 変数の準備
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

    // SQL文の作成
        String sql = "SELECT * FROM test";

        try {
            // JDBCドライバのロード
            Class.forName("com.mysql.cj.jdbc.Driver");
            // データベース接続
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test_db?serverTimezone=JST", "root", "root");
            // SQL実行準備
            stmt = con.prepareStatement(sql);
            // 実行結果取得
            rs = stmt.executeQuery();

      // データがなくなるまで(rs.next()がfalseになるまで)繰り返す
            while (rs.next()) {
                String id = rs.getString("id");
                String name = rs.getString("name");

                System.out.println(id + ":" + name);
            }
        } catch (ClassNotFoundException e) {
            System.out.println("JDBCドライバのロードでエラーが発生しました");
        } catch (SQLException e) {
            System.out.println("データベースへのアクセスでエラーが発生しました。");
        } finally {
            try {
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                System.out.println("データベースへのアクセスでエラーが発生しました。");
            }
        }
    }

}

コードが書き終わったら保存をし、「Test.java」を右クリックして「実行(R)」>「Javaアプリケーション」から実行します。

image.png
コンソールで以下のように表示されていれば成功です。

image.png

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

DockerでMySQLなどのテスト環境を作っていたら(errno: 150 "Foreign key constraint is incorrectly formed")が出た話

背景

mariadbをdocker環境に移してテストしようとしたところ、30分くらい詰まってしまったのでここに供養します。

現象

外部参照用のテーブルを新規に作成しようとすると下記のエラーが出る。

ERROR 1005 (HY000): Can't create table `{dbname}`.`{tablename}` (errno: 150 "Foreign key constraint is incorrectly formed")

原因(1)

参照しようとしている行がユニークでないためエラーになっていた。
下記のようなSQLで、重複データを削除し プレマリキーとした。

CREATE TEMPORARY TABLE {table name}_tmp AS SELECT id,MIN(uid),MIN(name) FROM tweets GROUP BY id;
DELETE FROM {table name};
INSERT INTO {table name} SELECT * FROM {table name}_tmp;
DROP TABLE {table name}_tmp;
ALTER TABLE {table name} ADD PRIMARY KEY (id);

原因(2)

参照先と参照元の型が異なる場合に発生する。
同一の方であることを確認した。

原因(3)

テーブルのcharsetが異なる場合に発生する。
下記のコマンドで確認する。

SHOW CREATE TABLE {table name};

とりあえず、対象テーブルを同一なcharsetに修正する。
※データが入っていると色々面倒ですが、私は何も入っていないのですんなり行きました。

ALTER TABLE {table name} CONVERT TO CHARACTER SET {char set};

あと、外部参照がある、テーブルにも設定させる

create table{table name}(
   {col} varchar(23) not NULL,
    ...
)ENGINE=InnoDB DEFAULT CHARSET={char set};

最後に

私は1と3で発生していました。
備忘録です、忘れぬように ここに刻む

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

MySQLのコンテナを作る方法

  • 環境
    • CentOS Linux release 7.8.2003 (Core)
    • Docker Engine 19.03.8
    • docker-compose version 1.25.5

1. docker-compose.ymlを作る

version: '3.8'
services:
  app:
...省略...
  logdb:
    image: mysql:8.0.20
    environment:
      MYSQL_DATABASE: logdb
      MYSQL_USER: log
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
      MYSQL_TCP_PORT: 3306
    ports:
      - 3304:3306
    volumes:
      - ./logdb/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./logdb/init:/docker-entrypoint-initdb.d
    container_name: logdb
    restart: always

imageにはDockerHubにあるMySQLを指定

指定のやり方はいくつかあるようだが、後でバージョンがわかる書き方にしてみた。
mysql - Docker Hub

environmentにデータベースの情報を指定

  • MYSQL_DATABASE : 初期作成するデータベース名を指定
  • MYSQL_USERMYSQL_PASSWORD : MYSQL_DATABASEで指定したデータベースのスーパーユーザーになるユーザーとそのパスワードを指定
  • MYSQL_ROOT_PASSWORD : rootユーザーのパスワードを指定
  • MYSQL_TCP_PORT : MySQLのポート番号を指定
    • 指定しなくても3306になりそうだけれど自信がないので指定しておく

portsに公開するポートを指定

ほかのコンテナやホストの外部からデータベースを使えるように{ホストでのポート}:{コンテナでのポート}を指定

volumesの指定

設定ファイルの配置

文字コードなどの必要な設定を記載した設定ファイルmy.cnfを用意しておき/etc/mysql/conf.dに配置する

my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'
skip-character-set-client-handshake
port=3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

[mysqldump]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[client]
default-character-set=utf8mb4

初期テーブル作成用SQLの配置

最初に作成しておいてほしいテーブル定義を書いたSQLをinitディレクトリに格納しておきdocker-entrypoint-initdb.dに配置するとデータベース作成後に作成しておいてもらえる
データを作成しておきたい場合もSQLをディレクトリに入れておけば実行してもらえる

USE logdb;

DROP TABLE IF EXISTS rhel6;
CREATE TABLE rhel6 (
-- ...省略...
);

DROP TABLE IF EXISTS rhel7;
CREATE TABLE rhel7 (
-- ...省略...
);

restartでコンテナの自動起動を設定

always(常に再起動)を設定することでホストを起動したときに自動で起動してもらえる

2. コンテナを作る

--no-recreateをつけて既存のコンテナを作り直さないようにしてコンテナを作成する

$ docker-compose up -d --no-recreate --build
...省略...
Creating logdb                   ... done

$ docker ps
CONTAINER ID       IMAGE             COMMAND            CREATED             STATUS              PORTS                             NAMES
625ce72a719        mysql:8.0.20      "docker-entry…"   23 seconds ago      Up 21 seconds       33060/tcp, 0.0.0.0:3304->3306/tcp logdb
5cead7ffb9b        host-java...      "/usr/sbin/init"   7 hours ago         Up 28 minutes       0.0.0.0:18080->8080/tcp           app

3. データベースにログインしてみる

ホストからログイン

ホストからつなぐときは、[コンテナに入る] > [データベースにログイン]でちょっと面倒くさい
けれどホストからつなぐことはあまりない・・・と思う

# 1.コンテナに入る
$ docker exec -it logdb bash

# 2. データベースにログイン
root@793f7ed80b16:/# mysql -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

# my.cnfの設定が使われてるっぽい
mysql> select default_character_set_name, default_collation_name from information_schema.schemata where schema_name = 'logdb';
+----------------------------+------------------------+
| DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+----------------------------+------------------------+
| utf8mb4                    | utf8mb4_general_ci     |
+----------------------------+------------------------+
1 row in set (0.00 sec)

# テーブルもできている
mysql> show tables;
+-----------------+
| Tables_in_logdb |
+-----------------+
| rhel6           |
| rhel7           |
+-----------------+
2 rows in set (0.00 sec)

mysql>

アプリ用コンテナからログイン

ほかのコンテナからログインするときは-h(ホスト)に「コンテナ名」を指定する

$ mysql -h logdb -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

ローカルPC(Windows)のGitBashでログイン

ホスト外部からログインするときは-h(ホスト)に「ホストのIPアドレス」を-P(ポート)に「docker-compose.ymlで指定したホストのポート」を指定する
winptyはGitBashを使用しているからつけているだけなので普通はいらない

$ winpty mysql -h {ホストのパブリックIP} -P 3304 -u log -D logdb -p
Enter password: *******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.20 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

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

DockerでMySQLを起動して、Intelij IDEAで接続する方法

DockerでMySQLを起動して、Intelij IDEAにdockerプラグインを導入して接続する方法を紹介します。画像多めです。

作業環境

OS:Windows 10
エディション:HOME
バージョン:2004

事前準備

①Windowsを最新版にアップデートする

下記のサイトを参考に、Windows 10 HOMEの場合は必ず最新版までアップデートしておきます。
https://www.atmarkit.co.jp/ait/articles/1701/07/news037.html
最新版になるまで、何回もやる可能性があります。下のような画面になれば、OKです。
202005191040.png

②IntelliJ IDEAのインストールする

以下のサイトを参考にIntelliJ IDEAの Community Edition をインストールし、日本語化します。
https://sukkiri.jp/technologies/ides/intellij-idea/intellij-idea-win.html
※Editionが2つあるので、注意してください。
202005241417.png

③Dockerをインストールする

以下のサイトを参考に、Dockerをインストールします。
https://techracho.bpsinc.jp/ebi/2020_03_27/90477

Windows 10 HOMEの場合は、インストール方法が特殊なので、下記のサイトを参考にインストールしてください。
https://tech.guitarrapc.com/entry/2020/04/21/034236

④Dockerの設定

Dockerのインストールが終わったら、起動して、上の歯車のアイコンを押して、設定を開きます。
202005191315.png
「General」の中にある「Expose daemon on …」をオンにし、下にある「Apply & Restart」を押します。
※Dockerの画面が出ない場合は、ここからアクセスします。
202005190946.png

サンプルソースをダウンロードする

今回は下記のサイトから、サンプルコードをダウンロードします。
https://github.com/miyabayt/spring-boot-doma2-sample
下の画像にように、「Clone or download」という緑のボタンを押すと、下のような画面が出てくるので、「Download ZIP」を押してダウンロードします。
202005191300.png
ZIPファイルをダウンロードして、デスクトップなどに解凍してから、Cドライブ直下に移動してください。
202005200019.png
私の環境下では、Cドライブ直下に解凍すると、下記のように解凍されました。元のフォルダの構成がとは異なるので、エラーの原因になります。上記の画像と同じ構成になるように解凍してください。
202005192249.png

IntelliJ IDEAにプラグインを導入する

事前準備が完了したら、IntelliJ IDEAに4つプラグインを導入します。

①Lombok pluginをインストールする

「構成」→「プラグイン」を押します。
202005191058.png
下記のような、プラグインを追加する画面に変わります。
202005191100.png
赤枠で囲ったところに「Lombok」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191103.png

②Eclipse Code Formatterをインストールする

次に「Eclipse Code Formatter」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191218.png

③Dockerをインストールする

次に「Docker」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191223.png

④Python Community Editionをインストールする

次に「Python Community Edition」と入力すると プラグインが表示されるので、インストールボタンを押して、インストールします。
202005191226.png
※このプラグインはIntelliJ IDEAからおすすめされて入れたので、不要の可能性もあります。
プラグインのインストールが終わったら、OKを押すと前の画面に戻ります。

導入したプラグインを設定する

次にプラグインの設定をしていきます。
「構成」→「設定」を押し、設定の画面を開きます。
202005191056.png

①Lombok pluginの設定

左側の「ビルド、実行、デプロイ」を押し、「コンパイラー」を開き、その中の「注釈プロセッサー」を押します。
202005191016.png
右側の画面が変わるので、「注釈処理を使用可能にする」にチェックを入れ、上の画面のようになればOKです。

②Eclipse Code Formatterの設定

左側の「その他の設定」→「Eclipse Code Formatter」を押します。
202005191020.png
右側の画面が変わるので、「Use the Eclipse code formatter」にチェックを入れ、「Eclipse Java Formatter config file」の右の「参照」を押すと、ファイル選択の画面が出てきます。
202005191021.png
先程解凍した「spring-boot-doma2-sample-master」というフォルダを開き、その中の「eclipse-formatter.xml」を選びます。

eclipse-formatter.xmlまでのパスは、Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、下記の通りになります。
C:\spring-boot-doma2-sample-master\eclipse-formatter.xml

③Dockerの設定

左側の「ビルド、実行、デプロイ」を押し、「Docker」を押します。
202005191014.png
「TCPソケット」を選び、接続が完了すればOKです。
接続できない場合は、まずはDockerが起動しているかどうか確認してください。

以上でプラグインの設定は終了です。

IntelliJ IDEAの設定を変更する

プラグインの設定が完了したら、IntelliJ IDEAの設定を変更していきます。

①bootRunを実行している場合でもビルドされるようにする

Intellij上で「Ctrl+Shift+A」を押すと、小さい画面が出てくるので、「レジストリー」と入力します。
202005191328.png
すると下に「レジストリー」と出てくるので、ここを選びます。
202005191331.png
「compiler.automake.allow.when.app.running」という項目探して、右側のチェックボックスにチェックを入れます。終わったら、「閉じる」を押します。

②コンソール出力の文字化けを防ぐ

Windowsの場合は、コンソール出力が文字化けするため、C:¥Program Files¥JetBrains¥IntelliJ Idea xx.x.x¥binの中にある「idea64.exe.vmoptions」というファイルを開きます。
202005191338.png
一番下の行に「-Dfile.encoding=UTF-8」を追記して保存します。
202005191339.png

③Java11を設定する

「構成」→「プロジェクト構造」を選びます。
202005191345.png
設定が開くので、「プロジェクト設定」→「プロジェクト」を開き、「プロジェクトSDK」と「プロジェクト言語レベル」をそれぞれ、「11」を選びます。
202005191352.png
もし、「プロジェクトSDK」で「11java version “11.0.7”」といった項目が出ない場合は、以下のページより「Java SE 11 (LTS)」の「JDK Download」からダウンロードして、インストールしてください。
https://www.oracle.com/java/technologies/javase-downloads.html

※詳しいインストール手順が必要な場合はこちらを参考にしてみてください。
https://sukkiri.jp/technologies/processors/jdk/jdk-win_install.html

DockerでMySQLを起動する

初回起動の場合

初回起動の場合は、以下の手順でMySQLを起動します。
202005191610.png

①docker-compose.ymlが存在するフォルダを確認する

サンプルコードの中には、DockerでMySQLを起動するための設定ファイル「docker-compose.yml」が含まれています。
202005200106.png
Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、「C:\spring-boot-doma2-sample-master\docker」にあります。

②Windows Power Shell を管理者権限で起動する

Dockerにコンテナなどを追加するので、タスクバーのwindowsマークの上で右クリックして、Windows Power Shell を管理者権限で起動します。
202005200041.png

③Windows Power ShellからDockerのMySQLを起動する

急にWindows Power Shellが出てきて、難しそうですが、入力するのは以下の2行だけです。

cd C:\spring-boot-doma2-sample-master\docker
docker-compose up

先程の「docker-compose.yml」というファイルが存在するフォルダまで移動します。Cドライブ直下に「spring-boot-doma2-sample-master」がある場合は、以下のようになります。

cd C:\spring-boot-doma2-sample-master\docker

“docker-compose”というコマンドが使えるかどうかを確かめるために、以下のように入力します。

docker-compose --version

以下のようにバージョンが表示されればOKです。

docker-compose version 1.25.5, build 8a1c60f6

次に以下のように入力して、MySQLを起動します

docker-compose up

エラーが出てうまく行かない場合は、docker-compose.ymlが存在するフォルダまで移動してから、上記のコードを実行しているかどうか、確認してください。
このコマンドが終了すると、Dockerの画面が下記のように変わります。
202005190953.png
簡単にDockerでMySQLを起動することができますね。

2回目以降

Dockerを起動します。Dockerの画面が出ない場合は、ここからアクセスします。
202005190946.png
白いクジラのアイコンの上で右クリックをして、「Dashboard」を選びます。
202005190948.png
Dockerの画面が出てきたら、赤枠で囲った▶部分を押します。
202005190949.png
MySQLが出てくるので、赤枠で囲ったボタンを押すと、サーバーの起動が始まります。
202005190952.png
下の画面が出てくればOKです。
202005190953.png

Dockerで起動したMySQLに、Intelij IDEAを接続する

Intelij IDEAを起動して、「オープンまたはインポート」を選びます。
202005191417.png
Cドライブ直下に解凍した「spring-boot-doma2-sample-master」を選び、OKを押します。
202005191420.png
下のような画面が出てくるので、「サービス」を選びます。
202005190959.png
画面が変わると「Docker」が出てくるので、選ぶと接続が始まります。202005191000.png
接続が完了すると、以下のような画面になります。
202005191001.png
以上で、Dockerで起動したMySQLに、Intelij IDEAで接続することができました。

サンプルコードを動かす

ここからは、サンプルコードを動かしていきます。
サンプルコードを動かす前に、プラグインの設定とJavaの設定を確認してください。
確認が終了したら、Intelij IDEAの「ターミナル」を開きます。
202005191002.png

①バージョン確認

ターミナルが起動したら、以下のように入力します。

cd C:\spring-boot-doma2-sample-master

次に、以下のようにコードを入力します。

gradle -v

以下のように、バージョンが表示されます。

------------------------------------------------------------
Gradle 6.3
------------------------------------------------------------

Build time:   2020-03-24 19:52:07 UTC
Revision:     bacd40b727b0130eeac8855ae3f9fd9a0b207c60

Kotlin:       1.3.70
Groovy:       2.5.10
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.7 (Oracle Corporation 11.0.7+8-LTS)
OS:           Windows 10 10.0 amd64

②サンプルコードを動かす

次にサンプルコードを動かします。以下のように入力します。

gradlew composeUp

プログラムが終わったら、以下のように入力します。

gradlew :sample-web-admin:bootRun

しばらく待つと、95%で止まりますが、そのままでOKです。
202005191007.png
これでアプリが起動したので、http://localhost:18081/adminにアクセスします。
screencapture-localhost-18081-admin-login-2020-05-19-10_09_21 (1).png
上のような画面が出てきたら、成功です。お疲れさまでした。

この記事は先輩エンジニアからアドバイスを受け、個人ブログから移植しました。おかしいところなどありましたら、ご指摘いただけると幸いです。

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

WordPress の wp-config.php のバリデーション

WordPress のデータベースへの接続は wp-config.php で定義されます。
その接続情報でデータベースに接続できるか判定する方法です。

wp-config.php は、wordpress 以下にあるものをコピーします。
wp-settings.php は空の PHP です。

フォルダー構造

$ tree
.
├── connect_check.php
├── wp-config.php
└── wp-settings.php
connect_check.php
#! /usr/bin/php
<?php
/*
    connect_check.php

                    May/24/2020

*/
// --------------------------------------------------------------------
include_once ("wp-config.php");

// --------------------------------------------------------------------
$host = DB_HOST;
$user = DB_USER;
$password = DB_PASSWORD;
$db = DB_NAME;

$dsn = 'mysql:dbname=' . $db . ';host=' . $host . ';charset=utf8';

fputs (STDERR,"*** 開始 ***\n");
print DB_USER . "\n";

try
    {
    $dbcon = new PDO ($dsn, $user,$password);
    $sql = "show schemas";
    $sql = "select version()";
    foreach ($dbcon->query($sql) as $row)
        {
        $str_json = json_encode($row);
        print $str_json . "\n";
        }
    $dbcon = null;
    }
catch  (PDOException $e)
    {
    print('Error:'.$e->getMessage());
    }

fputs (STDERR,"*** 終了 ***\n");
// --------------------------------------------------------------------
?>
wp-settings.php
<?php

?>

実行結果

データベースが MariaDB の時

$ ./connect_check.php 
*** 開始 ***
wordpress
{"version()":"10.4.13-MariaDB","0":"10.4.13-MariaDB"}
*** 終了 ***

データベースが MySQL の時

$ ./connect_check.php 
*** 開始 ***
wordpress
{"version()":"5.7.28-log","0":"5.7.28-log"}
*** 終了 ***

接続が出来ない時

$ ./connect_check.php 
*** 開始 ***
wordpress
Error:SQLSTATE[HY000] [1045] Access denied for user 'wordpress'@'localhost' (using password: YES)*** 終了 ***

バリデーションでオーケーになっても、まだ WordPress で接続できない時は、次を試して下さい。

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

MySQL他のテーブルをコピーする方法

概要

自分のメモ

テーブルコピー

<例>

CREATE TABLE
    `table_copy_target` like `table_original`;

■適宜下記書き換える
作成するテーブル名:table_copy_target
コピーするテーブル名:table_original

レコードコピー

<例>

INSERT INTO
    `table_copy_target`
    (id,name,name_kana,name2_kana...)
SELECT 
    id,name,name_kana,name2_kana...
FROM
    `table_original`;

■適宜下記書き換える
作成するテーブル名:table_copy_target
コピーするテーブル名:table_original

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

PHP+LINE Messaging APIでクイズアプリを作ってみよう

今回やりたいこと

今回はPHPでLINE Messaging APIを使いクイズアプリを作成します。

仕様

・リッチメニューをタップしクイズを出題
・4つの選択肢から回答する
・正解の場合のみ解説の参考サイトurlを添付
・クイズはDB管理とし、クイズの追加・編集・削除機能がある管理画面の作成
※管理画面は後日公開予定です。

こちらから友達追加してお試しいただけます!
https://lin.ee/3AOdmRRlo
スクリーンショット 2020-05-24 13.56.43.png

イメージ

あいさつメッセージ
IMG_6287.PNG

リッチメニューをタップするとクイズを出題
IMG_6306.PNG

不正解の選択肢をタップした場合のメッセージ
IMG_6289.PNG

正解の選択肢をタップした場合のメッセージ
IMG_6290.PNG

いいえをタップした場合のメッセージ
IMG_6305.PNG

はいをタップした場合、次のクイズが出題
IMG_6306.PNG

以上の仕様を実装します。

VPSで環境構築

VPSはこちらを参考に構築しました。詳細は下記サイトから確認してみてください。他にも参考になる記事がたくさんあるのでググってみて下さい!
ネコでもわかる!さくらのVPS講座 〜第一回:VPSてなんだろう?〜

Messaging APIを設定

Messaging APIの概要はこちら

プログラム

DBカラム

quizzes : id | quiz | ans1 | ans2 | ans3 | ans4 | correct | url | deleted

quiz:問題文
ans1~4:選択肢1~4
correct:正解番号
url:解説サイトのurl
deleted:論理削除用

index.php
<?php

$accessToken = 'アクセストークン'; 
//file_get_contents()関数でPOSTされたJSON文字列を取り出し
$jsonString = file_get_contents('php://input'); 
//エラーログ記録
error_log($jsonString); 
//json_decode()関数でJSONをデコードして変数に格納
$jsonObj = json_decode($jsonString); 
//メッセージイベントを取得
//スタンプ、テキスト、画像などの場合がある
$message = $jsonObj->{"events"}[0]->{"message"};
//ReplyToken取得
//受信したイベントに対して返信を行うために必要
$replyToken = $jsonObj->{"events"}[0]->{"replyToken"};
//メッセージタイプ取得
//ここで、受信したメッセージがテキストか画像かなどを判別
$type = $jsonObj->{'events'}[0]->{'type'};

// 送られてきたメッセージの中身からレスポンスのタイプを選択 

//$typeがmessageの場合
if ($type == 'message') {
   //messageがtextであり、かつtextがクイズの場合クイズを返信する
    if ($message->{"text"} == 'クイズ') {
    //DB接続
        $dbh = new PDO("mysql:host=localhost;dbname=DB名", 'ユーザー名', 'パスワード');
     //sql文を変数にセット
       //DBから論理削除されていないクイズIDの配列を作る
        $sql = "SELECT id FROM quizzes WHERE deleted = 0";
        $res = $dbh->query($sql);
        $quizIdArray = array();
        foreach ($res as $row) {
            array_push($quizIdArray, $row['id']);
        }
    //クイズIDをランダムに並べ替える
        shuffle($quizIdArray);
      //クイズID配列の先頭要素をキーに、クイズを取得し表示する
        $targetQuizId = $quizIdArray[0];
        $sql2 = "select * from quizzes where id = $targetQuizId";
        $stmt = $dbh->query($sql2);
        $targetRow = $stmt->fetch();
    //$messageDataにクイズの内容を代入する
        $messageData = [ 
            'type' => 'template', 
            'altText' => 'クイズ', 
            'template' => [ 'type' => 'buttons', 'text' => $targetRow['quiz'], 
            'actions' => [
            [ 'type' => 'postback', 'label' => $targetRow['ans1'], 'data' => 'ans=' . $targetRow['ans1'] . '&num=1&correct=' . $targetRow['correct'] . '&id=' . $targetRow['id'] ],
            [ 'type' => 'postback', 'label' => $targetRow['ans2'], 'data' => 'ans=' . $targetRow['ans2'] . '&num=2&correct=' . $targetRow['correct'] . '&id=' . $targetRow['id'] ],
            [ 'type' => 'postback', 'label' => $targetRow['ans3'], 'data' => 'ans=' . $targetRow['ans3'] . '&num=3&correct=' . $targetRow['correct'] . '&id=' . $targetRow['id'] ],
            [ 'type' => 'postback', 'label' => $targetRow['ans4'], 'data' => 'ans=' . $targetRow['ans4'] . '&num=4&correct=' . $targetRow['correct'] . '&id=' . $targetRow['id'] ],
            ] 
            ]
        ]; 
    //messageがtextであり、かつtextがいいえであった場合の返信を$massageDataに代入
    }elseif ($message->{"text"} == 'いいえ') {
        $messageData = [ 'type' => 'text', 'text' => 'いつも[解剖学クイズbot]をご利用いただきありがとうございます。クイズチャレンジお疲れ様でした!楽しんでいただけましたでしょうか?またのチャレンジをお待ちしております!' ]; 
        $messageData2 = [ 'type' => 'text', 'text' => '再度クイズにチャレンジする場合は、「クイズにチャレンジ!」をタップしてください!' ]; 
    } else {
   //$typeが上記以外の場合の返信内容を$messageDataに代入
        $messageData = [ 'type' => 'text', 'text' => '申し訳ありません、その操作には対応しておりません。「クイズにチャレンジ!」をタップしてクイズにチャレンジしてみて下さい。' ]; 
    } 
}
//$typeがpostbackの場合
if ($type == 'postback') {
   // JSONデータからポストバックデータを取得
    $postback = $jsonObj->{"events"}[0]->{"postback"}->{"data"};
   //文字列を名前と値に分解し変数に代入
    parse_str($postback, $data);
   //各値を変数に代入
    $answer = $data["ans"];
    $number = $data["num"];
    $id = $data["id"];
    $correct = $data["correct"];
   //ユーザーの選択した選択肢と正解番号を比較し、正解・不正解の場合で返信内容を$massageDataに代入
   //正解の場合
    if ($number == $correct) {
        $dbh = new PDO("mysql:host=localhost;dbname=DB名", 'ユーザー名', 'パスワード');
   //選択された選択肢のIDから解説サイトのurlを取得
        $sql3 = "SELECT url FROM quizzes WHERE id = $id";
        $stmt2 = $dbh->query($sql3);
        $targetRowUrl = $stmt2->fetch();
        $url = $targetRowUrl['url'];
   //$massageDataに返信内容を代入
        $messageData = [ 'type' => 'text', 'text' => $answer . 'ですね。' ]; 
        $messageData2 = [ 'type' => 'text', 'text' => '素晴らしい!『正解』です!!!' ]; 
        $messageData3 = [ 
            'type' => 'template',
            'altText' => '解説', 
            'template' => [
            'type' => 'buttons',
            'title' => '解説です!',
            'text' => '確認してみてね!', 
            'actions' => [
            [
            'type' => 'uri',
            'label' => 'Wikipediaへ移動', 
            'uri' => "$url", 
            ]
            ]
            ] 
        ]; 
        $messageData4 = [ 
            'type' => 'template', 
            'altText' => '次のクイズにチャレンジしますか?', 
            'template' => [ 'type' => 'confirm', 'text' => '次のクイズにチャレンジしますか?', 
            'actions' => [
            [ 'type' => 'message', 'label' => 'はい', 'text' => 'クイズ' ],
            [ 'type' => 'message', 'label' => 'いいえ', 'text' => 'いいえ' ], 
            ] 
            ]
        ];
    }else{
   //不正解の場合の返信内容を$massageDataに代入
        $messageData = [ 'type' => 'text', 'text' => $answer . 'ですね。' ]; 
        $messageData2 = [ 'type' => 'text', 'text' => 'むむ、、『不正解』です。' ]; 
    }
}
//メッセージの数に合わせ条件分岐
if ($messageData4 == true) {
    $response = [ 'replyToken' => $replyToken, 'messages' => [$messageData,$messageData2,$messageData3,$messageData4] ]; 
}elseif ($messageData3 == true) {
    $response = [ 'replyToken' => $replyToken, 'messages' => [$messageData,$messageData2,$messageData3] ]; 
}elseif ($messageData2 == true) {
    $response = [ 'replyToken' => $replyToken, 'messages' => [$messageData,$messageData2] ]; 
}else{
    $response = [ 'replyToken' => $replyToken, 'messages' => [$messageData] ]; 
}
error_log(json_encode($response)); 
//curlセッション初期化。urlも設定
$ch = curl_init('https://api.line.me/v2/bot/message/reply'); 
//curlオプション設定
curl_setopt($ch, CURLOPT_POST, true); 
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($response)); 
curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json; charser=UTF-8', 'Authorization: Bearer ' . $accessToken )); 
//curl実行
$result = curl_exec($ch);
//エラーログ記録
error_log($result); 
//curlセッション終了
curl_close($ch);

?>

工夫した点

・クイズをDB管理とし、追加・編集・削除機能をつけた
・クイズをランダムに出題
・ユーザーからのレスポンスに応じて異なる処理

改善案

・メッセージの数に合わせた条件分岐がダサいのでスマートに書けないものか。。。
・クイズ内容を身体の部位ごとに指定するなど、分野を分ける
・解説を外部サイトに依存しているが、bot内で完結しても良いか
・その場合、画像付きの解説などを入れるとUXが高められそう

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

【MySQL】外部キー制約を一時的に無効にする

きっかけ

CRUD処理の開発中にテストで一回論理削除したデータを復活させたくなったけど、データに外部キー制約がかかってて戻せない...
一時的に外部キー制約無効にしたい!

解決法

外部キー制約を無効にする

SET FOREIGN_KEY_CHECKS = 0

有効に戻す

SET FOREIGN_KEY_CHECKS = 1

外部キー制約がかかっているテーブルをDROP TABLEで削除したい場合も、上記のコマンドで無効にすることで削除できるようになります。削除した場合、外部キー制約をかけていたテーブルの制約も削除されます。

参考

MySQL 5.6 リファレンスマニュアル

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

MariaDB で、root のパスワードを再設定

MariaDB 10.4.13 でのルートのパスワードを忘れた時に、再設定する方法です。
次のページを参考にしました。
How To Reset Your MySQL or MariaDB Root Password

1) mariadb の停止

sudo systemctl stop mysqld

2) セーフモードで mariadb を立ち上げる

sudo mysqld_safe --skip-grant-tables --skip-networking &

3) root でアクセス

$ mysql -u root
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.4.13-MariaDB Arch Linux

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

4) グラントテーブルのロード

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.003 sec)

5) root パスワードの変更

> ALTER USER 'root'@'localhost' IDENTIFIED BY 'tiger123';

6) 結果を反映して、接続の遮断

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> exit;
Bye

7) セーフモードで動いている mariadb の停止

$ ps ax | grep mysql
   5284 pts/1    S      0:00 sudo mysqld_safe --skip-grant-tables --skip-networking
   5285 pts/1    S      0:00 /bin/sh /usr/bin/mysqld_safe --skip-grant-tables --skip-networking
   5370 pts/1    Sl     0:00 /usr/bin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --skip-grant-tables --skip-networking --log-error=/var/lib/mysql/iwata.err --pid-file=iwata.pid
   5479 pts/1    S+     0:00 grep mysql
$ sudo kill -9 5284 5285 5370
[1]+  Killed                  sudo mysqld_safe --skip-grant-tables --skip-networking

8) mariadb を起動

sudo systemctl start mysqld

9) root で接続

$ mysql -uroot -ptiger123
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 10
Server version: 10.4.13-MariaDB Arch Linux

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon Linux2 にMySQLを入れる際のエラー

AWS EC2インスタンスにLAMP環境構築する際に、MySQLインストールでエラーに詰まったのでメモメモ。

エラーの原因を結論から言えば、AmazonLinux2にはデフォルトでMySQLは用意されておらず、MariaDBがちょこんと居座ってること。そのため対処として公式ページからMySQLをインストールして、MariDB消せばOKである。

前提

  • Amazon Linux 2 AMI (HVM) SSD Volume Type
  • MySQL Ver 14.14 Distrib 5.7.30, for Linux (x86_64) ←これを入れたい

過程と対処

EC2インスタンスにssh接続後、ApacheとPHPをyumインストール。問題なく進み、そのノリでMySQLもインストール。

yum install -y mysql-community-server

ここでNo package mysql-community-server available.とエラーを返される。どうやらパッケージがないらしい。以下で調べてみると確かに無かった。

yum list mysql*

そこで、公式から追加することに(→MySQL Yum Repository)。ただしAmazonLinux2はcentOS7ベースということなので、追加するのはel7を選択。

 yum install http://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm   

ちゃんとリポジトリに追加されてるかを次で確認

yum repolist

mysql80-community-release-el7-3.noarchを確認。使用したいバージョンは5.7なので、5.7を有効化させる必要がある(最新バージョンの8.0のインストールによって旧バージョン5.7のリポジトリもセットでインストールされる)。

vi /etc/yum.repos.d/mysql-community.repo

mysql-communityのレポジトリ設定をいじる。上のコマンドで設定ファイルを開いたらMysql8.0のenabledの欄を0にして、Mysql5.7のenabledの欄を1に変更する。これによってインストールの方向が5.7に向く。

さて、これでyum install mysql-community-serverで解決かと思えば、次は依存関係のエラーが発生。エラー文を確認するとAvailable: 1:mariadb-libsの文字列を数件発見。MariaDB...?

どうやらAmazonLinux2(CentOS7も同様)ではMariaDBがデフォルトで入っており、MySQLインストールの際に邪魔になってしまうらしい。今回はMySQL使いたいので、MariaDBを削除することに。

yum remove mariadb-libs 

これの後にyumインストールしたら無事に解決しました。

参考

CentOS 7にMySQL 5.7をyumでインストール
AWS Amazon Linux2にMySQL5.7を構築する
Amazon Linux2でmysqlを入れようとしたらエラーが出た
パッケージ依存関係を解消する(rpm)

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