vagrant Homestead でホストOSの共有フォルダが見れなくなった際の対処
状況
ある日Homesteadの vagrant up
時に以下の様なエラーが出てゲストOSとホストOSフォルダ共有が出来なくなってしまった。
(windows10 64bit環境)
Going on, assuming VBoxService is correct... bash: line 5: setup: command not found ==> homestead-7: Checking for guest additions in VM... The following SSH command responded with a non-zero exit status. Vagrant assumes that this means the command failed! setup Stdout from the command: Stderr from the command: bash: line 5: setup: command not found
エラーでググると以下のページに行き当たり同じ対処をしたが、 GuestAdditions の インストールをHomestead側で行ってもmountがされない様だった。
対応したが私の環境では解決しなかった方法
上記のページに習いmountしてみたが上手くいかなかった。
vagrant@homestead:/mnt$ sudo ./VBoxLinuxAdditions.run Verifying archive integrity... All good. # ... インストール中のメッセージ... VirtualBox Guest Additions: Running kernel modules will not be replaced until the system is restarted vagrant@homestead:/mnt$ cd vagrant@homestead:~$ ls /etc/init.d/ | grep vboxadd # 何も出ない! 入ってない! vagrant@homestead:~$ ls /etc/init.d/ acpid avahi-daemon cron ebtables iscsid lvm2-lvmetad mdadm nfs-common open-vm-tools php7.2-fpm postgresql rsync supervisor unattended-upgrades apparmor beanstalkd cryptdisks grub-common keyboard-setup.sh lvm2-lvmpolld mdadm-waitidle nginx php5.6-fpm plymouth procps rsyslog sysstat uuidd apport blackfire-agent cryptdisks-early hwclock.sh kmod lxcfs memcached ntp php7.0-fpm plymouth-log redis-server screen-cleanup udev x11-common atd console-setup.sh dbus irqbalance lvm2 lxd mysql open-iscsi php7.1-fpm postfix rpcbind ssh ufw # やはり vboxadd がいない!
ちなみにこの記事執筆時のバージョンは以下 6.0.8 でした。 Index of /virtualbox/6.0.8
wget http://download.virtualbox.org/virtualbox/6.0.8/VBoxGuestAdditions_6.0.8.iso
そこでHomesteadのBOXファイル自体が古く対応できていないのでは?と思い至りupdateすることにした
windows側 の Gitbash で以下のコマンドを実行
$ vagrant box list # その他のBOXファイルがここに表示されている # updateを重ね現在は 6.1.0 laravel/homestead (virtualbox, 5.0.1) laravel/homestead (virtualbox, 5.2.0) laravel/homestead (virtualbox, 6.1.0) $ vagrant box update --box laravel/homestead # ここでダウンロードとupdateが行われるがしばらく時間がかかる $ vagrant box list # その他のBOXファイルがここに表示されている laravel/homestead (virtualbox, 5.0.1) laravel/homestead (virtualbox, 5.2.0) laravel/homestead (virtualbox, 6.1.0) laravel/homestead (virtualbox, 8.0.0-beta) # インストール後再度確認、上記の様に8.0.0-betaが入った
しかし、無事updateされて晴れてvagrant up
したが駄目。再度 GuestAdditions をmountしても同じ結果となる。乗らない…。
問題点が判明
windows側のGit bash で状況確認中、以下のerrorが出た事に注目
$ vagrant vbguest vagrant vbguest [homestead-7] GuestAdditions seems to be installed (6.0.8) correctly, but not running. bash: line 5: setup: command not found The following SSH command responded with a non-zero exit status. Vagrant assumes that this means the command failed!
もう直接的に GuestAdditions 6.0.8が駄目っす!って言っている。犯人はお前か。
このerror文章で検索をかけてみた所、以下のページが見つかる。
リンク先引用
[devapp] GuestAdditions seems to be installed (6.0.6) correctly, but not running. Redirecting to /bin/systemctl start vboxadd.service Redirecting to /bin/systemctl start vboxadd-service.service bash: line 4: setup: command not found ==> devapp: Checking for guest additions in VM... The following SSH command responded with a non-zero exit status. Vagrant assumes that this means the command failed!
setup
Stdout from the command:
Stderr from the command:
bash: line 4: setup: command not found ```
6.0.6でも同じ問題があったようだ
で、以下のコメントに注目
alvaro-canepa commented on 20 Apr
I have the same issue with Homestead and Virtualbox 6.0.6.
Adding this to Vagrantfile solve the problem:
if Vagrant.has_plugin?("vagrant-vbguest") config.vbguest.auto_update = false end
alvaro-canepa さんが、Vagrantfileにこの設定を追加しろって言ってる。
このコードはつまり vagrant-vbguest
はアップデートさせず使えって設定を書けってことらしい。
結論
という事で Homestead内の Vagrantfile を開き if文の中に設定を追記
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # ここには他の設定諸々が書かれている # 2019/06/24 add https://github.com/dotless-de/vagrant-vbguest/issues/333 if Vagrant.has_plugin?("vagrant-vbguest") config.vbguest.auto_update = false end end
これでvagrant reload --provision
した所、諸々の再設定がされて無事共有フォルダが反映されるようになりました。
でもいつかupodateが反映され、 その際には vagrant-vbguest も正しく修正された暁には、上の設定は消して新たな設定を反映されるようにするのが望ましいでしょう。
Apache2.4で複数ドメインを1つのサーバーで動かして Let's Encrypt でssl対応する方法のメモ
Apache2.4で複数のドメインを当てて、Let's Encryptで二つのサイトでssl対応をした際のメモを記しておきます。
- 要約
- Let's Encryptで複数のドメインで証明書を取るにはコマンドがあるが、既に一つのSSL認証を取得している場合は一度失効と削除をする必要があるようです。
/etc/http/conf/httpd.conf
の記述を/etc/httpd/conf.d/ssl.conf
に転載するのが基本- Let's Encryptで取得したキーのありかを conf ファイルで指定してやらないと駄目
- 何度も設定間違って再取得していると、1時間、または1週間のデッドロックを食らう
- ドメインのアクセスには
http://
https://
www.
有りwww.
無しの合計4パターンがあるが、今回はhttps://
のwww無しで統一リダイレクトをさせる設定にした
Let's Encryptで複数のドメインで証明書を取るコマンド
既に一つのSSL認証を取得している場合は一度失効と削除をする必要があるようです。 削除の方については以下のサイト等を参考にさせていただきました。
2つのサイトでのSSL認証の取得コマンド
rootユーザーになって以下のコマンドを打ちます。
例はドメイン aaa.site
, bbb.site
の二つとしています。
サイトの公開フォルダはサーバー内のそれぞれ /var/www/aaa-site
, /var/www/bbb-site
にあるものとします。
# certbot certonly --webroot -w /var/www/aaa-site -d aaa.site -w /var/www/bbb-site -d bbb.site
なお、インストールの経緯でコマンドの最初は certbot-auto
等にもなるようです。
次にApacheの設定ファイルです。
/etc/httpd/conf/httpd.conf
NameVirtualHost *:80 # 一つ目のサイトの設定 <VirtualHost *:80> DocumentRoot /var/www/aaa-web-site ServerName aaa.site # エイリアスの指定で www 付きでのアクセスも受け入れる事が出来るようです。 ServerAlias www.aaa.site AddDefaultCharset UTF-8 <Directory "/var/www/aaa-web-site/"> AllowOverride All # リダイレクト処理を行う設定 RewriteEngine On # 以下の二つのドメインでアクセスがあった場合書き換え処理を行う # http://aaa.site と http://www.aaa.site でアクセスがあった場合、リダイレクトをする RewriteCond %{SERVER_NAME} =aaa.site [OR] RewriteCond %{SERVER_NAME} =www.aaa.site # リダイレクト先は https://aaa.site となる、URIのパラメーターがある場合はそのままで飛ばす # 301リダイレクト LはマッチしたらRewriteを止め以降のルールは無視するそうです RewriteRule ^ https://aaa.site%{REQUEST_URI} [R=301,L] </Directory> </VirtualHost> # ふたつめのサイトの設定 やっている事は同じです <VirtualHost *:80> DocumentRoot /var/www/bbb-web-site ServerName bbb.site ServerAlias www.bbb.site AddDefaultCharset UTF-8 <Directory "/var/www/bbb-web-site/"> AllowOverride All RewriteEngine On RewriteCond %{SERVER_NAME} =bbb.site [OR] RewriteCond %{SERVER_NAME} =www.bbb.site RewriteRule ^ https://bbb.site%{REQUEST_URI} [R=301,L] </Directory> </VirtualHost>
/etc/httpd/conf.d/ssl.conf
かなり前に行ったLet's Encryptが自動生成した記述があるかは不明。長い記述の一部分のみを記載
NameVirtualHost *:443 # 一つ目のサイトの設定 <VirtualHost _default_:443> SSLEngine on DocumentRoot /var/www/aaa-web-site ServerName aaa.site ServerAlias www.aaa.site # SSL認証キーのありかを指定する Let's Encrypt で必要な設定 # ファイルの場所はCentOS7の私の環境の場合です。環境によって異なる可能性があります。 SSLCertificateFile /etc/letsencrypt/live/aaa.site/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/aaa.site/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/aaa.site/chain.pem <Directory "/var/www/aaa-web-site/"> AllowOverride All AddDefaultCharset UTF-8 RewriteEngine On # https://www.aaa.site でアクセスがあった場合のリダイレクト設定になる RewriteCond %{SERVER_NAME} =www.aaa.site # https://aaa.site へリダイレクトする、URIのパラメーターがある場合はそのままで飛ばす RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </Directory> </VirtualHost> # ふたつ目のサイトの設定 やってることは同じですが、 # 証明書キーの設定は1つめのサイトで行っているので必要無いのがミソです。 <VirtualHost _default_:443> SSLEngine on DocumentRoot /var/www/bbb-web-site ServerName bbb.site ServerAlias www.bbb.site <Directory "/var/www/bbb-web-site/"> AllowOverride All AddDefaultCharset UTF-8 RewriteEngine On RewriteCond %{SERVER_NAME} =www.bbb.site RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </Directory> </VirtualHost>
参考にさせていただいたサイト
近況報告
最近あんまり書いて無いですが、色々始まってます。
最近、講師から職業プログラマーにジョブチェンジを果たしました
5月の連休明けから、開発(PHP)の委託業務を週3日で始めました。通勤1.5時間がツライですが、お仕事をしつつえらい勉強になってます。
残りの2日は毎年やってる大学の非常勤講師(1年生にコンピュータの基礎を教える)ですが今年は色々あり過ぎて正直しんどい状況…。
現状の目標は8月から週5で通勤が辛くないPHP,Laravelのお仕事を探す事です。去年作ったwi-fiで滞在者がわかるアプリLivelynkを売るのではなく、あれを作った自分を売る、という風に視点を変えたら、40過ぎてからプログラミングを始めた人でも、けっこう高い価値が付いたみたいです。
滞在者確認アプリの現状
そのLivelynkの改修がなかなか進みませんが、ギークオフィス恵比寿ではインフラ的な位置を完全に確立して現在も絶賛稼働中です。 実はドメインの設定でやらかし連休中に数日サービスが繋がらない状態が続いたのですが、その際の不便な事といったら!みたいな感覚になったのが、申し訳なさもありますが、大事なものになっている事を認識出来た良い機会でもありました。
あの記事を書いた後から付いた機能があります。
一つはGoogleHomeとの連携、現在は人が来訪すると挨拶をさせている程度ですが、今後、価値ある情報を提供させることをするツモリです。
来訪者が来た際に挨拶するようになりました!他にも色々喋りますが、なんとしゃべるかは恵比寿訪問か、ご購入か、もしくは公開ソースコードでわかります pic.twitter.com/a0mOglBdkz
— sakamata (@sakamata) 2018年12月7日
Livelynkサーバーからラスパイを介して、GoogleHomeにしゃべらせるというハック的な実装の詳細はともかくですが、静かなオフィスで唐突にGoogleHomeが余計な挨拶や決まりきった挨拶をする際の気まずさといったら…。新たなソリューションでこれをやってはいかん!というのがわかっただけでも大きな収穫でした。
そしてもう一つはこの場所に『行く予定』を宣言できる機能です。 元々同じ仲間の兄弟アプリ『ツモリンク』
というのがありまして、任意の場所に今から行こうかな?というあいまいなニュアンスを宣言するアプリなのですが、この宣言ができる機能のみLivelynkに内包して実装しました。
実装の際は新機能の部分のみですが、習ったばかりのテスト駆動開発を意識して、テストを先に書いて実装をして、テストが通れば実装もOK、というフローで作りました。慣れずに時間はかかりましたが、今の所大きなバグは無い筈です。(つい昨日細かな不具合報告があったけど…)
あと、簡単な実装ですが、Googleカレンダーをメインの画面に表示させる様にして、近日中のギークオフィス恵比寿のミーティングやイベントが、一目でわかる様にしました。
また、Livelynkは企画や機能として何か重要なパーツが欠けている気がしているので、細かな機能追加をして使いやすさを追求しつつ、新しい価値を提供できる様なものにして行くツモリです。
その他お仕事や今後の事
また、小規模ですがプログラミングやウェブサイト制作のお仕事もいただいています。あと、現在週一で1時間だけ、プログラミング初心者の人に基礎を教えるというビデオチャットのアルバイトもしてます。という事でWord,やExcelだけでなくプログラムを人に教えられる所まで、ちょっとだけ来たみたいです。
でも、人に教える仕事ってものすごいやりがあって、自分も勉強になるのですが、時間ばかりかかってなかなか実入りが少ないのが悩み所ですね。
という事で、遠い目標として通貨や評価の新しい価値体系を作る為に、現在からの自分の価値を最大限発揮できるに様にするにはどうしたらいいのか?みたいな事を考え始めてます。
ゆるふわLaravel勉強会 (認証/JWT) 認証に関する資料
Laravel 認証についての色々まとめ
以下の記事は 2019/4/1 コワーキングスペース秋葉原Weeybleで行われる輪読会 [秋葉原] ゆるふわLaravel勉強会 (認証/JWT)のための認証に関する資料となります。
内容は以下の有志によるリファレンスサイトの記事の要約となります。 Laravel 5.8 認証
また、バージョンはLaravel 5.8.8 を前提にしています。
認証クイックスタート
Laravelインストール直後は認証系がフロント側で動く状態にはなっていないが、Controller等は既に準備されている
Controllers/Auth
配下
コントローラー | 用途 |
---|---|
RegisterController | 新ユーザーの登録 |
LoginController | 認証処理 |
ForgotPasswordController | パスワードリセットのためのメールリンク処理 |
ResetPasswordController | パスワードリセット処理 |
ひとまず認証付きのアプリを作るには、まずは以下のコマンドを打って、フロント側やルーティングに認証系の処理を自動生成させる
php artisan make:auth
コマンドを叩くとファイルに記述が追加されたり、新規ファイルが作られたりする
もし認証付きのアプリケーションを作るのであればfirst commit直後位に実施してしまうのが良い
変化のあるファイルの紹介
ルーティング
routes/web.php
// 以下2行が追加される
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
Auth::routes();
で登録画面、ログイン画面、パスワードリセットのすべてのルーティングを設定してくれている、個別に編集が必要な場合は、この行を廃止して画面毎にルーティングを定義する。
HomeControllerの追加
app\Http\Controllers\HomeController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HomeController extends Controller { /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); } /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { return view('home'); } }
ルーティングの2行目に追加された処理を行うControllerだが、ログイン直後の画面のサンプル例となる。 ログインすると/home
に移動するので、アプリケーションの仕様に従い、表示を作り込めば良いし、Home
という名前が気に食わないなら随意に変更する
その他以下の各viewファイルが自動生成されます。
resources\views\home.blade.php
resources\views\auth\login.blade.php
resources\views\auth\register.blade.php
resources\views\auth\verify.blade.php
resources\views\auth\passwords\email.blade.php
resources\views\auth\passwords\reset.blade.php
resources\views\layouts\app.blade.php
ログイン・登録・パスワードリマインダ等のページと機能も自動で生成してほぼ機能するようになります。
ブラウザでルートのpathにアクセスすると、画面左上に[LOGIN]と[REGISTER]のリンクが表示されるようになります。
認証の動作確認
まずはDBが無いので作ります。(vagrant環境でMySQLがある前提)
$ mysql -u root -p secret mysql> create database your_database_name; mysql>exit
migrateしてDBにtableを作ります。
$ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table
user table以外にpassword resetのtableもcreateされました。
これでREGISTER出来る様になりました。
登録画面に移動して、登録すると、DBにuserが生成され、ログインして/home
にリダイレクトされます。
当然一度ログアウトしてログインができることも確認できます。
また、ログイン画面にパスワードを忘れた際のMailリマインダ―がありますが、mailの設定をしないと飛びませんので、今回は割愛
以上が、クイックスタートで作られた認証の初期概要です。
認証のカスタマイズ (初級編)
初期状態は以下の様な認証の仕様となっていますが、これは簡単に変更が可能です。
以下はリファレンスサイトの内容をほぼ転載しています。
ログイン後のリダイレクト先 /home
の変更
LoginController
、RegisterController
、ResetPasswordController
、VerificationController
のredirectTo
プロパティで、認証後のリダイレクト先の場所を定義してください。
protected $redirectTo = '/';
ログイン時のEmailをユニークな username, user_id,等に変更する
ログイン時はemailとpasswordの組み合わせが認証のデフォルトだが、emailをuser_id等に変更したい場合。
これをカスタマイズしたい場合は、
LoginController
でusername
メソッドを定義してください。
public function username() { return 'user_id'; }
当然user Tableをmigrateして変更したいユニークとなるカラムを追加してください。
登録済みユーザーのロール別制限 guard メソッド
webアプリを普通に作ってる場合は個人的にあまり使いませんが、APIやSPAの際にはよく使う事になるそうです。
LoginController
、RegisterController
、ResetPasswordController
でguard
メソッドを定義してください。メソッドからガードインスタンスを返してください。
use Illuminate\Support\Facades\Auth; protected function guard() { return Auth::guard('guard-name'); }
認証済みユーザーの取得 -Authファサード超便利-
Auth::user()->email
とかでuser関連のデータをControllerやviewですぐ取得できる。
基本は認証時に行った user Tableのカラムのデータが取得できるので、自分のデータを取得したい際にとても便利に使えます。
use Illuminate\Support\Facades\Auth;
Auth::user()->email; // taro@gmail.com
認証中のユーザーか調べる -必須並みの便利機能-
Auth::check()
これも 認証してる/してない を簡単に切り替え判断できる。controllerでもviewでも使える。認証の有無で処理や表示を変える際に便利!よく使う。
use Illuminate\Support\Facades\Auth; if (Auth::check()) { // ログイン中の場合の処理 } else { // 非ログイン中の処理 }
認証済みのみ通すページをルーティングで指定
この辺はルーティングの説明時にも紹介した内容で、ルーティングrouter/
でチェーンメソッド->middleware('auth')
と書くと、認証時のみ有効となるルーティングとして定義できます。
Route::get('profile', function() {
// 認証済みのユーザーのみが入れる
})->middleware('auth');
それ以外でも例えばコントローラのコンストラクタでもmiddlewareメソッドを呼べる
public function __construct() { $this->middleware('auth'); }
認証回数制限
brute-force対策が最初から出来ている感じ?
Laravelの組み込みLoginControllerクラスを使用している場合、
Illuminate\Foundation\Auth\ThrottlesLogins
トレイトが最初からコントローラで取り込まれています。デフォルトでは何度も正しくログインできなかった後、一分間ログインできなくなります。制限はユーザーの名前/メールアドレスとIPアドレスで限定されます。
自前のユーザー認証 (中級編)
リファレンスにある内容を紹介する
app\Http\Controllers\Auth\LoginController.php
に
authenticate
メソッドを新たに定義する。
認証系のカスタマイズはvendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
にあるメソッドをオーバーライドするのが応用編の入り口の様です。
ちなみに下記のIlluminate\Foundation\Auth\AuthenticatesUsers.php
内のauthenticated
メソッドの実体は空メソッドで、カスタマイズ専用のメソッドである事がわかります。
/** * The user has been authenticated. * * @param \Illuminate\Http\Request $request * @param mixed $user * @return mixed */ protected function authenticated(Request $request, $user) { // }
これを以下の様にLoginController.php
に追加で記述をします。
以下、リファレンスサイトの例を転載します。
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class LoginController extends Controller { /** * 認証を処理する * * @param \Illuminate\Http\Request $request * * @return Response */ public function authenticate(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { // 認証に成功した return redirect()->intended('dashboard'); } } }
ここで重要なのはAuth::attempt($credentials)
です。
これが認証するか否かを判定できる仕組みで、引数に渡すのはモデルのカラム名となります。
オレオレの実装例
public function authenticate(Request $request) { // login_id カラムは email + '@' + community_id(int) で構成されたユニークの文字列として登録時に保存された値、これでログイン認証を行う $login_id = $request->email . '@' . $request->community_id; $credentials = array( 'login_id' => $login_id, 'password' => $request->password, ); $request->validate([ 'email' => 'required|string|email|max:170', 'password' => 'required|string|min:6', ]); if (Auth::attempt($credentials)) { return redirect('/')->with('message', 'ログインしました'); } else { return redirect()->back()->withErrors(array('email' => 'E-mailかPasswordが正しくありません'))->withInput(); } }
Auth::attempt($credentials)
に渡す認証の値は追加が可能です。以下の様に認証時の条件を3つ以上に設定することができます。
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) { // ユーザーは存在しており、かつアクティブで、資格停止されていない }
以降の認証に関する記述はリファレンスサイトを参考にしてください。
これ以降はケースバイケースで使用するかも。といったものが多い印象です。
よくありそうなカスタマイズについての実例など
RegisterController のカスタマイズ
ユーザー登録を行う際のvalidator
とcreate
メソッドの変更が必要であれば変える。
この辺は大変解りやすいコードだし、見たまんまで弄ってしまって基本OKです。
バリデートの変更や、ユーザー登録時に発行すべきカラムのデータ等を生成します。ありがちなのはユーザーの権限を初期状態で追加する。等の処理を行う事になるかと思います。
app\Http\Controllers\Auth\RegisterController.php
抜粋
/** * Get a validator for an incoming registration request. * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return \App\User */ protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); }
認証カスタマイズ(オレオレ編)
実はAuth::user()
で呼べるのは通常,user Tableのカラムだけとなります。ところがアプリの仕様上 user Tableがユニークにならない様な場合は、Auth::user() で欲しい一意のユーザーのデータが取得できず、偉い苦労しました。
どんなことをやったかというと、この記事にあるような事をしました。
Laravel 認証カスタマイズ 複数tableを結合しての認証で Auth::user() に必要な値を入れる方法
Laravelの認証機能をカスタマイズして、認証時に3つのカラム条件で認証をし、さらに認証後にAuth::user() ファサードに複数tableからの値を取得できるようにしました。
という訳で後半はこれについて説明します。
Laravel 認証カスタマイズ 複数tableを結合しての認証で Auth::user() に必要な値を入れる方法
Laravelの認証機能をカスタマイズして、認証時に3つのカラム条件で認証をし、さらに認証後にAuth::user() ファサードに複数tableからの値を取得することをしました。
環境Laravel5.6
windows10Pro 64bit
vagrant環境にて実施
そもそもの経緯として、DB構造が特殊になり、 通常の users tableのみでの認証では必要な値を取得できなくなっていました。
全体のDB設計をしてからやれば済む問題だったのですが、単数のtableでの認証を前提として、システムを作り込んでしまい。後からどうしても複数tableからの値を取得する必要に迫られて、Laravelの認証系のドキュメントやサイトをかなり読込むことになりました。
結果を先に書いておくと 複数tableをjoinしたMySQLのviewを migration で書いて、そのviewを認証用table,auth_users
として登録し、viewから一意の値を導きます。
通常はusers tableから、 email, password と2種類のカラムから一意、かつパスワードの一致で認証をしますが、今回は unique_name, password, community_id の3つのカラム条件から認証条件を導き出しています。
table構造図
(パワポで書いたのでちょっと変ですが意図は伝わるかと思います。)
user は複数のコミュニティに任意に所属・登録できるというシステムで、これを中間tableである community_user でどのユーザーがどのコミュニティに所属しているかを管理しています。
さらに community_user tableにはと1対1(hasOne)の関係で追加table communities_users_statuses があり、特定のユーザーの特定のコミュニティ内での情報(権限レベルのidや表示設定、日時等)が保存されています。さらにその先には roles(権限)tableがあり、idと権限名が記載されているという、かなりがっつりなtable設計をした構造になってます。
これら
users
community_user
communities_users_statuses
roles
上記4つのtabelのからのカラムデータを、Laravelのファサード Auth::user()->name
といった具合に、 Auth::user()->role
も Auth::user()->user_id
も Auth::user()->community_id
も "->"を一つ書くだけで一気に取得できる様にして、その値をアプリケーションの様々な処理のトリガーとして利用したいのです。(というかそういう風に作ってしまって後から変えるの凄いしんどい。)
まず、通常のLaravelの標準の認証系の追加をさくっとします。この辺は他のサイトにお任せします。
で、色々ファイルが作られますので、それをどう変えるか、というお話です。
まず、MySQLのviewを auth_users
という名前でマイグレーションファイルで作成します。通常のマイグレーションファイルの記述方法とは少し異なります。
use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; // 認証時に使用される view Auth::user() に収納される // $credentials array ('id', 'unique_name', 'password' ) class CreateViewAuthUsersTable20181114 extends Migration { /** * Run the migrations. * * @return void */ public function up() { DB::statement( 'DROP VIEW IF EXISTS auth_users' ); DB::statement( " CREATE VIEW auth_users AS SELECT community_user.id, community_user.user_id, community_user.community_id, users.name, users.unique_name, users.email, users.facebook_id, users.password, users.remember_token, communities.user_id AS reader_id, communities.name AS community_unique_name, communities.service_name, communities_users_statuses.role_id, communities_users_statuses.hide, communities_users_statuses.last_access, communities_users_statuses.created_at, communities_users_statuses.updated_at, roles.role FROM community_user JOIN users ON (community_user.user_id = users.id) JOIN communities ON (community_user.community_id = communities.id) JOIN communities_users_statuses ON (community_user.id = communities_users_statuses.id) JOIN roles ON (roles.id = communities_users_statuses.role_id) " ); } /** * Reverse the migrations. * * @return void */ public function down() { DB::statement( 'DROP VIEW IF EXISTS auth_users' ); } }
がっつりとview作成のSQL文を書いています。
DB::statement は通常のSQL文を書くという事ですね。 宣言の部分に use DB; は書かなくても大丈夫でした。書いたら逆にエラーになった。
で、以下のコマンドを実施
php artisan migrate
でSQL文を走らせて view,auth_users
を作ります。
この方法はこちらのサイトを参考にさせてもらいました。
LaravelのマイグレーションでView Tableを作成する
これにより先ほど説明した4つのtableが結合されたviewが作成されます。
viewは一つの大きなtableの様に扱う事ができます。出来上がったviewには所により同じ値が2度以上でますが、 unique_name password community_id の3つの値が全て重複するレコードは存在せず、これにより一意の認証が可能となります。
次にこのviewを認証用のtableとして使うための認証用モデルを作ります。
これは、標準で認証に使われているファイル app\User.php をコピーして書き換えました。
app\AuthUser.php
namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class AuthUser extends Authenticatable { use Notifiable; /** * モデルと関連しているテーブル * * @var string */ protected $table = 'auth_users'; /** * The attributes that should be hidden for arrays. * JSON出力の際誤って含めいない属性という事らしい * @var array */ protected $hidden = [ 'password', 'remember_token', ]; // 日時表記変更の ->format('Y-m-d') を使いたいカラム名を指定する protected $dates = [ 'last_access', 'created_at', 'updated_at', ]; }
これが結構忘れがちですが大事です!
次に上記の app\AuthUser.php を認証時に使うように config ファイルの model を書き換えます。
config/auth.php (抜粋)
'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\AuthUser::class, ],
また、login画面のviewファイルにはコミュニティ毎にログイン画面のURLが異なる仕様となっています。
ここにformの hidden で表示されているログイン画面の community_id の値をPOSTできる様にしています。また、標準のemailの入力欄であるフォームを ユーザーID(unique_name)の入力欄に変更しています。
resources\views\auth\login.blade.php
省略 <form method="POST" action="{{ route('login') }}" aria-label="{{ __('Login') }}"> @csrf <input type="hidden" name="community_id" value="{{$community->id}}"> 省略 <input id="unique_name" type="text" class="form-control{{ $errors->has('unique_name') ? ' is-invalid' : '' }}" name="unique_name" value="{{ old('unique_name') }}" required autofocus>
最後?に LoginController を書き換えます。
app\Http\Controllers\Auth\LoginController.php (抜粋)
// 前後省略 use DB; use Illuminate\Support\Facades\Auth; //Class宣言部分 省略 // ログイン時に使用するユニークであるカラムを指定 public function username() { return 'id'; } public function authenticate(Request $request) { $request->validate([ 'unique_name' => ['required', 'string', 'min:6', 'max:40', 'regex:/^[a-zA-Z0-9@_\-.]{6,40}$/u'], 'password' => 'required|string|min:6|max:100', ]); // 該当の community_user の id を取得 $community_user_id = DB::table('community_user') ->leftJoin('users', 'users.id', '=', 'community_user.user_id') ->where([ ['unique_name', $request->unique_name], ['community_id', $request->community_id], ])->pluck('community_user.id')->first(); if (!$community_user_id) { // 他のコミュニティで認証が取れるか? $result_bool = $this->CheckOtherCommunityExists($request->unique_name, $request->password); if ($result_bool) { // 他のコミュニティにいる場合中間table等にレコード追加 $community_user_id = $this->InsertNewStatuses($request->community_id, $request->unique_name); } else { // 他のコミュニティにいない場合 return redirect()->back()->withErrors(array('unique_name' => 'ユーザーIDかPasswordが正しくありません'))->withInput(); } } // community_user_id を含めた通常の承認フロー $credentials = array( 'unique_name' => $request->unique_name, 'password' => $request->password, 'id' => $community_user_id, ); // 認証許可 if (Auth::attempt($credentials)) { // session にcommunity値保存 $request->session()->put('community_id', $request->community_id); $request->session()->put('community_user_id', $community_user_id); return redirect('/')->with('message', 'ログインしました'); } else { return redirect()->back()->withErrors(array('unique_name' => 'ユーザーIDかPasswordが正しくありません'))->withInput(); } }
通常は$credentials の配列に email と password のみを指定して Auth::attempt($credentials) と渡してやれば認証を結果を返してくれますが、auth_users
から一意の値として取得できる条件として id を配列に追加してやります。
$credentials = array( 'unique_name' => $request->unique_name, 'password' => $request->password, 'id' => $community_user_id, );
こうすることにより、 MySQLのviewで作られた auth_users table を探しに行き、一意の値を取得して認証が行われるという訳です。
ちなみにコードの中ほどの独自メソッド群は、$community_user_id を特定する処理として、認証前に値を探しに行ったり、ユーザーがまだログインしたことのないコミュニティに初ログインした際に既存ユーザーであるか?の確認をしたり、community_user にtableに値を追加したり、と、このWebアプリケーション独自の処理を色々してます。
こっからは蛇足ですが、その処理の際に、認証を全て自分でカスタマイズできそうなヒントになりそうな処理を書いたので紹介。
// return bool 他のコミュニティに存在するかを判定する public function CheckOtherCommunityExists($unique_name, $password) { $hash_password = DB::table('users')->where([ ['unique_name', $unique_name], ])->pluck('password')->first(); if ($hash_password) { if (Hash::check($password, $hash_password)) { return true; } } return false; }
上記の自作メソッドは 認証時の id と password を使って、クイックスタートで作られる認証系の処理を通さないで ユーザー認証の判定ができています。(unique_name とpassword)この処理を書いていたら図らずも結構普通な感じの認証処理になってました。
なので、単純に自分で認証処理を作りたい際は上記を参考に返り値となるboolの判定を基に
Auth::login($user);
とやってしまえば、ログイン認証っぽい事はできるようです。 $user
はAuth::user()
に入る一意のユーザーのオブジェクト(DBのrecord)ですね。ただ、tokenに値を入れたり、リダイレクト先を指定したりの処理がどこまで必要になるかは未検証です。
Laravel 5.6 認証 イントロダクション
https://readouble.com/laravel/5.6/ja/authentication.html
【輪読会資料】基礎から学ぶVue.js CHAPTER7 より大規模なアプリ開発 読書メモ
以下の記事は2019/3/28 コワーキングスペース秋葉原Weeybleで行われる輪読会
[秋葉原] 基礎から学ぶVue.js輪読会 ch7 より大規模なアプリ開発(初心者歓迎!)のための読書メモとなります。
以下の書籍の CHAPTER7 より大規模なアプリ開発 のメモです。
- 作者: mio
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2018/05/29
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
CHAPTER 7 より大規模なアプリケーション開発
SECTION 33 アプリケーションを拡張しよう
Vue.js本体は画面の描画に関わる機能しか備えていないが、以下の様なエコシステムを導入すると機能を拡張できる。
Vuex
複数のコンポーネントでデータを共有したり、アプリケーション全体の状態を一元管理する状態管理用のライブラリ
Vue Router
コンポーネントで構造化された複数の画面をURLと紐づけるSPA(Single Page Application)構築の為のルーティング用のライブラリ
Vuex と Vue Routerは機能として独立しており、状況に応じて片方だけでも構築が可能。 それぞれの特徴はCHAP8,CHAP9で解説している。
ここでは単一ファイルコンポーネントを使ったコンポーネント構築とVueCLIを使ったビルド環境の導入を前提としての説明をする。
SECTION 34 Vue CLIとは
Vue CLIとはVue.jsを使ったコマンドラインインターフェース、Vue.jsの開発環境構築が簡単にできる
ソースコードを分けて管理
分割して作ったファイルをコンパイル時等に結合して一つのファイル化させる方法
モジュール化でさらに快適に!
モジュール化で作られたファイルは多くの機能から必要なものだけピックアップして組み込める。
Vue.jsのモジュール化は「単一ファイルコンポーネント」を採用している。
単純に結合しても動くわけではなく、補完する機能として代表的なものに「webpack」といったバンドルツールがある。
webpack以外にも多くのツールの複雑な設定を自動管理してくれるのが「Vue CLI」となる
webpackとは
モジュール化した複数のファイルをまとめるバンドルツール、他にも[Rollup]や[Parcel]といった別種が存在する。詳細は公式サイトを参照の事 webpack 公式サイト
モジュール化の際は、必要なリソースだけをバンドルするようになっているので、自動的に余計なものが付かないで最小単位で出力されるようになっている。
SECTION 35 単一ファイルコンポーネントとは
「単一ファイルコンポーネント」はコンポーネントの定義方法の一つでSFC(Single File Components)
とも言われる
一つのファイルで管理しきれないHTML,JavaScript,CSSを[.vue]という拡張子のファイルにまとめて管理する。
単一ファイルコンポーネントの例
Example.vue
<template> <div class="example"> <span class="title">{{ text }}</span> </div> </template> <script> export default { name: 'Example', data() { return { text: 'example' } } } </script> <!-- scoped CSS --> <style scoped> .title { color: #ffbb00; } </style>
こいつをビルド環境でプレーンなJavaScriptにプリコンパイルする
スコープ付きCSS(Scoped CSS)
<style>
タグでscoped
オプションを付けるとスコープ付きCSSを利用できる。(<style scoped>
)このテンプレート内でしかスタイルが適用されないようにできる。
出力される際には以下の様なユニーク属性で管理される
<div class="example" data-v-xxxxx> <span class="title" data-v-xxxxx> hoge </span> </div>
span.title[data-v-xxxxx] { color: #ff0000; }
これでクラス名の衝突を気にしなくて良くなる。なお、全くクラスの指定がないとパフォーマンスが落ちるので classでスタイル定義をするのが推奨されている。
子コンポーネントの扱い
テンプレート内に子コンポーネントが存在する場合、子のルート要素とスロットの要素は親と子の両方のスコープを持つ
<div class="example"> <child-comp/> </div>
親と子両方に<style scoped>
をを指定した際は以下の様に展開される
<div class="example" data-v-aaaaa> <div data-v-aaaaa data-v-bbbbb><!-- このルート要素 --> <span data-v-bbbbb>child-comp</span> </div> </div>
この様にルート要素のスタイルはどちらのファイルにも書くことができるので、柔軟にレイアウト変更が可能となる。
スコープをまたぐ設定
お互いにスコープの付いたコンポーネントから子のセレクタ .b
を指定したい例
cssの場合
<style scoped> .a >>> .b {color: #ff0000; } </style>
scssの場合
<style lang="scss" scoped> .a /deep/ .b {color: #ff0000; } </style>
外部ファイルの読み込み
<template src="./template.html"></template> <style src="./script.js"></style> <style src="./style1.css"></style> <style src="./style2.css" lang="scss" scoped></style>
他のマークアップ言語やスタイルシート言語の仕様
cssやscssの他に、[Pug],[Sass]を使用等をすることができる。Vue CLIで作成したプロジェクトなら、パッケージを以下の様にインストールしてから…
npm install pug pug-loader --save-dev
以下の様に書くだけで使用可能
<template lang="pug> div#example span {{ text }} </template>
SECTION 36 ES2015モジュールの書き方
ES2015モジュールは .js でファイルを作成するが、モジュールファイルは独自のスコープを持ち、他のファイルとは切り離される、変数の衝突や他の機能への干渉を気にしなくて良くなる反面、モジュール内で定義したデータや関数は他のファイルから直接アクセスできなくなる。
モジュールを定義する
Example.js
// stateオブジェクトはこのモジュール内でしか使用できない var state = { count :1 }
モジュール内のデータや関数を別のファイルに渡すにはエクスポート&インポートが必要
次の例はstate
オブジェクトをエクスポートして、外部でインポートできる様にした例
Example.js
var state = { count :1 } // デフォルトのインポート文で呼ばれた時に返すデータ export default state
モジュールを使用する
前述のExample.js
のstate
オブジェクトをExample
という変数名でインポートした例
main.js
import Example from './Example.js' console.log(Example.count) // => 1と出力
このような書き方は Vuex, Vue Router ファイルを書く際に必要なので覚えておくこと!
SECTION 37 Node.jsの導入
node.js
はJavaScriptの実行環境、サーバーサイドでJSを動かす際に必須
npm
はJSのパッケージ管理ツール、node.jsに一体化して付いてくる。 PHPでいう所のcomposer的な奴
以下からインストール
node.js 日本語公式サイト
windows10の場合はそのまま画面の指示に従いインストール
コマンドプロンプトで以下のコマンドでバージョンを出してインストールされたか確認する。
今回は推奨版10.15.3 LTS をインストールした
node -v v10.15.3 npm -v 6.4.1
Babelとは
ECMAScript準拠およびJSXのトランスパイラ、Vue CLIはデフォルトでBabelをインストールしてトランスパイルを行う。
トランスパイル(transpile)
一言で言えば、ある言語で書かれたコードを元に別の言語のコードを生成すること。
BabelはES2015のコードを古いES5のコードに変換してくれる
ES2015のコード | トランスパイル | ES5のコード |
---|---|---|
const count = 1 | => | var count = 1 |
Babelの目的やメリットは最新の記法を使って書ける様にすることにある
SECTION 38 Vue CLIの導入
Vue CLIをインストール
npm install -g vue-cli
バージョンを確認
vue --version 2.9.6
プロジェクト作成コマンドのひな形
vue init [テンプレート名] [プロジェクト名] cd [プロジェクト名] npm install
テンプレートは[webpack], [webpack-simple]が良く使われる,他にも[PWA],[Electron]等の様々なアプリケーション用のテンプレートが公開されている。
ここでは[webpack]を使って説明をして行く
新しいプロジェクトの作成
アプリを入れたい適当なフォルダに移動(cd)してから次のコマンドを実行
(Git bashで操作)
作ったフォルダ自体が localhost:8080 の実行環境になってそのまま開発環境のsever化してくれるので、本当にフォルダの場所とか適当で良い様です。
# htdocsに移動 $ cd /c/xampp/htdocs # プロジェクトの作成 vue init webpack vue-my-app $ vue init webpack vue-my-app # 質問が出るので色々選択しながら進む、今回は以下の設定で進んだ。 ? Project name (vue-my-app) ? Project name vue-my-app ? Project description (A Vue.js project) ? Project description A Vue.js project ? Author (Taro Yamada <yamada@gmail.com>) ? Author Taro Yamada <yamada@gmail.com> ? Vue build runtime ? Install vue-router? (Y/n) n ? Install vue-router? No ? Use ESLint to lint your code? (Y/n) n ? Use ESLint to lint your code? No ? Set up unit tests (Y/n) n ? Set up unit tests No ? Setup e2e tests with Nightwatch? (Y/n) ? Setup e2e tests with Nightwatch? Yes ? Should we run `npm install` for you after the project has been created? (recom ? Should we run `npm install` for you after the project has been created? (recom mended) npm
すると htdocs
フォルダ内に vue-my-app
フォルダが作られ、中に色々ファイルが作られる
$ ls -a vue-my-app/ ./ .babelrc .gitignore build/ index.html package.json README.md static/ ../ .editorconfig .postcssrc.js config/ node_modules/ package-lock.json src/ test/
フォルダとファイルの構成
[webpack]を使用した際、いろんなファイルやフォルダが作られるが、基本的に[src]フォルダ以下の物しか使わない
単一ファイルコンポーネントの[.vue]ファイルは慣例的に src/components
にまとめる
src/main.js でコンストラクタの呼び出しが行われている
/* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(App) })
開発サーバーを起動する
vue-my-app
フォルダ内に cd してから以下のコマンドを入れてサーバーを起動する
npm run dev
ブラウザでhttp://localhost:8080/
にアクセスしてVue.jsのロゴとWelcome to Your Vue.js App のメッセージが出力されればOK!
サーバーを起動させたコンソールは開きっぱなしにしておくこと
ホットリロード
ホットリロードはブラウザリロード不要でファイル変更の際に更新してくれる機能
vue-my-app/src/components/HelloWorld.vue
ファイル内のmsg: 'Welcome to Your Vue.js App'
を編集して上書きすると即座ぶブラウザが更新されるのが確認できる。超便利!
プロジェクトをビルドする
実際に運用モードとしてビルドするには以下のコマンドを入れる
npm run build
数分かかる。ビルドが終わると[dist]フォルダが作成される。
この[dist]フォルダだけを本番サーバーにアップロードすれば、ローカルからのビルドとデプロイが完了する。
ちなみに以下のサポートページで、静的サイト向けの高機能なホスティングサービスNetlify
の自動デプロイの方法についての記述がある。
Vue.js+Netlifyで自動デプロイ
開発時のAPIのパス統一やクロスドメイン対策
本番環境と開発環境でAPIのパスが異なる場合や、別ドメインのAPIからデータを取得する際はプロキシ設定が必要となる。config/index.js
に以下の様に記述することで切り替えができる
before config/index.js
proxyTable: {},
after config/index.js
proxyTable: { '/api' : { taget: 'http://localhost:8081', changeOrigin: true, pathRewrite: { '^api'; '/vue-my-app/api' } } },
例えばAPIで /api/user
を叩くと 異なるドメインから user のAPIを取得できるように実装がされているとする。
プロキシを使うと以下へのアクセスは
http://localhost:8080/api/user
以下の様に変更できる
http://localhost:8081/vue-my-app/api/user
より詳細はwebpackのドキュメントを参照のこと
SECTION 39 Vue.jsプラグイン
CHAPTER1で紹介されたElement,Awesome Vue,VueCurated等のUIコンポーネントや、Vuex,Vue RouterはVue.jsプラグインとして作成されている。
ここではVue.jsプラグインの使い方と自作プラグインの作成方法の紹介となる。
Vue.jsプラグインの使い方
コンストラクタを使用する前にグローバルメソッドのVue.use
を使用してVue.jsに登録する
src/main.js の上の行に書く?
// VueとVuexのモジュールを読み込む import Vue from 'vue' import Vuex from 'vuex' // VueにVuexを登録 Vue.use(Vuex)
スタンドアロン版でプラグインを使用する場合
Vuexの様な公式提供の奴はVue.use
を使わずとも良い。
Vue.js本体を読み込んだ後にプラグインのファイルを読み込む
公開されているリソースはプラグインだけじゃない
コンポーネントやカスタムディレクティブとして登録するのものある
プラグインを自作してみる
入門向けではないが一応説明、大規模アプリの開発リソースの再利用の際にプラグイン作成できると便利だそうな。
具体的にどのファイルのどこに書けばいいのか分らずなのだが、それはここまで読んだ内容を理解してないせいか、後の章で書かれるかだと思います。
スクロール数値を共有するプラグイン
var windowPlugin = { install: function(Vue) { // プラグインデータ用にVueインスタンスを利用する var store = new Vue({ data: { scrollY: 0 } }) // ウィンドウのスクロールイベントをハンドル var timer = null window.addEventListener('scroll', function() { if (timer === null) { timer = setTimeout(function() { // 200ms間隔でscrollYプロパティに代入 store.scrollY = window.scrollY clearTimeout(timer) timer = null }, 200) } }) // インスタンスプロパティに登録 Vue.prototype.$window = store.$data } }
プラグインを登録
Vue.use(windowPlugin)
すべての Vue インスタンスで使用可能
Vue.component('my-component', { template: '<div>{{ scrollY }}</div>', computed: { scrollY: function() { return this.$window.scrollY } } })
SECTION 40 ES2015で書いてみよう
新しいJavaScriptの書き方、ES2015(ES6)は対応してないブラウザがあるが、既に説明した通り、Babelが古いJS形式にトランスパイルしてくれるので、Vue CLI
ではES2015形式で遠慮せずに書ける。ここではES2015の書き方の説明となる。
正直ちゃんと追って無かったので、この知識はありがたい。
変数宣言
ES5
var x = 0
ES2015
// 再代入可能 let x = 0 // 定数 再代入不可 const x = 0
ES2015はスコープで仕切られる
ES5
{ var x = 1 } console.lod(x) // 1
ES2015
{ let x = 1 } console.lod(x) // not defined
constで宣言した配列は空配列を再代入できない。か、 length
を0にすると配列を空にできる
const array = [1, 2] array.push(3) console.log(array) // -> (3) [1, 2, 3] array.length = 0 console.log(array) // -> []
関数とメソッドの書き方
functionの省略
ES5
new Vue({ methods: { handleClick: function() { ... } } })
function は書かなくても良い
ES2015
new Vue({ methods: { handleClick() { ... } } })
アロー関数
functionを省略して =>
で書ける関数thisの扱いが従来の関数と異なり、アロー関数式で宣言された関数は、宣言された時点で、thisを確定(=束縛)させてしまう。
その為メソッド内のthis
が必要な場面では使用できないが無名関数の定義で便利とのこと
【JavaScript】アロー関数式を学ぶついでにthisも復習する話
let normalFunc = function(x){ console.log(x); } normalFunc('今までの関数'); let arrowFunc = (y) => { console.log(y); } arrowFunc('アロー関数式');
STEP1
const newArray = array.map(el => { return el * 2 })
STEP2 returnを省略
const newArray = array.map(el => el * 2)
慣れの問題だが、ここまで省略されると認識し辛いなぁ
STEP3 複数の引数
const newArray = array.map((el, index) => el * 2)
STEP4 オブジェクトの return
const newArray = array.map(el => ({ value: el * 2 }))
簡単な奴から使って慣れると良いよ。と作者もおっしゃってます。
テンプレートリテラル
クォーテーションで囲んでバックスラッシュで改行
ES5
var name = 'hoge' var template = '\ <div class="template">\ <strong>' + this.name + '</strong>\ </div>' console.log(template)
バッククォートで囲むだけで改行含めて受け付けてくれる
ES2015
const name = 'hoge' const template = ` <div class="template"> <strong>${ name }</strong> </div>` console.log(template)
オブジェクトプロパティのショートハンド
ES2015では変数名とプロパティが同じなら省略して書ける
ES5
const newObject = {a: a, b: b}
ES2015
const newObject = {a, b}
分割代入
べんりー
ES2015
// 配列要素1,2をそれぞれ変数a,bに代入 const [a, b] = [1, 2] console.log(a) // -> 1 // nameプロパティだけ代入 const { name } = { id: 1, name: 'りんご' } console.log(name) // -> りんご
引数のオブジェクトを分割して受け取ることも可能
ES2015
function myFunction({ id, name }) { console.log(name) // -> りんご } myFunction({ id: 1, name: 'りんご' })
v-for
ディレクティブでも使える
<ul> <li v-for="{ id, name } in list" :key="id">...</li> </ul>
スプレッド演算子
配列、オブジェクトのリテラルを展開する ...hoge
ES2015
const array = [1, 2, 3] // バラバラの3つの引数として渡す myFunction(...array) // arrayを展開して4を加えた新しい一次配列を作成 const newArray = [...array, 4] // -> (4) [1, 2, 3, 4]
配列メソッド
findメソッド
条件に一致した最初の要素の値を1つ返す
(そういえばこういう処理、スゲー大変だった気がする)
ES2015
const array = [ { id: 1, name: 'りんご' }, { id: 2, name: 'ばなな' } ] const result = array.find(el => el.id === 2) console.log(result) // -> { id: 2, name: 'ばなな' }
見つからない場合は undefind が返る
findindex
条件に一致した最初の要素のインデックスを1つ返す
const array = [ { id: 1, name: 'りんご' }, { id: 2, name: 'ばなな' } ] const result = array.findIndex(el => el.id === 2) console.log(result) // -> 1 (indexは0始まりなので2番目は1)
Promise
非同期処理を抽象化したオブジェクト。(もうajaxとかじゃない!)
Promiseで非同期処理の完了を知ることができる。
引数としてresolve
(解決した)と、reject
(拒否した)のコールバック関数を受け取る。
( $.ajaxの .done .fail みたいな感じか )
成功を知る例
function myFunction() { return new Promise((resolve, reject) => { setTimeout(() => { // 成功したことを通知 resolve('success!') }, 1000) }) } // 1秒後にmyFunctionが終わった知らせを受けてthenの処理が行われる myFunction().then(value => { console.log(value) // -> success! })
拒否(失敗)した事を知る例、かつ成功、失敗の両方の処理を書いた例
function myFunction(num) { return new Promise((resolve, reject) => { if (num < 10) { resolve('success!') } else { reject('error!') } }) } myFunction(100).catch(value => { console.log(value) // -> error! })
成功、拒否、どちらでも処理する際はfinally
を使う
myFunction().then().catch().finally(() => { // 成功でも失敗でも行われる })
Gitリポジトリからcloneして動かす際
プロジェクトフォルダをそのままリモートリポジトリに上げる。 別の環境でnode.jsをインストールして任意のフォルダで以下の操作をするだけでOK
git clone **url** npm install npm run dev
これだけで動く
□まとめ
- Vue CLI はVue.jsプロジェクトのベースを構築してくれる
- Vue CLI で単一ファイルコンポーネントを手軽に使用できる
- ES2015以降のECMAScriptを使ったコーディングが可能、基本を把握しておく
【勉強会資料】Laravelのルーティングについてのいろいろ
以下は[秋葉原] 第二回 初心者向けLaravel 勉強会 (ルーティング/テスト)にて行われた発表用の資料となります。 Laravel5.6の有志制作のリファレンス・ルーティングや、いくつかの記事を参考にかかせていただいたものです。
ルーティング知っているようで、知らない事が多くありました。自分の書き方が古いバージョンのものだけど、動いているとか。普段は自分に必要な事柄だけしか読まないのですが、改めてリファレンスの隅々まで読んだ事で、より効率的に、汎用的な事が出来そうです。