- 投稿日:2020-09-14T22:15:00+09:00
【初心者向け】LaravelアプリケーションをHerokuで公開しよう!【MySQL】
はじめに
Laravelアプリケーションを作成し、Herokuでいざ公開しようと思ったものの、これが意外や初心者には難しい。私はアプリケーションを公開するだけで3日間も悪戦苦闘してしまいました。同じ初心者の方には辛い思いをして欲しくないので、備忘録も兼ねてマニュアル記事を作成しました。
使用環境
・PHP7.2
・Laravel5.5
・mysql5.7
・Docker
※本記事では環境構築については解説いたしません
※PCはMacを使用しています①アプリケーションをGitリポジトリに入れよう
HerokuはGitの情報を用いてアプリケーションを公開します。そのため、まずはアプリケーションをGitリポジトリに入れる必要があります。
Gitについては以下のサイトが分かりやすいです。https://backlog.com/ja/git-tutorial/intro/01/
Gitの設定
まずは名前とメールアドレスを設定しましょう。以下のコマンドをターミナルに入力します。
※ご自身の名前とメールアドレスを入力してください。$ git config --global user.name "haruto.takahashi" $ git config --global user.email "haruto.takahashi@gmail.com"設定した内容は以下のコマンドで確認できます。
$ git config --global -l core.editor=/usr/bin/nano user.name=haruto.takahashi user.email=haruto.takahashi@gmail.comリポジトリの作成
まずはアプリケーションのあるディレクトリに移動します。
$ cd アプリケーション次に以下のコマンドを入力することでリポジトリが作成されます。
$ git init「Initialized empty Git repository in〜」と表示された場合は、指定のディレクトリに「.git/」というGitリポジトリが設置されたということになります。
以下のコマンドで現在のステータスを確認してみましょう。$ git status「No commits yet」と表示されるはずです。コミットされたファイルがないという意味です。
ステージの実行
以下のコマンドを入力し、全てのファイルのステージを実行します。
$ git add .再び以下のコマンドで現在のステータスを確認してみましょう。
$ git status今度は「new file:」としてステージされたファイルが無数の羅列となって表示されているかと思います。
コミットの実行
以下のコマンドを入力し、コミットを実行します。
$ git commit -m "first-commit"「first-commit」の部分は何でも良いのですが、git commit のコマンドの後に、-m "(メッセージ)" と付けることで、どんな変更を行ったかというコミットメッセージを入力することが可能です。
「create mode」と書かれた羅列が表示されていればコミット完了です。今後アプリケーションに変更を反映させる時は、同じようにコミットを実行しましょう。Herokuで公開後も同じです。②Herokuの設定をしよう
Gitの設定が完了したところで、次にHerokuの設定を行っていきます。Herokuへアプリケーションを公開(デプロイ)するためにはいくつか準備が必要です。
アカウントの作成
以下のページよりアカウントを作成してください。今回は無料版の使用を前提とします。
Heroku設定については以下のページが参考になります。
https://blog.proglus.jp/1438/Heroku-CLIの導入
Herokuをターミナルから操作できるようにするためのツールとしてHeroku-CLIを導入します。
まずは以下のコマンドを実行します。$ wget https://cli-assets.heroku.com/heroku-linux-x64.tar.gz -O heroku.tar.gz $ sudo mkdir -p /usr/local/lib/heroku $ sudo tar --strip-components 1 -zxvf heroku.tar.gz -C /usr/local/lib/herokuなお「-bash: wget: コマンドが見つかりません」と表示された場合は、以下のコマンドでwgetをインストールしましょう。
$ brew install wgetbrewも使用できない場合は同様にインストールが必要です。インストール方法はネットで検索すれば出てくるのでぜひ探してみてください。
シンボリックリンクの作成
導入が完了したら、次にシンボリックリンクを作成します。シンボリックリンクとは特定のファイルを別の場所から参照できるようにするためのもので、簡単に言うとWindowsのショートカットのようなものです。
シンボリックリンクを設定するには以下のコマンドを実行します。
$ sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/herokuなお余談ですが、シンボリックリンクを削除したい時は以下のコマンドを実行します。
$ unlink /usr/local/bin/herokuシンボリックリンクの設定が完了したら、以下のコマンドでHerokuへログインします。アカウント作成時に設定したメールアドレスとパスワードを聞かれるので入力しましょう。
$ heroku login -i heroku: Enter your login credentials Email: Herokuに登録済みのメールアドレスを入力 Password: Herokuに登録済みのパスワードを入力③Herokuアプリケーションを作成しよう
アプリケーションの作成
Herokuで公開するためのアプリケーションを作成します。下記のコマンドで実行されます。この時、アプリケーションの名前も設定しましょう。
$ heroku create 任意のアプリ名なお同じ名前のアプリケーションが既に作成されていた場合は、他者と重複しないよう名前を変更する必要があります。またその他の名前のルールとして、大文字やアンダーバー(_)はNGです。
作成後は以下のコマンドで名前が正しく登録されているかを確認します。$ heroku appsProcfileファイルの作成
Procfileファイルとは、Herokuのプラットフォーム上にあるWebアプリがどのようなコマンドで実行されるのかを記述するファイルのことです。以下のコマンドで作成できます。
$ echo "web: vendor/bin/heroku-php-apache2 public/" > ProcfileHerokuのapache2(Webサーバソフト)を使用するという記述になります。
ここで一度、Gitでコミットを実行します。$ git add . $ git commit -m 'add procfile'④アプリケーションを公開しよう
いよいよ最終段階...ですが設定しなければいけないことがまだいくつかあります。
データベースの設定
Herokuでは、PostgreSQLが標準のデータベースとなっています。MySQLを利用するにはClearDBというクラウドサービスを活用します。以下のコマンドで追加できます。
$ heroku addons:add cleardb環境変数の設定
Gitコミットを実行したファイルには.envファイルが含まれていないため、これまでとは別途で環境変数を設定する必要があります。
まず以下のコマンドを実行することで、Herokuでローカル環境と同じAPP_KEYが生成されます。$ heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)以下のコマンドでHerokuアプリケーションの環境変数を確認できます。
$ heroku config === youtube-curation Config Vars APP_KEY: base64:設定されたAPP_KEYが表示 CLEARDB_DATABASE_URL: mysql://ユーザ名:パスワード@ホスト名:5432/データベース名「DATABASE_URL」に表示されている内容を元に、以下のコマンドで環境変数の設定を行います。それぞれコピペしましょう。
$ heroku config:set DB_USERNAME=ユーザ名 $ heroku config:set DB_PASSWORD=パスワード $ heroku config:set DB_HOST=ホスト名 $ heroku config:set DB_DATABASE=データベース名またデータベースの設定も行います。使用するデータベースはMySQLなので以下のコマンドを実行します。
heroku config:set DB_CONNECTION=mysql最後にもう一度、環境変数が正しく設定されているかを確認しましょう。
$ heroku config === youtube-curation Config Vars APP_KEY: base64: APP_KEY CLEARDB_DATABASE_URL: mysql://ユーザ名:パスワード@ホスト名:5432/データベース名 DB_CONNECTION: mysql DB_USERNAME: ユーザ名 DB_PASSWORD: パスワード DB_HOST: ホスト名 DB_DATABASE: データベース名確認ができたら以下のコマンドでHerokuアプリケーションのマイグレーションを実行します。
$ heroku run php artisan migrate以下のように
Do you really wish to run this command? (yes/no) [no]:と聞かれた場合は「y(yes)」と答えます。
またシーダーを挿入する場合は以下のコマンドも実行します。
$ heroku run php artisan db:seedHerokuアプリケーションへのアクセス
設定は以上です。お疲れ様でした。
以下のURLからアプリケーションへアクセスしましょう。
https://Herokuアプリ名.herokuapp.com/
アプリケーションへの接続がうまくいかない場合は環境変数を見直してみましょう(私もここでミスがありました)
先ほどと同じ「heroku config:set」のコマンドを用いることで、環境変数を上書きすることができます。【補足①】Heroku公開後にアプリケーションの更新を反映する方法
復習になりますが、以下のコマンドでHerokuアプリケーションに変更が反映されます。
$ git add . $ git commit -m 'メッセージ' $ git push heroku master【補足②】Heroku公開後にエラーが発生した場合
Herokuアプリケーションはエラー発生時に「something went wrong.」というメッセージのみ表示されます。しかしこれではエラーの原因が分からないままです。以下のコマンドを実行することで、エラーの詳細を表示することができます。
$ heroku config:set APP_DEBUG=true先ほどのメッセージが表示された画面を更新すると、エラーの詳細が表示されるはずです。
エラーが解決したら以下のコマンドでエラーの詳細が表示されないように設定を戻しておきましょう。$ heroku config:set APP_DEBUG=falseあとがき
私は初めてアプリケーションを作成した時に、ネットで公開するだけでまさかこんなにたくさんの手順があるとは思いもよらず絶望していました。この記事がそんな辛い思いをしている駆け出しエンジニアの方のお役に立てば幸いです。最後までお読みいただきありがとうございました!
参照サイト
https://yu-nocode.com/wp/entry/laravel-quest-6/#i
https://qiita.com/yu731994/items/86e03c5ff91aa3ba7e9d
https://qiita.com/fukkun/items/dfa7002371b9f6e1abae
https://laraweb.net/environment/4115/
- 投稿日:2020-09-14T21:37:33+09:00
HerokuにデプロイしたLaravelアプリでDBのレコード表示(日本語)が文字化け
問題
先日、Laravelで制作しているクチコミ投稿サイトをHerokuにデプロイしました。データベースにはClearDB MySQLを使用していますが、日本語の文字化けが発生しました。YouTube万屋エンジニアチャンネル様の多大な協力のおかげで解決できました。
状況整理
- MacターミナルのMySQLでINSERTしたデータはブラウザで表示すると
ƒ–ルーノート最高ã®ãƒŸï
みたいに文字化けする- 一方ブラウザ上のフォームから投稿した内容はターミナルで表示すると
?????????
となる- ただし、ターミナルでINSERTしたデータはターミナル上ではきちんと表示され、ブラウザのフォームから投稿したデータはブラウザ上ではきちんと表示される
ちなみに、teratailにも質問投稿していました→ https://teratail.com/questions/291553?reply=true
環境確認
Heroku, ClearDB MySQL, Laravel 7, MacOS
原因は何か?
上のteratailを見ていただくとわかりますが、私は文字コードに関連しそうな箇所の見当をつけるべくviewの
のやdatabase.phpなど見当違いな箇所を見てましたが、今回に関しては関係ありませんでした。原因はMySQLクライアントの文字コード設定でした。ターミナルでMySQLにログインして下記コマンドで確認できます↓
mysql> show variables like 'character%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+↑このlatin1をutf8に変更する必要があります。変更にはMySQLの設定ファイルをいじることが必要です。
MySQLの設定ファイルを探せ!
設定ファイルはmy.cnfで、複数のディレクトリに存在していて、優先順位があるみたいです。下記コマンドで、それぞれのディレクトリと優先順位を確認できます。
$ mysql --help | grep my.cnf order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf1つめのディレクトリにはファイルが存在しませんでした...↓
$ cd /etc/my.cnf -bash: cd: /etc/my.cnf: No such file or directory2つめはディレクトリが存在しませんでした...↓
$ cd /etc/mysql -bash: cd: /etc/mysql: No such file or directory3つめのディレクトリにはありました...↓
$ cd /usr/local/etc $ ls bash_completion.d freetds.conf locales.conf odbc.ini openldap php fonts gitconfig my.cnf odbcinst.ini openssl@1.1 pool.confcatコマンドでファイルを閲覧します↓catは、concatenate(連結するの意)の略でファイルを閲覧したり連結コマンド。
$ cat my.cnf # Default Homebrew MySQL server config [mysqld] # Only allow connections from localhost bind-address = 127.0.0.1 mysqlx-bind-address = 127.0.0.1↑character(文字)に関する設定がありません。これを使っていきます!
その前に一応4つめも↓...ありません。
$ cd ~/.my.cnf -bash: cd: /Users/私のユーザー名/.my.cnf: No such file or directory番外編で下記の方法でも探しました。大量の結果が出てきて、しかも長かったので途中でCtrl+cでキャンセルしましたが、2点ほど気になる結果が。
$ find / -name "my*.cnf" find: /usr/sbin/authserver: Permission denied /usr/local/etc/my.cnf /usr/local/Cellar/mysql/8.0.21_1/.bottle/etc/my.cnf一応中を覗いてみるとこんな感じ↓でもこれは一旦無視。
$ cd /usr/local/Cellar/mysql/8.0.21_1/.bottle/etc $ ls my.cnf $ cat my.cnf # Default Homebrew MySQL server config [mysqld] # Only allow connections from localhost bind-address = 127.0.0.1 mysqlx-bind-address = 127.0.0.1my.cnfファイルに文字コードの設定を追記する
/usr/local/etc/my.cnfファイルをいじっていきます。
下記のように[mysqld]にcharacter-set-server = utf8
、[client]にdefault-character-set = utf8
を追記しました。(アンダーバーとハイフンなどスペルミスお気をつけください!汗)
念のため、開くコマンドは$vi my.cnf
、開いたらINSERTのi
で編集モード、終わったらescボタン
:wq
Enterボタン
です。my.cnf[mysqld] # Only allow connections from localhost bind-address = 127.0.0.1 mysqlx-bind-address = 127.0.0.1 character-set-server = utf8 [client] default-character-set = utf8 [mysql]結果確認
MySQLを再起動(
$ mysql.server stop
$ mysql.server start
)して、見てみると...↓mysql> show variables like "character%"; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+↑character_set_serverがlatin1のままなのは気になりますが、この状態でターミナルからINSERT文で挿入したレコードの日本語はきちんとブラウザで表示され、ブラウザのフォームから投稿して挿入されたレコードはターミナルのMySQLできちんと日本語で表示されるようになりました。
ちなみに、過去に文字化けしたレコードはそのまま文字化けしたままです。
もしこれでうまく行かなかったらぜひコメントください m(_ _)m
YouTube万屋エンジニアチャンネル様、重ね重ねありがとうございました。
- 投稿日:2020-09-14T15:50:52+09:00
特定のテーブルスペースにあるテーブルをinnodb_file_per_tableにテーブルを一気に移動したい時に使うSQL
データ容量が不足して、テーブルスペースを削除したいけど、テーブルスペースを削除するにはテーブルスペースに格納されているデータを別のテーブルスペースに移さないといけない!
そんな時に利用するALTER TABEL文を一気に作成するクエリです。
テーブルスペースを利用していたが、innodb_file_per_tableに一括で変換して元の領域に戻したいと思った時に使ってください。
innodb_file_per_tableテーブルスペースの場合だけ、データ削除によってテーブルに空き領域が出来たときには、ちゃんと必要な分だけ容量を確保するようにMysqlは動きます。
テーブルスペースの場合は、空き容量を回収してくれないので、削除しないとダメなので、運用がちょっと面倒。テーブルの文字コードを一括変換するSQLを作成するSQL
SELECT a.NAME AS space_name, b.NAME AS table_name, REPLACE( CONCAT( "ALTER TABLE " , b.NAME , " TABLESPACE innodb_file_per_table;" ) , "/", ".") FROM information_schema.INNODB_SYS_TABLESPACES a, information_schema.INNODB_SYS_TABLES b WHERE a.SPACE = b.SPACE AND a.NAME LIKE '<テーブルスペース名>' AND b.NAME not like "%/FTS%" ;
- 投稿日:2020-09-14T15:50:52+09:00
特定のテーブルスペースにあるテーブルをinnodb_file_per_tableもしくは特定のディレクトリのテーブルスペースに一気に移動したい時に使うSQLを作成するSQL
データ容量が不足して、テーブルスペースを削除したいけど、テーブルスペースを削除するにはテーブルスペースに格納されているデータを別のテーブルスペースに移さないといけない!
そんな時に利用するALTER TABEL文を一気に作成するクエリです。
innodb_file_per_tableテーブルスペースの場合だけ、データ削除によってテーブルに空き領域が出来たときには、ちゃんと必要な分だけ容量を確保するようにMysqlは動きます。
テーブルスペースの場合は、空き容量を回収してくれないので、削除しないとダメなので、運用がちょっと面倒。特定のテーブルスペースにあるテーブルをinnodb_file_per_tableもしくは特定のディレクトリのテーブルスペースに一気に移動したい時に使うSQLを作成するSQL
SELECT a.NAME AS space_name, b.NAME AS table_name, REPLACE( CONCAT( "ALTER TABLE " , b.NAME , " TABLESPACE innodb_file_per_table;" ) , "/", ".") as "innodb_file_per_tableに移動するSQL", CONCAT( "CREATE TABLESPACE `" , REPLACE( b.NAME , "/", "_") , "` ADD DATAFILE '<テーブルスペースを作成するディレクトリ>", REPLACE( b.NAME , "/", "_") , ".ibd' FILE_BLOCK_SIZE=8192 Engine=InnoDB;" ) as "特定のディレクトリにテーブルごとにテーブルスペースを作成するSQL", CONCAT( "ALTER TABLE " , REPLACE( b.NAME , "/", "_") , " TABLESPACE = `" , REPLACE( b.NAME , "/", "_") , "`;" ) as "特定のディレクトリのテーブルごとのテーブルスペースにテーブルを移動するSQL" FROM information_schema.INNODB_SYS_TABLESPACES a, information_schema.INNODB_SYS_TABLES b WHERE a.SPACE = b.SPACE AND a.NAME LIKE '<テーブルスペース名>' -- テーブルスペース単位で指定したい場合はこちら #AND b.NAME LIKE '<データベース名>%' -- データベース単位で指定したい場合はこちら ;
- 投稿日:2020-09-14T15:50:52+09:00
テーブルをinnodb_file_per_tableもしくは特定のディレクトリのテーブルスペースに一気に移動したい時に使うSQLを作成するSQL
データ容量が不足して、テーブルスペースを削除したいけど、テーブルスペースを削除するにはテーブルスペースに格納されているデータを別のテーブルスペースに移さないといけない!
そんな時に利用するALTER TABEL文を一気に作成するクエリです。
innodb_file_per_tableテーブルスペースの場合だけ、データ削除によってテーブルに空き領域が出来たときには、ちゃんと必要な分だけ容量を確保するようにMysqlは動きます。
テーブルスペースの場合は、空き容量を回収してくれないので、削除しないとダメなので、運用がちょっと面倒。テーブルをinnodb_file_per_tableもしくは特定のディレクトリのテーブルスペースに一気に移動したい時に使うSQLを作成するSQL
SELECT a.NAME AS space_name, b.NAME AS table_name, CONCAT( "ALTER TABLE " , REPLACE( b.NAME , "/", "_") , " TABLESPACE innodb_file_per_table;" ) as "innodb_file_per_tableに移動するSQL", CONCAT( "DROP TABLESPACE " , a.NAME , " ENGINE=INNODB;" ) as "テーブルスペースを削除るSQL", CONCAT( "CREATE TABLESPACE `" , REPLACE( b.NAME , "/", "_") , "` ADD DATAFILE '<テーブルスペースを作成するディレクトリ>", REPLACE( b.NAME , "/", "_") , ".ibd' FILE_BLOCK_SIZE=8192 Engine=InnoDB;" ) as "特定のディレクトリにテーブルごとにテーブルスペースを作成するSQL", CONCAT( "ALTER TABLE " , REPLACE( b.NAME , "/", "_") , " TABLESPACE = `" , REPLACE( b.NAME , "/", "_") , "`;" ) as "特定のディレクトリのテーブルごとのテーブルスペースにテーブルを移動するSQL" FROM information_schema.INNODB_SYS_TABLESPACES a, information_schema.INNODB_SYS_TABLES b WHERE a.SPACE = b.SPACE AND a.NAME LIKE '<テーブルスペース名>' -- テーブルスペース単位で指定したい場合はこちら #AND b.NAME LIKE '<データベース名>%' -- データベース単位で指定したい場合はこちら #AND b.NAME NOT IN ('<除外したいテーブル名>') ;
- 投稿日:2020-09-14T10:11:57+09:00
【第二回】SpringとMySqlとMyBatisの連動方法
はじめに
DreamHanksの松下です。今回はSpringとMySqlとMyBatisの連動方法を解説していきます。
xmlファイルの設定
新規でプロジェクトを作った際にデフォルトで生成される3つのxmlファイルをカスタマイズしていきます。
◆pom.xmlの設定
下記のdependency(依存するライブラリ)をデフォルトで生成されたpom.xmlの<dependencies>タグの中にコピペしてください。
pom.xmlの詳しい内容は下記の記事で解説しています。
Mavenの解説<!-- MySQL --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version> </dependency> <!-- MyBatis 3.4.1 --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <!-- MyBatis-Spring --> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- Spring-jdbc --> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${org.springframework-version}</version> </dependency> <!-- Mybatis log --> <!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4.1 --> <dependency> <groupId>org.bgee.log4jdbc-log4j2</groupId> <artifactId>log4jdbc-log4j2-jdbc4</artifactId> <version>1.16</version> </dependency>上記pomの解説
<!-- MySQL --> Mysql(DB)と接続するためのdependency
<!-- MyBatis 3.4.1 --> MyBatisを使うためのdependency
<!-- MyBatis-Spring --> MyBatisとSpringフレームワークを連動するためのdependency
<!-- Spring-jdbc --> SpringJdbcで使うためのdependency
<!-- Mybatis log --> MyBatisのログを出すためのdependency◆root-context.xmlの設定
デフォルトの状態
root-context.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Root Context: defines shared resources visible to all other web components --> </beans>設定後の状態
root-context.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <!-- Root Context: defines shared resources visible to all other web components --> <context:component-scan base-package="com.dreamhanks" /> <context:component-scan base-package="com.dreamhanks.service" /> <!-- MySQL dataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property> <property name="url" value="jdbc:log4jdbc:mysql://localhost:3306/work_db?useSSL=false&serverTimezone=UTC"></property> <property name="username" value="root"></property> <property name="password" value="Daiki8863"></property> </bean> <!-- mybatis SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property> </bean> <!-- mybatis --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> </bean> </beans>①設定後の状態のroot-context.xmlをコピペしてください。
②<!-- MySQL dataSource -->の設定
・下記のvalue値を自分のmysqlの環境に合わせる<property name="url" value="jdbc:log4jdbc:mysql://localhost:3306/work_db?useSSL=false&serverTimezone=UTC"></property> <property name="username" value="root"></property> <property name="password" value="Daiki8863"></property>特にみるべきところ
・work_db → カレントスキーマ
・username, passwordを自分のmysqlの環境に合わせる。③パッケージ名などは自分の環境にあわせること
root-context.xmlの詳しい内容は「xmlファイルの解説」という記事内で解説しています。(2020/09/11工事中)
<context:component-scan base-package="com.dreamhanks" /> <context:component-scan base-package="com.dreamhanks.service" />◆servlet-context.xmlの設定
servlet-context.xml<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/views/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> <context:component-scan base-package="com.dreamhanks.workmanager" /> </beans:beans>①特に設定すべき個所はありませんが、下記の内容が自分の環境と合っているかを確認してください
<context:component-scan base-package="com.dreamhanks.workmanager" />servlet-context.xmlの詳しい内容は「xmlファイルの解説」という記事内で解説しています。(2020/09/11工事中)
- 投稿日:2020-09-14T04:36:05+09:00
EC2内でローカルと同じGemをインストールしようとしたらエラーが起きた
ポートフォリオ用に作成したアプリをAWSにデプロイする際にEC2環境にGemをインストールしようとした時に下記のエラーが発生したので、解決方法をメモしておく。
bundle installを実行して、ローカルと同じGemをインストールしようとしたら下記のエラーが発生した。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.3/ext/mysql2 /home/ec2-user/.rbenv/versions/2.5.1/bin/ruby -r ./siteconf20200913-26933-1jq0rwz.rb extconf.rb checking for rb_absint_size()... yes checking for rb_absint_singlebit_p()... yes checking for rb_wait_for_single_fd()... yes checking for -lmysqlclient... no ----- mysql client is missing. You may need to 'sudo apt-get install libmariadb-dev', 'sudo apt-get install libmysqlclient-dev' or 'sudo yum install mysql-devel', and try again. ----- *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. Provided configuration options: --with-opt-dir --without-opt-dir --with-opt-include --without-opt-include=${opt-dir}/include --with-opt-lib --without-opt-lib=${opt-dir}/lib --with-make-prog --without-make-prog --srcdir=. --curdir --ruby=/home/ec2-user/.rbenv/versions/2.5.1/bin/$(RUBY_BASE_NAME) --with-mysql-dir --without-mysql-dir --with-mysql-include --without-mysql-include=${mysql-dir}/include --with-mysql-lib --without-mysql-lib=${mysql-dir}/lib --with-mysql-config --without-mysql-config --with-mysql-dir --without-mysql-dir --with-mysql-include --without-mysql-include=${mysql-dir}/include --with-mysql-lib --without-mysql-lib=${mysql-dir}/lib --with-mysqlclientlib --without-mysqlclientlib To see why this extension failed to compile, please check the mkmf.log which can be found here: /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/extensions/x86_64-linux/2.5.0/mysql2-0.5.3/mkmf.log extconf failed, exit code 1 Gem files will remain installed in /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.3 for inspection. Results logged to /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/extensions/x86_64-linux/2.5.0/mysql2-0.5.3/gem_make.out An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling. In Gemfile: mysql2どうやらMySQLがインストールできなかったらしく、このどれかのコマンドやったら直るかもとのことらしい。
解決策
mysql client is missing. You may need to 'sudo apt-get install libmariadb-dev', 'sudo apt-get install libmysqlclient-dev' or 'sudo yum install mysql-devel', and try again.エラーメッセージ内にあった上記の推奨コマンドの一つである
sudo yum install mysql-devel
を実行したら解決した。下記が出ればOK
In Gemfile: mysql2 [ec2-user@ip-10-0-0-142 trelog_app]$ sudo yum install mysql-devel 読み込んだプラグイン:priorities, update-motd, upgrade-helper amzn-main | 2.1 kB 00:00:00 amzn-updates | 3.8 kB 00:00:00 nodesource | 2.5 kB 00:00:00 依存性の解決をしています --> トランザクションの確認を実行しています。 ---> パッケージ mysql-devel.noarch 0:5.5-1.6.amzn1 を インストール --> 依存性の処理をしています: mysql55-devel >= 5.5 のパッケージ: mysql-devel-5.5-1.6.amzn1.noarch --> 依存性の処理をしています: /usr/bin/mysql_config のパッケージ: mysql-devel-5.5-1.6.amzn1.noarch --> トランザクションの確認を実行しています。 ---> パッケージ mysql55-devel.x86_64 0:5.5.62-1.23.amzn1 を インストール --> 依存性の処理をしています: real-mysql55-libs(x86-64) = 5.5.62-1.23.amzn1 のパッケージ: mysql55-devel- ............省略 ........ .... .. . 依存性関連をインストールしました: mysql55.x86_64 0:5.5.62-1.23.amzn1 mysql55-devel.x86_64 0:5.5.62-1.23.amzn1 mysql55-libs.x86_64 0:5.5.62-1.23.amzn1 mysql56-devel.x86_64 0:5.6.49-1.37.amzn1 完了しました!依存関係がいい感じになったっぽいので再度Gemをインストールすると無事にインストールできた。やったぜ。
- 投稿日:2020-09-14T00:15:37+09:00
Python + MySQL でコネクションプーリング
Python で MySQL とのコネクションプーリングを行う方法と、そのハマりどころについて。
mysql-connector-python の MySQLConnectionPool の問題
まず、MySQL 公式の Python クライアント mysql-connector-python で単純にコネクションを作成する場合は以下のように書ける。
import mysql.connector cnx = mysql.connector.connect(host="...", user="...", password="...", database="...")この mysql-connector-python には MySQLConnectionPool というクラスが用意されており、これを使うと簡単にコネクションプーリングができる。1
from mysql.connector.pooling import MySQLConnectionPool cnxpool = MySQLConnectionPool(host="...", user="...", password="...", database="...", pool_size=10) cnx = cnxpool.get_connection() cnx.close() # 実際にはコネクションは切断されず、コネクションプールにリリースされるめでたしめでたし・・・とはいかない。
試しに以下のコードを実行してみる。
from mysql.connector.pooling import MySQLConnectionPool cnxpool = MySQLConnectionPool(host="...", user="...", password="...", database="...", pool_size=3) cnxpool.get_connection() cnxpool.get_connection() cnxpool.get_connection() cnxpool.get_connection() #=> PoolError: Failed getting connection; pool exhaustedMySQLConnectionPool はプールのコネクションが枯渇した場合、例外を投げる仕様となっている。
このシンプルな仕様は嫌いではないのだけど、実際に Web アプリケーションなどで利用する際は「他のコネクションがリリースされるまで待つ」ような挙動であってくれたほうが嬉しいケースが多い。そうでないと、リクエスト処理の並列数が少しでもプールサイズを上回っただけでエラーが発生してしまう。
SQLAlchemy の QueuePool を使った解決策
この問題は、SQLAlchemy の QueuePool を使うと解決できる。2
from sqlalchemy.pool import QueuePool cnxpool = QueuePool(lambda: mysql.connector.connect(host="...", user="...", password="...", database="..."), pool_size=10) cnx = cnxpool.connect()QueuePool の第一引数は「DB API に対応したコネクションオブジェクト」を返す関数ならなんでもいいらしい。汎用的ですごい。
SQLAlchemy というモジュール自体は ORM だが、今回は ORM 部分を全く使わずに QueuePool という仕組みだけを利用している。
- 投稿日:2020-09-14T00:08:22+09:00
laravelでテスト用DBを設定する手順
ほとんどをよしなに手軽にやってくれるLaravelですが、
DBを使うphpunit設定はちょっと分かりにくいです。SQLSTATE[HY000] [1044] Access denied for user 'user'@'%' to database 'test_db'↑phpunitのコマンドでこんな表示があった人は、幸せにできる記事です。
※DBはmysql
設定のポイント
・テスト用のDB(スキーマ)を作る必要がある
・作成したスキーマに、テスト時に使う接続設定(ユーザー権限)を加える必要がある
・phpunit側に接続情報を加える必要がある1 テスト用のDBを作成する
ここではrootユーザーで接続している想定です。
CREATE SCEMA test_db;2 アクセス権限の設定
laravelの接続情報(.envに書く
DB_USERNAME
のとこ)がroot以外のユーザーの場合、
デフォルトではrootユーザーが作成したDBへのアクセス権限がない場合がある(rootユーザ以外でSHOW DATABASES
してもDB一覧に表示されない)。ので、rootユーザーでGRANT文を実行、アクセス権限を与えて、テストで使えるようにしてあげる
GRANT ALL ON test_db.* TO user(ユーザー名);もし権限を与えたいユーザー名がわからない時は、mysqlスキーマから確認
mysql> SHOW DATABASES; -- スキーマ一覧を表示 +--------------------+ | Database | +--------------------+ | information_schema | | app_db | | mysql | | performance_schema | | sys | | test_db | +--------------------+ mysql> use mysql; mysql> select * FROM user; -- ユーザーとHOST(どこからの接続を許容するか)、ユーザーが持つ権限も表示される※ アプリ用DBユーザとテスト用DBユーザを分けるメリットはそれほどないと思うので、laravelの
.env
に書いてあるユーザーでいいと思います。3 phpunit.xmlに接続情報を記入
あとは、
.env
に書いてある接続情報を、phpunit.xml
に書いてあげればOK!DB_DATABASE=db # アプリで使うDB DB_USERNAME=user DB_PASSWORD=pw
.env
に↑みたいに書いてあったら、↓のように書く。<php> <server name="APP_ENV" value="testing"/> <server name="BCRYPT_ROUNDS" value="4"/> <server name="CACHE_DRIVER" value="array"/> <server name="MAIL_DRIVER" value="array"/> <server name="QUEUE_CONNECTION" value="sync"/> <server name="SESSION_DRIVER" value="array"/> <!-- テストで使うDBのスキーマ名 --> <server name="DB_DATABASE" value="test_db"/> <!-- 接続するuserの名前 --> <server name="DB_USERNAME" value="user"/> <!-- 接続するuserのパスワード --> <server name="DB_PASSWORD" value="pw"/> </php>DBを使うテストファイルを実行してみましょう。
./vendor/bin/phpunit ./tests/Feature/DatabaseTest.php記事冒頭のエラーで困っていた人は、解決できているハズ!
その他phpunitの準備に役立ちそうな記事
おわりに
DBに接続する時の設定をする、という当然のことをしただけなんですが、人が用意してくれた自動化環境(AWSやらdocke)に慣れてしまうと、触れる機会が少なくなってしまうものです。
こういう基本的なとこに触れるのも、たまにはいいですよね。