- 投稿日:2019-05-24T23:19:41+09:00
Docker で Laravel開発環境
Nginxのconfを作成する
server { listen 80; root /usr/share/nginx/laravel/public; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ ^/.+\.php(/|$) { fastcgi_pass laravel-container:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }DockerでPHP-FPMを作成する
FROM php:7.3-fpm-alpine RUN apk add libzip-dev RUN docker-php-ext-configure zip --with-libzip RUN docker-php-ext-install pdo_mysql zipdocker-composeを作成する
version: "3.7" services: laravel: build: . container_name: laravel-container working_dir: /usr/share/nginx/laravel networks: - laravel-docker volumes: - ./laravel:/usr/share/nginx/laravel nginx: image: nginx:1.16-alpine container_name: reverse-proxy working_dir: /usr/share/nginx/laravel networks: - laravel-docker ports: - "8080:80" volumes: - ./default.conf:/etc/nginx/conf.d/default.conf - ./laravel:/usr/share/nginx/laravel mysql: image: mysql:8.0 container_name: mysql-server networks: - laravel-docker environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_DATABASE=homestead - MYSQL_USER=homestead - MYSQL_PASSWORD=secret ports: - 3306:3306 redis: image: redis:5.0-alpine container_name: redis-server networks: - laravel-docker ports: - 6379:6379 networks: laravel-docker: driver: bridge詳細は下記(ハンズオン)
- 投稿日:2019-05-24T22:59:53+09:00
HomesteadでRuby on Railsの環境構築
Homesteadはlaravelの開発環境を簡単に構築できるパッケージだが、Ruby on Railsで必要なソフトも入っているため、Homesteadを使用したRuby on Railsの環境を構築していく。
今回はMacで、使用するDBはMySQLとする。
Homesteadとは?
Laravel公式のboxで、Vgrantを使用することで仮想マシンにLaravelの開発環境を簡単に構築することができるパッケージです。
PHPやWebサーバ、その他のサーバソフトウェアをローカルマシンにインストールする必要なく、開発環境を構築できます。導入されているソフトウェア
公式より以下のソフトが既に含まれています。(2019/5 現在)
- Ubuntu 18.04
- Git
- PHP 7.3
- PHP 7.2
- PHP 7.1
- Nginx
- MySQL
- lmmによるMySQLとMariaDBデータベーススナップショット
- Sqlite3
- PostgreSQL
- Composer
- Node (Yarn、Bower、Bower、Grunt、Gulpを含む)
- Redis
- Memcached
- Beanstalkd
- Mailhog
- avahi
- ngrok
- Xdebug
- XHProf / Tideways / XHGui
- wp-cli
- Minio
オプションで導入できるソフトウェア
- Apache
- Crystal & Lucky Framework
- Dot Net Core
- Elasticsearch
- Go
- MariaDB
- MongoDB
- Neo4j
- Oh My Zsh
- Ruby & Rails
- Webdriver & Laravel Dusk Utilities
- Zend Z-Ray
VirtualBoxとVagrantのインストール
VirtualBoxをインストール
仮想化ソフトは他にもいくつかあるそうですが「VirtualBox」を使用
インストールはこちらから >> https://www.virtualbox.org/
自分の使用しているOSを選択
【注意】
「機能拡張がブロックされました」と表示されたら「システム環境設定」→「セキュリティとプライバシー」から読み込みを許可しましょうVagrantをインストール
Vagrantとは仮想化ソフト(VirtualBox)を使用し、コマンドを入力することで仮想環境を管理したり構築したりすることができるツールです。
インストールはこちらから >> https://www.vagrantup.com/
自分の使用しているOSを選択
ダウンロードしたらバージョンを確認してみる。
$ vagrant --version Vagrant 2.2.4これで2.2.4のVagrantがインストールされました。
Homesteadのboxをインストール
boxとはOSのディスクイメージファイルで、これを追加することで仮想環境を作成できる。
https://app.vagrantup.com/laravel/boxes/homestead
上記のリンクの公式を確認すると「laravel/homestead」があるのでこれを取得する。
VagrantCloudにあるboxを追加する場合は名前だけでも良い。
$ vagrant box add laravel/homestead
実行するとproviderは何かと聞かれるので「virtualbox」の「3」を選択する。
結構時間がかかるので終わるまで待つ。$ vagrant box add laravel/homestead ==> box: Loading metadata for box 'laravel/homestead' box: URL: https://vagrantcloud.com/laravel/homestead This box can work with multiple providers! The providers that it can work with are listed below. Please review the list and choose the provider you will be working with. 1) hyperv 2) parallels 3) virtualbox 4) vmware_desktop Enter your choice: 3 ==> box: Adding box 'laravel/homestead' (v7.2.1) for provider: virtualbox box: Downloading: https://vagrantcloud.com/laravel/boxes/homestead/versions/7.2.1/providers/virtualbox.box box: Download redirected to host: vagrantcloud-files-production.s3.amazonaws.com ==> box: Successfully added box 'laravel/homestead' (v7.2.1) for 'virtualbox'!Successfulluyとなったので、以下のコマンドでboxがちゃんと追加されたか確認する。
$ vagrant box list laravel/homestead (virtualbox, 7.2.1)Homesteadのファイルをダウンロード
ダウンロードしたファイルは任意のディレクトで良いが、今回はホームディレクトリの直下にダウンロードするので移動しておく。
$ cd $ pwd /Users/ユーザー名以下のコマンドでgithubからリポジトリをクローンします。
$ git clone https://github.com/laravel/homestead.git Homestead Cloning into 'Homestead'... remote: Enumerating objects: 59, done. remote: Counting objects: 100% (59/59), done. remote: Compressing objects: 100% (46/46), done. remote: Total 3606 (delta 37), reused 22 (delta 13), pack-reused 3547 Receiving objects: 100% (3606/3606), 782.03 KiB | 863.00 KiB/s, done. Resolving deltas: 100% (2190/2190), done.Homesteadの初期化
Homesteadは
Homestead.yaml
というファイルに色々書くことで、任意の設定をすることができる。
Homestead.yaml
は初期化することで生成される。ダウンロードしたHomesteadディレクトリに移動する。
中に色々なファイルが入っているが、初期化をしていないのでHomestead.yaml
が生成されていない。$ cd Homestead/ $ ls CHANGELOG.md Vagrantfile composer.lock phpunit.xml.dist scripts Homestead.yaml.example bin init.bat readme.md src LICENSE.txt composer.json init.sh resources tests以下のコマンドで初期化する。
$ bash init.sh Homestead initialized! $ ls CHANGELOG.md LICENSE.txt aliases composer.lock phpunit.xml.dist scripts Homestead.yaml Vagrantfile bin init.bat readme.md src Homestead.yaml.example after.sh composer.json init.sh resources tests
Homestead initialized!
と表示されたので、中を確認するとHomestead.yaml
が生成されている。SSH鍵のファイルの作成
ホストOSとゲストOSの通信はSSHで行うので、それに必要な鍵を作成する。
まずはホームディレクトリに移動して既に鍵があるかを確認。
$ cd $ ls -la | grep .ssh
id_rsa
とid_rsa.pub
が表示されれば、既にSSH鍵ファイルはあります。無い場合は以下のコマンドで作成する。
$ ssh-keygen -t rsa途中で
Enter file in which to save the key (/Users/ユーザー名/.ssh/id_rsa):
と保存するディレクトリを聞かれるので、そのままEnterを押す。次に
Enter passphrase
とパスフレーズを求められるので任意のパスフレーズを設定する。
Enter same passphrase again:
と再度確認を求められるので設定したパスフレーズを入力する。$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/Users/ユーザー名/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/ユーザー名/.ssh/id_rsa. Your public key has been saved in /Users/ユーザー名/.ssh/id_rsa.pub. The key fingerprint is: ...(以下省略)...ファイルキーが作成されたので、先ほどのコマンドで確認する。
$ ls -la | grep .sshHomesteadの設定
Homestead(仮想マシン)の各設定は、初期化した時に生成した
homestead.yaml
に記述します。Homesteadのディレクトリに移動し、vimで
Homestead.yaml
を編集。$ cd Homestead/ $ vim Homestead.yaml下記が
Homestead.yaml
のデフォルトのです。Homestead.yaml--- ip: "192.168.10.10" # IPアドレス memory: 2048 # 割り当てるメモリ cpus: 2 # 割り当てるCPU provider: virtualbox # 使用するプロバイダ # SSH公開鍵のパス authorize: ~/.ssh/id_rsa.pub # SSH秘密鍵のパス keys: - ~/.ssh/id_rsa # 共有ディレクトリの設定 # map: ホストマシン側で共有したいディレクトリ # to: ゲストマシン側で共有したいディレクトリ folders: - map: ~/code to: /home/vagrant/cod # Nginxサイトの設定 # map: アクセスするドメイン名の設定 # to: ゲストマシンNginxのドキュメントルートの設定 sites: - map: homestead.test to: /home/vagrant/code/public # 使用するDB名 databases: - homestead # ports: # - send: 50000 # to: 5000 # - send: 7777 # to: 777 # protocol: udp # blackfire: # - id: foo # token: bar # client-id: foo # client-token: barrails serverは3000なので、コメントアウトを外して新しく記述する。
ports: - send: 3000 to: 3000それ以外はデフォルトのままで使用しますが、共有ディレクトリの設定や、ドキュメントルートの設定などの変更が可能です。
デフォルトの
folders
だとホストマシンのホームディレクトリ直下にcode
ディレクトリが指定されていますが、現在code
ディレクトリがないので作成しておきます。今後プロジェクトフォルダを作成したときは、この
code
ディレクトリのなかに入ることになります。$ mkdir ~/code【注意】
sites
プロパティをHomestead boxのプロビジョニング後に変更した場合、仮想マシンのNginx設定を更新するため、vagrant reload --provision
を再実行する必要があります。ホスト名の設定
IPアドレス
192.168.10.10
にhomestead.test
というドメイン名で設定してあり、hosts
ファイルに追記することで、Webブラウザでhttp://homestead.test
にアクセスすることができる。MacとLinuxでは
/etc/hosts
にファイルがあるので追加していく。
アクセス権がないと保存できないので、sudo
をつけて192.168.10.10 homestead.app
を追記する。$ sudo vim /etc/hosts ## # Host Database # # localhost is used to configure the loopback interface # when the system is booting. Do not change this entry. ## 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost 192.168.10.10 homestead.testVagrant Boxの実行
各種設定が終わったら仮想マシンを起動します。
Homesteadのディレクトリ内に
Vagrantfile
があるので、違うディレクトリにいる場合は移動します。$ pwd /Users/ユーザー名/Homestead下記のコマンドで仮想マシンを起動する。
$ vagrant up Bringing machine 'homestead-7' up with 'virtualbox' provider... ==> homestead-7: Importing base box 'laravel/homestead'... ==> homestead-7: Matching MAC address for NAT networking... ==> homestead-7: Checking if box 'laravel/homestead' version '7.2.1' is up to date... ==> homestead-7: Setting the name of the VM: homestead-7 ==> homestead-7: Clearing any previously set network interfaces... ...(以下省略)...以下のコマンドで起動できているかを確認。
$ vagrant status Current machine states: homestead-7 running (virtualbox) The VM is running. To stop this VM, you can run `vagrant halt` to shut it down forcefully, or you can run `vagrant suspend` to simply suspend the virtual machine. In either case, to restart it again, simply run `vagrant up`.
running (virtualbox)
となっているので起動できていることが確認できます。あとは
ssh
コマンドで仮想マシンに入ります。$ vagrant ssh Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-47-generic x86_64) Thanks for using _ _ _ | | | | | | | |__ ___ _ __ ___ ___ ___| |_ ___ __ _ __| | | '_ \ / _ \| '_ ` _ \ / _ \/ __| __/ _ \/ _` |/ _` | | | | | (_) | | | | | | __/\__ \ || __/ (_| | (_| | |_| |_|\___/|_| |_| |_|\___||___/\__\___|\__,_|\__,_| * Homestead 8.4.0 released! * Settler v7.2.1 released! Make sure you update 0 packages can be updated. 0 updates are security updates. Last login: Thu May 24 08:54:14 2019 from 10.0.2.2 vagrant@homestead:~$無事に仮想マシンに入れたので、あとはRailsの環境を構築していきます。
Ruby on Railsの環境を構築
Homesteadが立ち上がったのであとは必要なソフトなどを入れていくが、既にあるのがほとんどなので
rbenv
等を入れていく。必要なライブラリをインストール
Ubuntu自体をアップデート(最新化)します。
$ sudo apt update今回はMysqlを使用するので、必要な関連パッケージをインストール
$ sudo apt install mysql-server mysql-client $ sudo apt install libmysqlclient-devRubyインストール
rbenvをインストール
rbenvとは、Rubyの「インストール」と「バージョン切替」を簡単におこなえるようにするためのツールです。
Gitを使ってrbenvをインストールします
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv Cloning into '/home/vagrant/.rbenv'... remote: Enumerating objects: 15, done. remote: Counting objects: 100% (15/15), done. remote: Compressing objects: 100% (11/11), done. remote: Total 2759 (delta 4), reused 8 (delta 4), pack-reused 2744 Receiving objects: 100% (2759/2759), 528.92 KiB | 874.00 KiB/s, done. Resolving deltas: 100% (1724/1724), done.インストールできたらrbenvコマンドが使えるように設定する
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile $ exec $SHELL -lrbenvコマンドが使えるようになったか確認する
$ rbenv --version rbenv 1.1.2-2-g4e92322Rubyをビルドするために使うプラグインの「ruby-build」をインストール
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build Cloning into '/home/vagrant/.rbenv/plugins/ruby-build'... remote: Enumerating objects: 38, done. remote: Counting objects: 100% (38/38), done. remote: Compressing objects: 100% (25/25), done. remote: Total 9750 (delta 14), reused 29 (delta 8), pack-reused 9712 Receiving objects: 100% (9750/9750), 2.08 MiB | 2.10 MiB/s, done. Resolving deltas: 100% (6340/6340), done.インストールできるRubyのバージョンを確認する
$ rbenv install --list Available versions: 1.8.5-p52 1.8.5-p113 1.8.5-p114 1.8.5-p115 1.8.5-p231 1.8.6 1.8.6-p36 1.8.6-p110 1.8.6-p111 1.8.6-p114 ...(途中省略)... 2.5.4 2.5.5 2.6.0-dev 2.6.0-preview1 2.6.0-preview2 2.6.0-preview3 2.6.0-rc1 2.6.0-rc2 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0-dev jruby-1.5.6 jruby-1.6.3 ...(以下省略)...バージョンを指定してRubyをインストール。
終わったら仮想マシンにインストールされているRubyのバージョンを確認します。$ rbenv install -v 2.6.3 /tmp/ruby-build.20190524115043.18071 ~ Downloading ruby-2.6.3.tar.bz2... -> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.bz2 Installing ruby-2.6.3... /tmp/ruby-build.20190524115043.18071/ruby-2.6.3 /tmp/ruby-build.20190524115043.18071 ~ checking for ruby... /home/vagrant/.rbenv/shims/ruby config.guess already exists config.sub already exists checking build system type... x86_64-pc-linux-gnu ...(以下省略)... $ rbenv versions * system (set by /home/vagrant/.rbenv/version) 2.6.3インストールされているのを確認できたら、仮想マシン全体で有効にするRubyのバージョンを指定する。
ディレクトリごとに指定する場合は
global
ではなく、有効にしたいディレクトリでlocal
を指定する。$ rbenv global 2.6.3 $ rbenv versions system * 2.6.3 (set by /home/vagrant/.rbenv/version)アスタリスクが移動しました。
ちゃんと最新バージョンがインストールされたかを確認$ ruby -v ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]bundlerのインストール
bundlerはプロジェクトごとで使うgemを、インストールしたり使用したりする。
どのバージョンが必要なのかは、プロジェクトフォルダにあるGemfile
を読み取りることで実行される。bundlerはRubyGemsからインストールできるので
gem
コマンドでインストールする。
bundle
コマンドが使えるようになるので確認する。$ gem install bundler Fetching bundler-2.0.1.gem Successfully installed bundler-2.0.1 Parsing documentation for bundler-2.0.1 Installing ri documentation for bundler-2.0.1 Done installing documentation for bundler after 2 seconds $ bundle -v Bundler version 2.0.1Ruby on Railsのインストール
Ruby on Railsは、
gem
コマンドでインストールする。
最新ではないバージョンを指定したい場合は-v
オプションをつけて指定。インストールが終わったら
rails
コマンドが使用できるので確認する。$ gem install rails Fetching i18n-1.6.0.gem Fetching rack-2.0.7.gem ...(途中省略)... Removing ruby (1:2.5.1) ... Removing ruby2.5 (2.5.1-1ubuntu1.2) ... Removing libruby2.5:amd64 (2.5.1-1ubuntu1.2) ... Removing rake (12.3.1-1) ... Removing ruby-test-unit (3.2.5-1) ... Processing triggers for libc-bin (2.27-3ubuntu1) ... Processing triggers for man-db (2.8.3-2ubuntu0.1) ... $ rails -v Rails 5.2.3Railsアプリを作成
Homestead.yaml
で共有ディレクトリの設定がすでにできているので、code
ディレクトリ内にファイルを作る。$ cd $ cd code/今回は例として
test_app
というプロジェクトファイルを作成します。プロジェクトファイルは
rails new
というコマンドで作成でき、-d
オプションで使用するデータベースを指定できます。オプションを指定しない場合は「SQLite」というデータベースがデフォルトで使用されますが、今回は「Mysql」を使用するので以下のコマンドでファイルを作成します。
$ rails new test_app -d mysql create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile run git init from "." Initialized empty Git repository in /home/vagrant/code/test_app/.git/ create package.json create app ...(途中省略)... Using spring-watcher-listen 2.0.1 Using turbolinks-source 5.2.0 Using turbolinks 5.2.0 Using uglifier 4.1.20 Using web-console 3.7.0 Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. run bundle exec spring binstub --all * bin/rake: spring inserted * bin/rails: spring inserted $ ls test_app確認すると
test_app
というファイルが作成されています。Railsサーバーの起動
Railsサーバーはプロジェクトフォルダに移動して
rails s
コマンドで起動できます。しかしVagrant環境で仮想マシンを起動している場合は、
rails s -b 0.0.0.0
というコマンドでRailsサーバーを起動させます。localホスト以外からはアクセスできないため、
-b 0.0.0.0
オプションをつけて全てのIPアドレスを許可します。$ cd test_app/ $ rails s -b 0.0.0.0 => Booting Puma => Rails 5.2.3 application starting in development => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.12.1 (ruby 2.6.3-p62), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://0.0.0.0:3000 Use Ctrl-C to stopこのように表示されれば無事にサーバーが起動したことになります。
サーバーを停止したいときはCtrl + c
で停止することできます。ブラウザでアクセス
ドメイン名の設定もデフォルトでしてあるので、ブラウザには
homestead.test:3000
でアクセスできます。Mysqlのパスワードを設定
これはRailsアプリがMysqlにhomesteadユーザーでログインしようとした結果、「パスワードがない」と言われていることが原因です。
- データベース : homestead
- ユーザー名 : homestead
- パスワード : secret
Homesteadでは上記のようなデフォルトの設定があるので、データベースの設定ファイルにパスワードを記述します。
【注意】
サーバーを起動しているタブではコマンド操作ができないので、新たにタブを増やし再度ssh
で仮想マシンに接続します。データベースの設定ファイルは
config
ディレクトリの中にdatabase.yml
という名前で入っています。$ ls config/ application.rb credentials.yml.enc environments master.key spring.rb boot.rb database.yml initializers puma.rb storage.yml cable.yml environment.rb locales routes.rb $ vim config/database.ymlvimで開き
password
の所にsecret
を追記して保存します。database.yml# MySQL. Versions 5.1.10 and up are supported. # # Install the MySQL driver # gem install mysql2 # # Ensure the MySQL gem is defined in your Gemfile # gem 'mysql2' # # And be sure to use new-style password hashing: # https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html # default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: secret socket: /var/run/mysqld/mysqld.sock development: <<: *default database: test_app_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: test_app_test保存したらサーバーを一度停止し、再起動してからブラウザにアクセスしてみます。
データベース作成
再びアクセスしてみると先ほどのエラーはなくなりましたが、違うエラーが出てきました。
これは
Unknown database 'test_app_development'
とでていて、test_app_development
というデータベースが無いよと注意されています。Railsには
rails db:create
というコマンド存在していて、database.yml
に記述されている情報を元に、データベースを作成してくれます。これらはデフォルトで
プロジェクトフォルダ名_development
プロジェクトフォルダ名_test
という2つのデータベース名が記述されているので特に変更はせずに、先ほどの
rails db:create
コマンドを実行して上記の2つのデータベースを作成します。$ rails db:create Created database 'test_app_development' Created database 'test_app_test'データベースが作成されたので再度ブラウザにアクセスしてみます。
上記のように表示されれば成功です。これで問題なくアクセスができました。
あとはアプリケーション制作
これでHomesteadを使用したRuby on Railsの環境を構築できました。
あとは作成したフォルダでアプリケーションを作ってみてください。おまけ(gitのブランチ名の表示)
デフォルトだとブランチ名は表示されていないが、設定すれば表示される
vagrant@homestead:~/code/test_app$
vagrant@homestead ~/code/test_app (master *) $gitのブランチ名の表示をしたい場合は以下の処理を
.bash_profile
もしくは.bashrc
に追記する。.bash_profileか.bashrcに追記if [ -f /etc/bash_completion ]; then . /etc/bash_completion fi if [ -f /etc/bash_completion.d/git-prompt ]; then export PS1='\[\033[01;32m\]\u@\h\[\033[01;33m\] \w$(__git_ps1) \n\[\033[01;34m\]\$\[\033[00m\] ' else export PS1='\[\033[01;32m\]\u@\h\[\033[01;33m\] \w \n\[\033[01;34m\]\$\[\033[00m\] ' fi追記したら変更を反映させる
vagrant@homestead:~/code/test_app$ source ~/.bashrc vagrant@homestead ~/code/test_app (master *) $参考記事
- 投稿日:2019-05-24T21:19:10+09:00
[雑メモ]Socialiteとabraham/twitteroauthで複数アカウントでツイート
ログインと登録がTwitterからのみのアプリを作成していて、
こちらを参考にabraham TwitterOAuthと連携してみたものの、アクセストークンの取得がややこしい
Socialiteで簡単にログインと登録しつつ、取れるのでそれを用いてつぶやいてみる
Socialiteで参考にしたのはこちらSocialiteで登録・ログイン→トークン取得→TwitterOAuthでツイートの流れ
LoginController.phpclass LoginController extends Controller { use AuthenticatesUsers; public function __construct() { $this->middleware('guest')->except('logout'); } /** * 認証ページヘユーザーをリダイレクト * * @return \Illuminate\Http\Response */ public function redirectToProvider() { return Socialite::driver('twitter')->redirect(); } /** * ユーザーのアクセストークンを取得する * * @return \Illuminate\Http\Response */ public function handleProviderCallback() { try { $twitter_user = Socialite::driver('twitter')->user(); //アクセストークン取得 $token = $twitter_user->token; $token_secret = $twitter_user->tokenSecret; if ($twitter_user) { //ユーザーの取得または生成 $user = User::firstOrCreate(['twitter_id' => $twitter_user->id]); //最新状態に更新 $user->update( [ 'twitter_name' => $twitter_user->name, 'twitter_nickname' => $twitter_user->twitter_nickname, 'twitter_avatar_original' => $twitter_user->avatar_original, 'twitter_oauth_token' => $token, 'twitter_oauth_token_secret' => $token_secret ] ); Auth::login($user, true); return redirect()->route('activity.index')->with('success', 'ログインしました'); } } catch (Exception $e) { return redirect()->route('top')->with('error', 'Twitterアカウント取得に失敗しました'); } return redirect()->route('top')->with('erorr', 'エラーが発生しました。再度お試しください'); } public function logout() { Auth::logout(); return redirect()->route('top')->with('success', 'ログアウトしました'); } }あとはログイン後のページでつぶやいてやる
Hoge.phppublic function tweet() { $user = Auth::user(); $twitter_user = new TwitterOAuth( config('twitter.consumer_key'), config('twitter.consumer_secret'), $user->twitter_oauth_token, $user->twitter_oauth_token_secret ); //ツイートする $res = $twitter_user->post("statuses/update", [ "status" => 'ツイート内容' ]); }だいぶスッキリしました
アクセストークンはセッションに入れるのと、保存するのどっちが良いのか...
こちらはServiceProviderを作成して、Facadeで呼び出せるようにしているけど、アクセストークンが変わる場合のうまい書き方が思いつかないなにかアドバイスあればください
- 投稿日:2019-05-24T20:23:31+09:00
51歳からのプログラミング 備忘 吹き出し的なもの
吹き出し的なもの(以下、吹き出しという)を作ってみた。
入力欄を空欄で入力した時に、
吹き出しで「未入力です」ってアナウンスが
フェードインして入る、って感じで。・ 吹き出しを、cssで用意
・ 吹き出しのcssは、<input の後の <span に設定
・ 吹き出しのcssは、最初は非表示にしとく(display:none)
・ 吹き出したいときに、表示する(ここでは、submit時)そんな感じで作れそうだったので作った。
表示位置の設定と、フェードインアウト,
入力時には非表示状態、をコードしてるので、
ちょっと長いのが残念。
完成コードはこれ
でも、吹き出しをフェードアウトさせるところが気に入らない。いつか直そう。//------- jquery ---------- <script> $(function(){ var position,width; var $form=$('form'); var $inp =$('input[name="inp"]'); var $sp =$('span[name="sp"]'); $form.submit(function(){ if(!$inp.val()){ position=$inp.offset(); width =$inp.width(); $sp.text('未入力です'); $sp.css('display','inline'); $sp.offset({top :(position.top-1), left:(position.left+width+10), }); $sp.hide().fadeIn(100); return false; } }); $inp.on('keypress',function(){ $sp.fadeOut(100); }); }); </script> //---------------------------- //---------- css ------------- <style> .tip {display:none; color:white; background:blue; border-radius:5px; } </style> //---------------------------- //--------- html ------------- <form action="test" method="post"> {{csrf_field()}} // これはlaravel仕様です <input name="inp"> <span name="sp" class="tip"></span> </form>コードを打つだけで楽しい。
心が躍るような楽しさ。
こんな楽しいことがあったんだ。
- 投稿日:2019-05-24T19:46:27+09:00
PHP(Laravel) でエンドポイントをつくって、 Nuxt.js に渡す
// この記事は、 note に投稿した記事の再掲です。
ディレクトリ構成
Nuxt.js, Laravel 別々にディレクトリを作成し、それぞれ個別のプロジェクトとして扱います
- nuxt-project # Nuxt.js - Nuxt のファイルたち - laravel-project # Laravel - Laravel のファイルたちLaravel をさわる
はじめに、 Laravel を使ってエンドポイントを作る
Laravel をインストール
下記のコマンドを実行してインストールができる
$ cd /your/project/directory $ composer create-project laravel/laravel <project-name>パーミッションを変更
インストールしたら、 Laravel の
storage
ディレクトリとbootstrap/cache
ディレクトリのパーミッションを 777 に変更するディレクトリパーミッション
Laravelをインストールした後に、多少のパーミッションの設定が必要です。storage 下と bootstrap/cache ディレクトリをWebサーバから書き込み可能にしてください。設定しないとLaravelは正しく実行されません。Homestead仮想マシンを使用する場合は、あらかじめ設定されています。https://readouble.com/laravel/5.7/ja/installation.html#configuration
routes/api.php
にエンドポイントの記述を追加http://localhost:8000/api でアクセスできるようになる
Route::get('/api', function(){ $nokura = array( [ 'title' => '主役じゃない方の僕ら', 'story' => 'モブキャラ4人のギャグコメディ' ], [ 'title' => 'イデアの眷属', 'story' => 'スーツの人たちがたくさん出てくる' ], ); $array = array(); foreach($nokura as $item) { $title = $item['title']; $story = $item['story']; $arr = array( 'title' => $title, 'story' => $story ); array_push($array, $arr); } return $array; });Laravel を起動する
http://localhost:8000/api にエンドポイントができているはず
$ php artisan serve
次に、Nuxt.js をさわる
さきほど作った Laravel のエンドポイントから、Nuxt.js を使って情報を取得する
Nuxt.js をインストール
色々聞かれるので、
axios
をインストールすると良い$ yarn create nuxt-app <my-project>
axios
を追加インストール時に追加済なら飛ばします
$ yarn add -D @nuxtjs/axios
proxy-module
を追加$ yarn add -D @nuxtjs/proxy
nuxt.config.js
に設定を追加
/api
でアクセスしたら
開発環境の場合は http://localhost:8000/api
本番環境の場合は https://production-url/api
を表示してね という設定ですmodule.exports = { dev: (process.env.NODE_ENV !== 'production'), modules: [ '@nuxtjs/axios', '@nuxtjs/proxy', ], proxy: { '/api': (this.dev) ? 'http://localhost:8000' : 'https://production-url' }, axios: { }, }情報を取得する
Laravel で作成したエンドポイントを
asyncData()
で叩くと
routes/api.php
に記述した内容が取得できるindex.vue<template lang="pug"> div pre {{apiPost}} </template> <script> export default { async asyncData({ app }) { let data = await app.$axios.$get('/api') return { apiPost: data } }, } </script>おわり
- 投稿日:2019-05-24T19:24:11+09:00
LaravelでMySQLへのデータ挿入時にエラーが出た場合の対処法
はじめに
LaravelのSeederでテストデータを入力しようとした際に、次のエラーが発生した。
SQLSTATE[HY000]: General error: 1364 Field 'カラム名' doesn't have a default valueNOT NULLであるフィールドにNULLをInsertした事によりエラーが出たようだ。
今回はこの警告を無効化することで対処する。環境
- Laravel 5.5.45
- MySQL 5.7.26
対処法
config/database.php
のstrict
の値をfalse
に設定する。database.php'mysql' => [ // 略 // 'strict' => true, 'strict' => false, // 略 ],原因
strict
がtrue
になっていると、次のようにsql_mode
が設定される。mysql> select @@GLOBAL.sql_mode; +---------------------------------------------------------------------------------------+ | @@GLOBAL.sql_mode | +---------------------------------------------------------------------------------------+ | STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | +---------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
sql_mode
にSTRICT_TRANS_TABLES
が設定されていると、無効な値が挿入された場合にエラーを出すようになる。参考
- 投稿日:2019-05-24T18:22:48+09:00
Laravelで投稿アプリの機能を作成 ~ログインカスタマイズ編Ⅰ~
はじめに
【30分クッキング】Laravelで投稿アプリの機能を作成のCRUD編、リレーション編に引き続き、
今回はできる限り工程を取らずに、自分のページに遷移させていく方法を実装いたしましたので
紹介していきたいと思います前提
・前回のデータを元に修正していくので、一緒にデータを作りたい方は
下記から見ることをお勧めします
①https://qiita.com/ProgramingDai/items/cf6944f9cd0ac08f4e3e
②https://qiita.com/ProgramingDai/items/249acc8894079ee58268・今回はできる限り工数を割くため、既存のLoginCotrollerとlogin.blade.phpを利用します
実装イメージ
{root}/post ↓ 未認証 ↓ {root}/login ↓ 認証後 ↓ {root}/post ↓ ログアウト ↓ {root}/login実装レシピ
1.ログイン後のリダイレクト先変更
/app/Http/Controllers/Auth/LoginController.php// 中略 // protected $redirectTo = '/home'; // デフォルトリダイレクト先 protected $redirectTo = '/post'; // 変更後リダイレクト先 // 中略2.ログアウト後のリダイレクト先変更
今回はUserController.phpを新たに作成して実装します
php artisan make:controller UserController
/app/Http/Controllers/UserController.phpnamespace App\Http\Controllers; use Illuminate\Http\Request; // 追加 use Illuminate\Support\Facades\Auth; class UserController extends Controller { // ログアウト遷移先変更 public function getLogout(Request $request){ Auth::logout(); return redirect()->route('login'); } }3.ルーティング設定
/routes/web.php// 中略 Route::get('/logout', 'UserController@getLogout')->name('user.logout');4.ビューの修正
デフォルトでの「login.blade.php」の中身を全て変更していきます。/resources/views/auth/login.blade.php@extends('layouts.postapp') @section('content') @section('maincopy', 'ログインしてください') <form method="POST" action="{{ route('login') }}"> {{ csrf_field() }} @if ($errors->has('email')) {{ $errors->first('email') }} @endif <input type="text" class="form" name="email" placeholder="メールアドレス"> @if ($errors->has('password')) {{ $errors->first('password') }} @endif <input type="password" class="form" name="password" placeholder="パスワード"> <input type="submit" class="create" value="ログイン"> </form> @endsection5.新規登録とログアウトリンクの切り分け表示
ログインするためには新規登録画面とログアウトできるリンクが必要です
@if(Auth::check())
で現在認証中か否かを判定することができますこのページのどこでもいいので下記コードを追加してください
/resources/views/layouts/postapp.blade.php@if(Auth::check()) <!--認証中なら--> <a href="{{ route('user.logout') }}"><img src="{{ asset('img/logout.svg') }}" class="add" alt="ログアウト"></a> @else <!--未認証なら--> <a href="{{route('register')}}"><img src="{{ asset('img/user.svg') }}" class="add" alt="ユーザー登録"></a> @endif※imgの部分は通常のリンク文字にしてもOKです
※ボタンUIはこちらのサイトから無料でダウンロードしました
https://www.ikonate.com/あとがき
こんな感じ自動生成されるをページを利用すれば、遷移を変更していくだけで
オリジナルログイン画面の実装ができます。ログイン周りはこの他にも、「login.blade.php」を使わず
ビュー自体もオリジナルで実装する方法もありますので、興味があれば調べてみてください。
次回はregister(新規登録)周りのカスタマイズを実装していく予定ですので、ぜひ。Laravelで投稿アプリの機能を作成
~CRUD編~
https://qiita.com/ProgramingDai/items/cf6944f9cd0ac08f4e3e
~リレーション編~
https://qiita.com/ProgramingDai/items/249acc8894079ee58268
~ログインカスタマイズ編Ⅰ~
https://qiita.com/ProgramingDai/items/fee669e5a8cf67f0e38e
~ログインカスタマイズ編Ⅱ~
https://qiita.com/ProgramingDai/items/4fe2e3cc90987356c9c4参考書籍: PHPフレームワーク Laravel入門
https://blog.hiroyuki90.com/articles/laravel-books/
- 投稿日:2019-05-24T18:22:48+09:00
Laravelで投稿アプリの機能を作成 ~ログインカスタマイズ編~
はじめに
【30分クッキング】Laravelで投稿アプリの機能を作成のCRUD編、リレーション編に引き続き、
今回はできる限り工程を取らずに、自分のページに遷移させていく方法を実装いたしましたので
紹介していきたいと思います前提
・前回のデータを元に修正していくので、一緒にデータを作りたい方は
下記から見ることをお勧めします
①https://qiita.com/ProgramingDai/items/cf6944f9cd0ac08f4e3e
②https://qiita.com/ProgramingDai/items/249acc8894079ee58268・今回はできる限り工数を割くため、既存のLoginCotrollerとlogin.blade.phpを利用します
実装イメージ
{root}/post ↓ 未認証 ↓ {root}/login ↓ 認証後 ↓ {root}/post ↓ ログアウト ↓ {root}/login実装レシピ
1.ログイン後のリダイレクト先変更
/app/Http/Controllers/Auth/LoginController.php// 中略 // protected $redirectTo = '/home'; // デフォルトリダイレクト先 protected $redirectTo = '/post'; // 変更後リダイレクト先 // 中略2.ログアウト後のリダイレクト先変更
今回はUserController.phpを新たに作成して実装します
php artisan make:controller UserController
/app/Http/Controllers/UserController.phpnamespace App\Http\Controllers; use Illuminate\Http\Request; // 追加 use Illuminate\Support\Facades\Auth; class UserController extends Controller { // ログアウト遷移先変更 public function getLogout(Request $request){ Auth::logout(); return redirect()->route('login'); } }3.ルーティング設定
/routes/web.php// 中略 Route::get('/logout', 'UserController@getLogout')->name('user.logout');4.ビューの修正
デフォルトでの「login.blade.php」の中身を全て変更していきます。/resources/views/auth/login.blade.php@extends('layouts.postapp') @section('content') @section('maincopy', 'ログインしてください') <form method="POST" action="{{ route('login') }}"> {{ csrf_field() }} @if ($errors->has('email')) {{ $errors->first('email') }} @endif <input type="text" class="form" name="email" placeholder="メールアドレス"> @if ($errors->has('password')) {{ $errors->first('password') }} @endif <input type="password" class="form" name="password" placeholder="パスワード"> <input type="submit" class="create" value="ログイン"> </form> @endsection5.新規登録とログアウトリンクの切り分け表示
ログインするためには新規登録画面とログアウトできるリンクが必要です
@if(Auth::check())
で現在認証中か否かを判定することができますこのページのどこでもいいので下記コードを追加してください
/resources/views/layouts/postapp.blade.php@if(Auth::check()) <!--認証中なら--> <a href="{{ route('user.logout') }}"><img src="{{ asset('img/logout.svg') }}" class="add" alt="ログアウト"></a> @else <!--未認証なら--> <a href="{{route('register')}}"><img src="{{ asset('img/user.svg') }}" class="add" alt="ユーザー登録"></a> @endif※imgの部分は通常のリンク文字にしてもOKです
※ボタンUIはこちらのサイトから無料でダウンロードしました
https://www.ikonate.com/あとがき
こんな感じ自動生成されるをページを利用すれば、遷移を変更していくだけで
オリジナルログイン画面の実装ができます。ログイン周りはこの他にも、「login.blade.php」を使わず
ビュー自体もオリジナルで実装する方法もありますので、興味があれば調べてみてください。
次回はregister(新規登録)周りのカスタマイズを実装していく予定ですので、ぜひ。Laravelで投稿アプリの機能を作成
~CRUD編~
https://qiita.com/ProgramingDai/items/cf6944f9cd0ac08f4e3e
~リレーション編~
https://qiita.com/ProgramingDai/items/249acc8894079ee58268
~ログインカスタマイズ編~
https://qiita.com/ProgramingDai/items/fee669e5a8cf67f0e38e参考書籍: PHPフレームワーク Laravel入門
https://blog.hiroyuki90.com/articles/laravel-books/
- 投稿日:2019-05-24T16:09:17+09:00
LaravelでbrongsToManyしてみた。3 <タグから関連記事を取得>
- 中間テーブルの構成を作成
- 関連したタグを取得
- コレ
- まだあるかも。。
※前回までの物がない人は一読を推奨します。
タグの選択(ボタン要素を追加)
index.blade.php
<a href="twiite?tag={{ $tag }}" style="color: inherit"> <p style="display: inline-block; margin-left: 10px; border: 1px solid #5fa; max-width: 100px"> {{ $tag }} </p> </a>タグの項目をaタグで囲んでみました。
今回はルートを通してないので、クエリでタグを持たせたいと思います。
ここでのリンクは例えば「https: //localhost:8080/twiite?tag=令和」などです。クエリーデータを取得する場合以下があります。
$_GET['tag'];//html上 や __construct(Request $request){ $request->tag; }//php上 などです。ModelにbelongsToManyを追加
記事からやったのとまったく逆をやればいいのです。そう単純な話なのです。
ただ、attacheに関しては中間テーブルに記録する作業をタグからする意味も必要もないので、
そこは違うところです。あくまで今回は記事取得になります。
Tag.php に追加public function twiites() { return $this->belongsToMany(Twiite::class); }前と逆ですね。。これで、中間テーブルを使うことができます。
TwiiteController.php
public function index(Request $request) { //省略... + if(!empty($request->tag)){//タグ情報がクエリで来ている場合。(検索) + $oneTagRecorde = $this->tag->where('name', $request->tag) + ->first();//タグを押してここに入るので、一意で一つしかないと予想される。 + $twiiteList = $oneTagRecorde->twiites() + ->orderby('twiite_id') + ->get();//リレーションからタグに対応するツイートを全取得。 + } + else{ $twiiteList = $this->twiite->where('user_id',$userId) ->orderby('created_at','desc') ->get();//ツイート全件取得 + } //省略... return view('index', compact('twiiteList', 'userId'));//index view }処理を通常時の全レコード取得から、特定タグ情報が入ったものだけに変更します。
ここで、送ったクエリデータを判定し、何か入っていれば、タグ検索を
入っていなければ、通常の全レコード取得をするという流れになります。
その後の処理は前と待ったく同じです。。投稿一覧 選択タグ色付けなど
選択して、関連記事が表示されるときに、
そのアクションを検知して、選択されているタグが赤くなるようにしてみますか。。
そして、どんな順番だろうと、選択タグが先頭に来るようにしましょう。TwiiteController.phpのindex()
public function index(Request $request) { foreach($twiiteList as $twiiteRecord){ $tags = $twiiteRecord->tags()->orderby('tag_id')->get();//中間テーブル経由でタグのrecordを取得 $tagName = []; + $exchangeArray = 0;//先頭になるタグ名の番号 foreach($tags as $tagRecord){//タグも複数あるので、繰り返す。 $tagName[] = $tagRecord->name;//取得してきたレコードのid + if($request->tag === $tagRecord->name)//タグ名が選択タグと一致 + $exchangeArray = count($tagName) - 1;//現在保存されているタグの場所n番目 } + if($exchangeArray != 0){//先頭入れ替え + $name = $tagName[0]; + $tagName[0] = $tagName[$exchangeArray]; + $tagName[$exchangeArray] = $name; + } $twiiteRecord['tags'] = $tagName;//送るデータに追加(同foreachで回すため) } return view('index', compact('twiiteList', 'userId'));//index view }検索タグがあれば、その番号を保存しておいて、先頭と入れ替える
という処理を追加。
そのほかデータの取得などは前々回と同じことなので、コメントアウトと、前のを見てください。
index.blade.php<?php $first = true; ?> @foreach($twiite->tags as $tag) <a href="twiite?tag={{ $tag }} " style=" <?php echo !empty($_GET['tag']) & $first ? 'color: red' : 'color: inherit'?> "> <?php $first = false; ?> <p style="display: inline-block; margin-left: 10px; border: 1px solid #5fa; max-width: 200px"> {{ $tag }} </p> </a> @endforeach先頭に検索タグを持ってきたので、foreachのループ一回目だけ行いたいので、
$first = true;とかしています。
方法は好きなやり方で、やってください。
今回は三項演算子を使って、ifをしています。
ここでの条件は、クエリにタグ情報があるか? かつ 一回目か(初期のtrueか)?
これで、なければそのまま黒字に、あれば、先頭だけ赤文字になります。完成
一通りやりたい機能は達成できました。
- 記事にタグを追加して保存、そのリレーション。
- 中間テーブルから関連タグを取得してきて、表示。
- タグからの記事検索。
- 検索結果の表示結果整形。基本はもう動きますね。ただ、コードが汚いのと、長いので、まだ改良はできますが、
まあ、良しとしましょう。。w
今回一連の記事の流れは以上、記事とタグの中間テーブルが使いてぇという内容です。完結!こちらに動かした動画がありますので、どうぞ参考に。
※音無しです。
今回のコードは
gitに挙げてますので、どんどん使ってください。issueしていただいても結構ですよー。
本場で働いているので、まあ、答えられる範囲で答えます。では。。次回は
あるかも。。一通り削除とかも付けてみようか?なんて思ってます。
ちょっと動かしておくのも面白いかと。。。
やるかわからないですwーー追記ーー
本記事シリーズの完成版はこちら。gitの管理をしっかりしました。
https://github.com/175B005/vueLaravelまた違うのをやっていくので、ここのブランチはvue.jsで追加していく用です。
belongstomanyというブランチでここまでを残しておきますので、
どうぞよろしくお願いします。
- 投稿日:2019-05-24T15:37:53+09:00
LaravelでbrongsToManyしてみた。2 <関連したタグを取得>
※基本的な内容は前回の記事にあるので、要参照です。
今回の追加 Controllerファイルindex内+index.blade.phpのみ
追加範囲全部↓
TwiiteController.php
public function index(Request $request) { $userId = Auth::id();//ログイン中のid $twiiteList = $this->twiite->where('user_id',$userId) ->orderby('created_at','desc') ->get();//ツイート全件取得 + foreach($twiiteList as $twiiteRecord){ + + $tags = $twiiteRecord->tags()->orderby('tag_id')->get();//中間テーブル経由でタグのrecordを取得 + + $tagName = []; + foreach($tags as $tagRecord){//タグも複数あるので、繰り返す。 + $tagName[] = $tagRecord->name;//取得してきたレコードのid + } + $twiiteRecord['tags'] = $tagName;//送るデータに追加(同foreachで回すため) + } return view('index', compact('twiiteList', 'userId'));//index view }index.php
<h1>ーーーあなたのツイート一覧ーーー</h1> @foreach ($twiiteList as $twiite) <div style="border: 1px solid #000; display: block; width: 400px; margin-top: 2px"> <p style="display: inline-block">{{ $twiite->contents }}</p> </div> + @foreach($twiite->tags as $tag) + <p style="display: inline-block; margin-left: 10px; border: 1px solid #5fa; width: 100px">{{ $tag }}</p> + @endforeach @endforeachbelongsToMany型のオブジェクト取得からのタグ取得。
$tags = $twiiteRecord->tags()->orderby('tag_id')->get(); //インスタンスオブジェクトからorderby()->get()をして、中間テーブルに対応する //タグのデータをすべて取得してきました。要するに、attacheでやっていた扱い方と全く一緒。
getすればrecordが取得できるぜ。というお話です。全件のタグを取得
foreachで回しているので、記事全件から一件ずつタグを見に行く。
さらにタグは複数あると想定されるので、(そうじゃなきゃやらないw)
タグの取得後に、記事のデータに付随させて送りたかったので、
foreachで回して、対応した記事に配列として追加。
あとはコメントアウトで細かく見てください。別で送れますが、別で送ると、整合性がなくなる可能性がありますし、
何より細かい作業するようになると、一度に扱えた方が便利です。タグを表示
cssは面倒なので書いてません。インラインで申し訳ない。。
記事の中に入れて持ってきたので、foreach内でタグの数だけ表示をしています。次回は
次回は逆の取得をします。タグをクリックすると、その関連記事が出てくるようにしたいと思います。
- 投稿日:2019-05-24T10:25:19+09:00
LaravelでbrongsToManyしてみた。
環境
- Laravel5.6
- mysql5.7
- nginx
- composer
- php
今回やること
- 多対多の中間テーブルを作り、attachをすること。
- 記事に紐づくタグを作る。
- 大したことはやってないです。確認程度に眺めてください。
使用メソッド
- belongsToMany
- attach
- firstOrCreate
作るDB構成
記事 --- 中間テーブル --- タグ --- id --- id ---> twiite_id --- user_id tag_id <--- id contents --- --- --- --- name time time time 端的に言うと---
--twiite table--
id user_id contents tag1 tag2 tag3 tag4 tag5 1 1 1コメやったぜ first --- --- --- --- 2 1 laravelの記事を書いています。 laravel mysql php composer framework 3 2 ホンダ シビッグ(車) ほんだし ビッグ(だし) ほんだし ホンダ 本田 --- --- と管理すると、無駄な枠がいくつもできてしまいますよね。。
そして、5コと設定したら、DBを変えるまで、5コです。
これでは、変更があってもすぐに対応できませんので分けて管理します。やっていく。。
※プロジェクトがある前提で進めます。
今回作るプロジェクトはこれ
(vendorファイルと.envがそのままなので、消してからcomposer install してください。)必要なファイルを作成
php artisan make:model -mrc <記事名> php artisan make:model -mrc <タグ名> php artisan make:migrate <中間テーブル名>複数記事と複数タグのリレーションをします。
必要そうなマイグレーションファイルやコントローラなども面倒なので、オプション付けて、一緒に作ってしまいましょう。
中間テーブルはテーブルを作成できれば、あとはいらないので、付属ファイルは作らないでOK。まずはDBを整える
<日付>_<記事名>table.php
//<記事名> = twiite class CreateTwiitesTable extends Migration { public function up() { Schema::create('twiites', function (Blueprint $table) { $table->increments('id'); $table->Integer('user_id')->unsigned(); $table->string('contents'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('twiites'); } }<日付>_<タグ名>table.php
//<タグ名> = tag class CreateTagsTable extends Migration { public function up() { Schema::create('tags', function (Blueprint $table) { $table->increments('id'); $table->string('name', 20); $table->timestamps(); }); } public function down() { Schema::dropIfExists('tags'); } }<日付>_<中間テーブル名>table.php
<中間テーブル名> = twiitetag class CreateTwiiteTagTable extends Migration { public function up() { Schema::create('tag_twiite', function (Blueprint $table) { $table->increments('id'); $table->integer('twiite_id'); $table->integer('tag_id'); }); } public function down() { Schema::dropIfExists('tag_twiite'); } }マイグレーションファイルはこれで完成です。では、
php artisan migrateエラーが起きていなければ成功です。DBでも確認しましょう。
mysql -u ユーザ名 -p Password:******* mysql>use DB名 mysql>show tables;table に先ほどのテーブルが作られていれば、成功。
desc table <テーブル名>;これで、テーブルの制約が確認できますよ。
ルートを通します。
routes\web.php に追加
Route::resource('/twiite', TwiiteController::class,['except' => ['show', 'create']]);詳細の場所は好きにしてください。exceptで今回使わないので、除去しています。
表示を整えます。
超適当に機能だけを付けています。
<html> <head> <meta charset="utf-8"> <title>多:多</title> </head> <body> <form method="post"> {{ csrf_field() }} <input style="width:400px; height:100px" name="contents"><!--本文--> <input style="width:300px; height:30px" name="writelineTags" placeholder="「,」で区切って、タグ付けする(上限5コ)"><!--タグ文字列--> <input type="hidden" value=<?= $userId; ?> name="user_id"><!--ログイン中のid--> <button>投稿</button> </form> <h1>ーーーあなたのツイート一覧ーーー</h1> <div style="border: 1px solid #000; display: box; width: 400px"> @foreach ($twiiteList as $twiite) <p>{{ $twiite->contents }}</p><!--渡されたツイートデータ(なければ実行なし)--> @endforeach </div> </body> </html>Modelを作る
リレーションの設定は、DB個別でもできます。
直接sql文をたたくか、マイグレーションフィルに外部キーを設定でもできます。
が、しかし、せっかくフレームワークを使っているので、
生かさなければ!!
modelにて、その流れを肩代わりしてくれます。
外部キーなどをつくるわけではないので、そこは間違えないように!!<記事名>.php
class Twiite extends Model { protected $fillable = [ 'user_id', 'contents' ]; protected $dates = [ 'created_at', 'updated_at' ]; public function tags() { return $this->belongsToMany(Tag::class); } }外部キーがあれば、第二引数に設定したものが外部キーとして扱える。
今回はないが、リレーション相手のtagテーブルのidを保存しておきたいため、
idは外部キーではなく、indexの主キーでのアクセスとなる。今回のこのページで作っているのは、一方的なリレーションになるので、
tagからのhasmanyは無い。後で続編予定。。そこで、作る。。現状できないこと
- タグ情報から関連する記事を取得できない。
- タグを独自で作ったり、削除ができない。というか全く扱えないw
Controller を作る
最後に作るのはコントローラ!
最後でなくてもいいんだけど、DBの入出力と、フロントの表示が整ってから、必要なデータの処理を
する方が、わかりやすいと思うんだ。。。<記事>Controller.php
use App\Twiite; use App\Tag; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class TwiiteController extends Controller { protected $twiite; public function __construct(Twiite $twiite){ $this->middleware('auth');//ユーザ認証 $this->twiite = $twiite;//twiiteクラスのインスタンス化 } public function index(Request $request) { $userId = Auth::id();//ログイン中のid $twiiteList = $this->twiite->where('user_id',$userId) ->orderby('created_at','desc') ->get();//ユーザのtwiite全取得 return view('index', compact('twiiteList', 'userId'));//index view } public function store(Request $request) { $userId = Auth::id();//ログイン中のid $inputs = $request->all();//リクエスト全て if(!empty($inputs['writelineTags'])){ $tags = $this->setTagDivide($inputs['writelineTags']);//文字列を配列に分割「,」 $tag_ids = $this->getIds($tags);//分割したタグを作り(またはカウントを追加し、)、そのidを取得 } $this->twiite->contents = $inputs['contents'];//contentsデータを追加 $twiite = $this->twiite->create($inputs);//twiiteデータ一件を作成&一件のデータを持つmodelのオブジェ クト取得 $twiite->tags()->attach($tag_ids);//中間テーブルに格納 return redirect()->to('twiite');//indexへリダイレクト } public function setTagDivide($tagstring){ $tags = explode(',',$tagstring);//文字列から特定の文字に応じて区切り、配列として格納。 return $tags;//Is Array. } public function getIds($tags){ $tagClass = new Tag();//tagを扱うクラスをインスタンス化 $recodes = [];//帰り値の初期化 $count = 5; foreach($tags as $tag){ $count--;//カウント if($count <= 0) exit;//上限を超える場合は強制退場 $aleadyTag = $tagClass->firstOrCreate(['name' => $tag]);//あれば取得、なければ作成。 $aleadyTag->increment('counts'); $recodes[] = $aleadyTag->id; } // dd($recodes);//tag_id,tag_id,tag_id.. return $recodes; } }※Authはユーザ認証のメソッドです。
ユーザーは一人ではないので、そのidなどを判定するために使っています。
処理にはAuthやmidlewereなどは直接関係ないです。見る人が見ると、「はあ?」と怒られてしまいそうな記述ですが、
急ぎ説明用に作ったものなので、ご容赦を。。とりあえず、それぞれ横に書いてあるdirectionの通りの意味です。
詳細は自分で調べてください。今回重要なのは、ここ。
$twiite = $this->twiite->create($inputs); $twiite->tags()->attach($tag_ids);$this->twiiteは、いわばnew Twiite() やTwiite::Classで作れるもののことで、モデルクラスをインスタンス化したものです。
createメソッドは返り値が追加したデータを持つ、モデルクラスのオブジェクトなので、
今回は1件のデータをattributeに持つ、オブジェクトになります。当然モデルクラスにデータが入っているだけなので、インスタンスとは何ら機能に変化はありません。
そこから、先ほど<記事名>.phpで行った、tags()というメソッドを使い、
アタッチをしています。。
attacheを扱っているのは<記事名>クラスなので、その(指定がなければidになる)id、
attacheで送るデータは()内に入った、タグのid。attacheメソッドは引数が配列データで送れるので、その場合は、複数個中間テーブルに保存されることになります。
ex)記事1個目にタグが複数ある場合。
twiite_id tag_id 1 1 1 2 1 3 1 4 2 4 こんな感じで、中間テーブルが同一の記事idに複数一気に作成されます。
中間テーブルの利用。
登録をしただけじゃ、何の意味もないので、これを呼び出す必要もあります。
が、今回はこのへんで! 次回の記事に続きを書いていきますので、そちらも見てください。
- 投稿日:2019-05-24T10:25:19+09:00
LaravelでbrongsToManyしてみた。1 <中間テーブルの構成を作成・一方向からのリレーション>
環境
- Laravel5.6
- mysql5.7
- nginx
- composer
- php
今回やること
- 多対多の中間テーブルを作り、attachをすること。
- 記事に紐づくタグを作る。
- 大したことはやってないです。確認程度に眺めてください。
使用メソッド
- belongsToMany
- attach
- firstOrCreate
作るDB構成
記事 --- 中間テーブル --- タグ --- id --- id ---> twiite_id --- user_id tag_id <--- id contents --- --- --- --- name time time time 端的に言うと---
--twiite table--
id user_id contents tag1 tag2 tag3 tag4 tag5 1 1 1コメやったぜ first --- --- --- --- 2 1 laravelの記事を書いています。 laravel mysql php composer framework 3 2 ホンダ シビッグ(車) ほんだし ビッグ(だし) ほんだし ホンダ 本田 --- --- と管理すると、無駄な枠がいくつもできてしまいますよね。。
そして、5コと設定したら、DBを変えるまで、5コです。
これでは、変更があってもすぐに対応できませんので分けて管理します。やっていく。。
※プロジェクトがある前提で進めます。
今回作るプロジェクトはこれ
(vendorファイルと.envがそのままなので、消してからcomposer install してください。)必要なファイルを作成
php artisan make:model -mrc <記事名> php artisan make:model -mrc <タグ名> php artisan make:migrate <中間テーブル名>複数記事と複数タグのリレーションをします。
必要そうなマイグレーションファイルやコントローラなども面倒なので、オプション付けて、一緒に作ってしまいましょう。
中間テーブルはテーブルを作成できれば、あとはいらないので、付属ファイルは作らないでOK。まずはDBを整える
<日付>_<記事名>table.php
//<記事名> = twiite class CreateTwiitesTable extends Migration { public function up() { Schema::create('twiites', function (Blueprint $table) { $table->increments('id'); $table->Integer('user_id')->unsigned(); $table->string('contents'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('twiites'); } }<日付>_<タグ名>table.php
//<タグ名> = tag class CreateTagsTable extends Migration { public function up() { Schema::create('tags', function (Blueprint $table) { $table->increments('id'); $table->string('name', 20); $table->timestamps(); }); } public function down() { Schema::dropIfExists('tags'); } }<日付>_<中間テーブル名>table.php
<中間テーブル名> = twiitetag class CreateTwiiteTagTable extends Migration { public function up() { Schema::create('tag_twiite', function (Blueprint $table) { $table->increments('id'); $table->integer('twiite_id'); $table->integer('tag_id'); }); } public function down() { Schema::dropIfExists('tag_twiite'); } }マイグレーションファイルはこれで完成です。では、
php artisan migrateエラーが起きていなければ成功です。DBでも確認しましょう。
mysql -u ユーザ名 -p Password:******* mysql>use DB名 mysql>show tables;table に先ほどのテーブルが作られていれば、成功。
desc table <テーブル名>;これで、テーブルの制約が確認できますよ。
ルートを通します。
routes\web.php に追加
Route::resource('/twiite', TwiiteController::class,['except' => ['show', 'create']]);詳細の場所は好きにしてください。exceptで今回使わないので、除去しています。
表示を整えます。
超適当に機能だけを付けています。
<html> <head> <meta charset="utf-8"> <title>多:多</title> </head> <body> <form method="post"> {{ csrf_field() }} <input style="width:400px; height:100px" name="contents"><!--本文--> <input style="width:300px; height:30px" name="writelineTags" placeholder="「,」で区切って、タグ付けする(上限5コ)"><!--タグ文字列--> <input type="hidden" value=<?= $userId; ?> name="user_id"><!--ログイン中のid--> <button>投稿</button> </form> <h1>ーーーあなたのツイート一覧ーーー</h1> <div style="border: 1px solid #000; display: box; width: 400px"> @foreach ($twiiteList as $twiite) <p>{{ $twiite->contents }}</p><!--渡されたツイートデータ(なければ実行なし)--> @endforeach </div> </body> </html>Modelを作る
リレーションの設定は、DB個別でもできます。
直接sql文をたたくか、マイグレーションフィルに外部キーを設定でもできます。
が、しかし、せっかくフレームワークを使っているので、
生かさなければ!!
modelにて、その流れを肩代わりしてくれます。
外部キーなどをつくるわけではないので、そこは間違えないように!!<記事名>.php
class Twiite extends Model { protected $fillable = [ 'user_id', 'contents' ]; protected $dates = [ 'created_at', 'updated_at' ]; public function tags() { return $this->belongsToMany(Tag::class); } }外部キーがあれば、第二引数に設定したものが外部キーとして扱える。
今回はないが、リレーション相手のtagテーブルのidを保存しておきたいため、
idは外部キーではなく、indexの主キーでのアクセスとなる。今回のこのページで作っているのは、一方的なリレーションになるので、
tagからのhasmanyは無い。後で続編予定。。そこで、作る。。現状できないこと
- タグ情報から関連する記事を取得できない。
- タグを独自で作ったり、削除ができない。というか全く扱えないw
- 空文字の入力への対応ができない。
- ほぼヴァリデーションしてないので、ガタガタ。。
- 複数同じタグを入力できてしまう。カウントも増えるので、不正が可能。
Controller を作る
最後に作るのはコントローラ!
最後でなくてもいいんだけど、DBの入出力と、フロントの表示が整ってから、必要なデータの処理を
する方が、わかりやすいと思うんだ。。。<記事>Controller.php
use App\Twiite; use App\Tag; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class TwiiteController extends Controller { protected $twiite; public function __construct(Twiite $twiite){ $this->middleware('auth');//ユーザ認証 $this->twiite = $twiite;//twiiteクラスのインスタンス化 } public function index(Request $request) { $userId = Auth::id();//ログイン中のid $twiiteList = $this->twiite->where('user_id',$userId) ->orderby('created_at','desc') ->get();//ユーザのtwiite全取得 return view('index', compact('twiiteList', 'userId'));//index view } public function store(Request $request) { $userId = Auth::id();//ログイン中のid $inputs = $request->all();//リクエスト全て if(!empty($inputs['writelineTags'])){ $tags = $this->setTagDivide($inputs['writelineTags']);//文字列を配列に分割「,」 $tag_ids = $this->getIds($tags);//分割したタグを作り(またはカウントを追加し、)、そのidを取得 } $this->twiite->contents = $inputs['contents'];//contentsデータを追加 $twiite = $this->twiite->create($inputs);//twiiteデータ一件を作成&一件のデータを持つmodelのオブジェ クト取得 $twiite->tags()->attach($tag_ids);//中間テーブルに格納 return redirect()->to('twiite');//indexへリダイレクト } public function setTagDivide($tagstring){ $tags = explode(',',$tagstring);//文字列から特定の文字に応じて区切り、配列として格納。 return $tags;//Is Array. } public function getIds($tags){ $tagClass = new Tag();//tagを扱うクラスをインスタンス化 $recodes = [];//帰り値の初期化 $count = 5; foreach($tags as $tag){ $count--;//カウント if($count <= 0) exit;//上限を超える場合は強制退場 $aleadyTag = $tagClass->firstOrCreate(['name' => $tag]);//あれば取得、なければ作成。 $aleadyTag->increment('counts'); $recodes[] = $aleadyTag->id; } // dd($recodes);//tag_id,tag_id,tag_id.. return $recodes; } }※Authはユーザ認証のメソッドです。
ユーザーは一人ではないので、そのidなどを判定するために使っています。
処理にはAuthやmidlewereなどは直接関係ないです。見る人が見ると、「はあ?」と怒られてしまいそうな記述ですが、
急ぎ説明用に作ったものなので、ご容赦を。。とりあえず、それぞれ横に書いてあるdirectionの通りの意味です。
詳細は自分で調べてください。今回重要なのは、ここ。
$twiite = $this->twiite->create($inputs); $twiite->tags()->attach($tag_ids);$this->twiiteは、いわばnew Twiite() やTwiite::Classで作れるもののことで、モデルクラスをインスタンス化したものです。
createメソッドは返り値が追加したデータを持つ、モデルクラスのオブジェクトなので、
今回は1件のデータをattributeに持つ、オブジェクトになります。当然モデルクラスにデータが入っているだけなので、インスタンスとは何ら機能に変化はありません。
そこから、先ほど<記事名>.phpで行った、tags()というメソッドを使い、
アタッチをしています。。
attacheを扱っているのは<記事名>クラスなので、その(指定がなければidになる)id、
attacheで送るデータは()内に入った、タグのid。attacheメソッドは引数が配列データで送れるので、その場合は、複数個中間テーブルに保存されることになります。
ex)記事1個目にタグが複数ある場合。
twiite_id tag_id 1 1 1 2 1 3 1 4 2 4 こんな感じで、中間テーブルが同一の記事idに複数一気に作成されます。
中間テーブルの利用。
登録をしただけじゃ、何の意味もないので、これを呼び出す必要もあります。
が、今回はこのへんで! 次回の記事に続きを書いていきますので、こちら(次)も見てください。
- 投稿日:2019-05-24T07:07:42+09:00
laravelのインストール
laravelのインストール
composer が入った後Laravelを作成する際
通常の解説ではlaravel new hogehogeとしてたが、うまくいかないことがある事とダウングレードすることから
composer create-project laravel/laravel:5.5 hogehogeにしたほうがいい。