gurelog

エンジニアになるため、日々学んだことをまとめています

【Laravel】親モデルを削除したら子モデルも削除されるようにする!

こんにちは。gureです。

今回は親モデルを削除したら子モデルも削除されるようにする方法をまとめました。

 

今回の親→item

子→bookmark です。

商品本体が削除されたら、ユーザーがブックマークしていた商品もブックマークテーブルから削除してね!が今回のお願いです。

切実。

 

モデルに追加

Item.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
 protected $fillable = ['name', 'bland', 'image', 'price'];
 
 public function bookmark()
{
 return $this->hasMany('\App\Models\bookmark');
}

public static function boot()
{
 parent::boot();

 static::deleting(function($item) {
 $item->bookmark()->delete();
});
}
}

 

下記の部分を追加しました。


public static function boot()
{
 parent::boot();

 static::deleting(function($item) {
 $item->bookmark()->delete();
});
}
 

 

boot()メソッドはレコードの登録や削除の際に呼ばれるメソッドだそうです。

ここにdeleting()というメソッドを追加することで、Item::delete()が呼ばれたとき=商品が削除された時、関連するBookmarkモデルが削除されるという仕組みみたいです。

裏であれこれとやってくれているんですね。えらい。

 

 

今回の作業はRailsでいうdepends::destroyにあたるものですね。

同じことをするにも、Laravelには方法が多すぎて迷ってしまいました。

どうやら公式には削除の方法は載っていないらしく、、?調べても公式ではヒットしませんでした、、。

あんなになんでも詳しく載せてくれているのにどうして、、という気持ちです。

 

おしまい。

 

 

参考資料

https://oki2a24.com/2020/08/03/deleting-laravel-related-models/

https://qiita.com/naomichi-y/items/a2a0e7e74048871de5e6

 

【Laravel】ログイン&新規登録後のリダイレクト先をトップページにしたい

 

こんにちは。gureです。

今回は、ログイン/新規登録後のリダイレクト先をトップページに変える方法についてまとめたいと思います。

 

デフォルトで実装されている認証機能を使うと、ログインした後と新規登録した後は/homeへ戻ってしまいます。

ただ今回はデフォルトの/homeは使用していないので、トップページに戻っていただきたいのです。

 

というわけで、app/Http/Controllers/Auth/LoginController.phpの最後に追記します。

 
class LoginController extends Controller
{
 
 
・・・なんかいろいろ書いてある・・・
 
//追記
public function redirectPath()
{
return '/';
}
}
 
 

 

これでログイン後はトップページに戻ってくれます。

新規登録後も同様にしたいので、今度はapp/Http/Controllers/Auth/RegisterController.phpに追記します。

 

class RegisterController extends Controller
{
 
 
・・・なんかいろいろ書いてある・・・
 
//追記
public function redirectPath()
{
return '/';
}
}
 
 

 

これで新規登録後もトップページに戻ってくれるようになりました。

 

デフォルトの認証機能は諸々コミコミでやってくれるので大変便利ですが、、、決まっていること以外を実装するには裏側でどう動いているのかまで知っておく必要がありますね、、。

今日はてんやわんやしました。

おしまい。

 

参考資料

https://qiita.com/kamotetu/items/609862930a23d56e2258

【Laravel】コントローラーからビューに変数を渡す

こんにちは。gureです。

今回はLaravelでコントローラーからビューに変数を渡す方法についてまとめました。

 

どうやら3種類方法があるみたいです。

 

 

①[]とダブルアロー関数を使って渡す

ItemsController.php

public function index()
{
 $items = Item::latest()->get();
 return view('index', ['items' => $items]);
}

第一引数ではindexのビュー渡してねと指示を、

第二引数ではitemsは$itemsだからよろしくね、と渡しています。

 

②with関数を使って渡す

ItemsController.php

public function index(){
$items = Item::latest()->get();
return view('index')->with('items', $items);
}

 viewはindex、withではitemsは$itemだからよろしくね、と渡しています。①と似ていますね。

 

今回は変数が一つなのでよいですが、複数になると、

return view('index')->with('items', $items)->with('items2', $items2)->with('items3', $items3);

 と長ったらしくなるので、ちょっと使いづらいですね。

 

③compact関数を使って渡す

ItemsController.php

public function index()
{
 $items = Item::latest()->get();
 return view('index', compact('items'));
}

 その名の通りコンパクトですね。

第一引数ではindexのビュー渡してねと指示を、

第二引数ではitemsは変数でよろしく、と渡しています。

①と②をみているとよくそれで渡せるな、、?という気持ちになりますね。

 

個人的にわかりやすいのは①の方法ですが、同じ単語を何度も書く方法は手間的にもイマイチだな〜と思うので使っていきたいのは③です。

 

 

ちなみに、いずれもビューにはこんな形で変数を渡しました。

index.blade.php

@extends('layout')
@section('content')
@foreach ($items as $item)
 <p>{{ $item->bland }}</p>
 <img src="../../uploads/{{ $item->image }}" class="card-img-top">
 <h5>{{ $item->name }}</h5>
 <p>¥{{ $item->price }}</p>
@endforeach
@endsection

 @foreach ($items as $item)など視覚的に何がしたいのかわかりやすいのがいいですね。

 

だんだんPHPにも慣れてきて楽しくなってきました^ - ^

 

おしまい。 

 

参考資料

https://qiita.com/pipiox/items/af3e2c765677d5db8b4c

https://www.php.net/manual/ja/function.compact.php

https://toriyaru.com/2019/10/25/laravel%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%81%8B%E3%82%89%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AB%E8%A4%87%E6%95%B0%E3%81%AE%E5%A4%89%E6%95%B0%E3%82%92%E6%B8%A1%E3%81%99/

 

【Laravel】画像をアップロードするには?

こんにちは。gureです。

今回はLaravelで画像投稿機能を実装してみました。

 

完成品

完成品はこんな感じです。

入力フォーム↓

f:id:gure-y:20201017222111p:plain

表示↓

f:id:gure-y:20201017222301p:plain

 

ルーティングの設定

 web.php

<?php

use App\Http\Controllers\ItemsController;


Route::get('/',[ItemsController::class, 'index'])->name('index');

Route::get('/create',[ItemsController::class, 'create'])->name('create');
Route::post('/store',[ItemsController::class, 'store'])->name('store');

 indexに投稿したitemが表示されるようになっています。

createではitemの情報を入力フォームに、storeでは入力フォームで入力した内容を実際にDBに保存します。

 

コントローラーの設定

ItemsController.php

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\ItemValid;
use App\Models\Item;

class ItemsController extends Controller
{
 public function index(){
 $items = Item::latest()->get();
 return view('index', ['items' => $items]);
}

public function create(){
 return view('create');
}

public function store(ItemValid $request){
 if ($file = $request->image) {
 $fileName = time() . $file->getClientOriginalName();
 $target_path = public_path('uploads/');
 $file->move($target_path, $fileName);
} else {
 $fileName = "";
}
 $item = new Item;
 $item->name = $request->name;
 $item->bland = $request->bland;
 $item->price = $request->price;
 $item->image = $fileName;
 $item->save();
 return redirect()->route('index');
}
}

長いコントローラーは本当にこれでいいのか、、?という気持ちになりますね。 

 

if ($file = $request->image) {
 $fileName = time() . $file->getClientOriginalName();
 $target_path = public_path('uploads/');
 $file->move($target_path, $fileName);
} else {
 $fileName = "";
}

↑の2行目で保存した時刻とファイルの拡張子を組み合わせて$fileNameに代入しています。

3行目では保存先をpublic/uploadsに指定しています。

4行目で$fileNameはpublic/uploadsへと移動させます。

imageが添付されていない場合には条件分岐によって$fileNameには""が代入されます。

 

$item = new Item;
$item->name = $request->name;
$item->bland = $request->bland;
$item->price = $request->price;
 
$item->image = $fileName;
$item->save();

$itemのカラムそれぞれに$requestでとってきた(=入力フォームに入力された)各々の内容を代入します。

$item->imageには先ほど作成した$fileNameを代入して、保存します。

 

シンボリックリンクの作成

ターミナルで以下のコマンドを実行します。

$ php artisan storage:link

特定のファイルやディレクトリを指し示す別のファイルを作成し、それを通じて本体を参照できるようにする仕組みです。

 

入力フォームの作成

create.blade.php

@extends('layout')
@section('title', '商品投稿')
@section('content')

<form method="POST" action="{{ route('store') }}" enctype="multipart/form-data">
<p>商品名</p>
<textarea name="name"></textarea>
<p>ブランド</p>
<textarea name="bland"></textarea>
<p>画像</p>
<input type="file" name="image">
<p>値段</p>
<input name="price">
<button type="submit">作成</button>
<a href="{{ route('index') }}">キャンセル</a>
</form>

@endsection

 

 画像はtype="file"にします。

 

表示画面の作成

index.blade.php

<div class="container py-4">
@if(!isset($items[0]))
<span>登録なし</span>
@else
@foreach ($items as $item)
<div class="col-md-4 text-left mt-4">
 <div class="card-deck">
  <div class="img-flex-4">
   <div class="card">
    <p class="card-text"><small class="text-muted"> {{ $item->bland }}</small></p>
    <img src="../../uploads/{{ $item->image }}" class="card-img-top">
    <div class="card-body">
     <h5 class="card-title">{{ $item->name }}</h5>
     <p class="card-text">¥{{ $item->price }}</p>
     <a href="{{ route('edit', ['id'=>$item->id]) }}">編集</a>
     <a href="{{ route('delete', ['id'=>$item->id]) }}" id="btn-bell">削除</a>
    </div>
   </div>
  </div>
 </div>
</div>
@endforeach
@endif
</div>

 

画像の表示の部分ではpublic/uploadsに入っている画像を参照しています。

<img src="../../uploads/{{ $item->image }}" class="card-img-top">

 

 

Laravelでアプリケーションを作ってみているのですが、MVCの流れなどなどは記述が違うだけで、やっていることはRailsと同じですね。

ただ画像のアップロードの方法は全く別物で難しかったです。

 

おしまい。

 

 

参考資料

http://e-words.jp/w/%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%83%E3%82%AF%E3%83%AA%E3%83%B3%E3%82%AF.html

https://qiita.com/ryo-program/items/35bbe8fc3c5da1993366

個人的UNIXコマンドまとめ

こんにちは。gureです。

今回はUNIXコマンドを基本コマンドから個人的なんじゃこりゃコマンドまでまとめてみました。

 

cd (change directory)

ディレクトリを移動する

cd project
# projectというディレクトリに移動
cd ~/
#ホームディレクトリに移動
cd ..
#一つ上の階層のファイルに移動

 

ls (list)

カレントディレクトリにあるファイルを表示する

ls
#ファイル #ファイル #ファイル

 

pwd (print working directory)

カレントディレクトリを表示する

#今ここ

 

mkdir(make directory)

ディレクトリを作成する

mkdir project
#カレントディレクトリの中にprojectというディレクトリができる

 

rmdir(remove directory)

ディレクトリを削除する(そのディレクトリが空の場合のみ)

rmdir project
#カレントディレクトリの中のprojectというディレクトリが削除される

 

touch

中身が空のファイルを作成する

touch index.html
#index.htmlというファイルがカレントディレクトリの中にできる

 

tail

ファイルの末尾部分を表示する

 

grep

ファイル内の文字列を検索する

grep "index" project
#projectディレクトリからindexを検索

 

chown(change owner)

ファイルの所有者を変更する

chown gure index.html
#index.htmlの所有者はgureになった

 

chmod(change mode)

ファイルの保護モードを変更する

 

 

mv(move)

ファイルを移動する・ファイル名を変更する

mv index.html project/
#index.htmlというファイルがprojectディレクトリに移動する
mv index.html edit.html
#index.htmlというファイルの名前がedit.htmlに変わる

 

rm(remove)

ファイル/ディレクトリを削除する

rm index.html
#index.htmlというファイルが削除される

 

echo

変数の値を表示する

 

export

環境変数として変数を設定する

export PASSWORD='secret'
#VPASSWORD='secret'として環境変数が設定された

 

ps(process)

プロセスの状態を表示する

ps
#現在動作しているプロセスが表示される

 

kill

プログラムを終了させる

kill 25346
#25346というプロセス番号のプログラムを終了させる

 

 

 

コマンドは文章や単語が省略されている場合が多いので、初見のコマンドはなんじゃこりゃ??となってしまいますね。

最初mkdirを見た時、このコマンド何ができるんだ、、??と思ってしまいました。

おしまい。

 

参考資料

http://www5.plala.or.jp/vaio0630/ftp/command.htm

Dockerとは?

こんにちは。gureです。

今回はDockerについて理解が曖昧なままだったので、まとめてみようと思います。

 

Dockerとは?

 

Docker社が開発している、コンテナ化を用いてアプリケーションを開発・配置・実行するためのオープンソースソフトウェア(OSS)のことです。

 

コンテナとは?

 

他のユーザーから隔離された実行環境のことです。

f:id:gure-y:20201015212507j:plain

くじら1頭分がひとつのコンテナになっており、コンテナの中にはそれぞれのアプリケーションとライブラリが入っています。

 

Docker便利ポイント!

◆コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる

👉本番環境と開発環境を同じ環境にすることができる

👉開発者同士の開発環境の違いに左右されない

 

◆1つのOSに対して、多数のコンテナを管理、コンテナ同士は隔離されている

👉仮想マシンに比べて軽い&速い

↓コンテナAのくじらだけが起きて動いているので、コンテナBやCの重さに左右されない

f:id:gure-y:20201015212507j:plain

 

◆コンテナ作成に必要なリソースが少ない

👉導入も簡単

 

 

組織内で誰かと開発をする際には必須ということですね。

便利!

まだまだ深掘りできそうなのでまた今度さらに詳しく調べてみたいと思います。

おしまい。

 

参考資料

http://docs.docker.jp/

https://knowledge.sakura.ad.jp/13265/

https://qiita.com/rawHam/items/80ba13d2d2d56dba411e

https://www.geekly.co.jp/column/cat-technology/1902_047/

【Ruby】AからZまでの配列を作る

こんにちは。gureです。

今回は AからZまでの配列を作りたかったので、方法について調べてみました。

 

方法

 


p ("A".."Z").to_a

#結果
["A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
 

 

あら簡単。

数字の範囲オブジェクトと同様に表せるんですね。

その変わり配列に入れないとAからZは出せません。

p ("A".."Z")

と入れると、

#結果
"A".."Z"

と返ってきます。

文字列の集合なのでそれもそうか。と言う感じですね。

 

* (Splat Operator)を使っても、同じ結果が得られます。

p [*'A'..'Z']

 

* (Splat Operator)は奥が深〜〜〜いようなのでまた今度じっくりとまとめてみたいと思います。

イメージ的にはJavaScriptのスプレット構文ぽいな〜と思っています。

 

他の言語もまたいで理解を進めていくのは楽しいですね。

おしまい。

 

参考資料

https://qiita.com/7kaji/items/6e8a38901a5382f03db3