- 投稿日:2020-11-21T23:56:20+09:00
DockerでLaravel環境を構築するためのディレクトリ構造を一発で作成できるコマンドライン
DockerでLaravelの環境構築をする度に、ディレクトリやdockerファイル作成のためのコマンドを入力するのが面倒だったので、1回のコマンドラインで下記のような構造を作成できるようにしました。
application ├─ docker │ ├─ php │ │ └─ Dockerfile │ └─ nginx │ └─ default.conf └─ docker-compose.yml$ mkdir -p application/docker/php && mkdir -p application/docker/nginx && cd application/docker/php && touch Dockerfile && cd .. && cd nginx && touch default.conf && cd ../.. && touch docker-compose.yml上記コマンドを入力すれば最低限Dockerの環境構築に必要なディレクトリやファイルを作成できます。
プロジェクト名「application」などは必要に応じて適宜変更して下さい。
- 投稿日:2020-11-21T18:53:04+09:00
LaravelのSeeder実行時に「Class 'Database\Seeders\Datetime' not found」エラーが出たときの対処法
背景
LaravelでSeeder実行時に少々詰まったので共有します。
環境
Laravel Framework 8.15.0
現象
Seederファイルを用意した状態でSeederを実行するとエラーが発生する
$ php artisan db:seed Seeding: Database\Seeders\FutsalsTableSeeder Error Class 'Database\Seeders\Datetime' not found at database/seeders/FutsalsTableSeeder.php:22 18▕ [ 19▕ 'name' => 'futsal 1', 20▕ 'place' => 'tokyo', 21▕ 'url' => 'xxx', ➜ 22▕ 'created_at' => new Datetime(), 23▕ 'updated_at' => new Datetime() 24▕ ], 25▕ [ 26▕ 'name' => 'futsal 2',原因
Datetimeに関して、use宣言をしていないため
解決策
use DateTime
を追記すればOKです。HobeTablesSeeder.php<?php namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; use DateTime; // ←これを追加 class FutsalsTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // 省略 } }
- 投稿日:2020-11-21T16:40:56+09:00
【Laravel6でエラーが出た】BadMethodCallExeption: Method Illuminate¥Routing¥Rout::get does not exist.
【Laravel6でエラーが出た】BadMethodCallExeption: Method Illuminate¥Routing¥Rout::get does not exist.
使用環境
- windows 10 Home(COREi7)
- XAMPP 7.3.18
- Laravel 6
背景
Laravel5.7入門の動画に沿ってLaravel6の学習をしていた。
しかしながら、ところどころ違うところも出てきており、極力、ファイルをいじらずに進め、php artisan serveをしようとしたところエラーが発生。routesディレクトリ中のweb.phpを見てみると、以下のようになっていた。
<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ use App\Http\Controllers\TaskController; use Illuminate\Routing\Route; Route::get('/', function () { return redirect('/tasks'); }); Route::get('/tasks', 'TaskController@index'); Route::post('/tasks', 'TaskController@store'); Route::delete('/tasks/{task}', 'TaskController@destroy');
- 解決案1
エラー文そのまま検索してみるとちょうど同じ状況に陥った人の記事を発見できた。
https://qiita.com/tatuki81/items/6384f21382c17200de0d早速、同じことをしてみる。
use App\Http\Controllers\TaskController; use vendor\laravel\framework\src\Illuminate\Routing;しかし、エラーは解決できず...
- 解決案2
- 違う記事を見つけたので同じことを試してみる https://teratail.com/questions/257584
まずは以下のように。
use App\Http\Controllers\TaskController; use Illuminate\Support\Facades\Route;すると、
php artisan serve
できた。内容を見てみると同じRoute.phpというファイル名でも中身は全然違う。
Illuminate\Support\Facades内のRoute.phpは以下のような内容。
<?php namespace Illuminate\Support\Facades; /** * @method static \Illuminate\Routing\Route fallback(\Closure|array|string|callable|null $action = null) * @method static \Illuminate\Routing\Route get(string $uri, \Closure|array|string|callable|null $action = null) * @method static \Illuminate\Routing\Route post(string $uri, \Closure|array|string|callable|null $action = null) * @method static \Illuminate\Routing\Route put(string $uri, \Closure|array|string|callable|null $action = null) * @method static \Illuminate\Routing\Route delete(string $uri, \Closure|array|string|callable|null $action = null)わかったこと
原因は指定したファイルにメソッド(getとか使えるように書いてある)が入っていないよ!ということだったらしい。
メソッドが入っているIlluminate\Support\Facades内のRoute.phpを使うよという風にしたことでエラーが解除されたみたい。
- 投稿日:2020-11-21T12:17:04+09:00
【未経験・独学】Laravelでアプリケーションの開発からAWSを用いたデプロイまで
はじめに
今回は、社内向けの質問アプリケーションの開発・デプロイをした際の話についてまとめます。
なにかアプリケーションを開発中もしくはこれから開発する方の参考になれば幸いです。開発スタート時
- 23歳
- 実務未経験
- 大学は非情報系
- PHPの基礎とLaravelの基礎を3ヶ月ほど学んだ状態
- 資格:基本情報技術者
アプリ紹介
今回開発したものは、「社内向けの質問アプリケーション」です。
デモ
デモ1(ゲストログイン・質問記事ページ・コメントプレビュー・タグ検索)
見ていただくと分かるとおり、大部分はQiita風です。開発を進めていく上で頭の中でイメージしていたものがかなりQiitaに近かったからです(日常でQiitaを使っていたためかなり影響を受けました笑)
ただ、同じモノを作るのではなくその上で、自分なりの工夫を追加していきました。
例えば、質問の重要度(急ぎ・お手すきに・その他)の指定・解決済みの質問には解決済みと表示される・質問や回答をした際に以下のようにSlackのチャンネルにて通知がいくようにするなど・・・。開発背景
実際に社会人として働いてみて以下のことを感じました。
1.この質問、複数人(複数回)聞かれていそうor今後ありそう
→同じ質問に、何度も回答するのは回答者に負担がかかってしまう。2.チャット上での質問や回答に限界がある
コロナウイルスの影響も有り、在宅ワークが増えています。そのため質問をする際はチャット上で行う機会が今まで以上に増えています。しかし、どうしてもチャット上での質問では自分の考えや思いを伝えることに限界があると感じました。どうやって解決するか?
1の問題に対しては、頻繁に聞かれることは社内にドキュメントとして残しておけばいいと思います。しかし、何度か聞かれたことに答えた後、「これ頻繁に聞かれるからまとめておこう」と思っても手間がかかるため、ついつい後回しになりがちかと思います。
→それなら、質問に対しての回答がそのまま社内にドキュメントとして蓄積していけば、手間がかからなくていいのでは?
社内向けの質問・回答アプリケーションがあれば、そのまま質問とその回答がデータとして蓄積していくのでよさそう!2の問題を解決するために、マークダウン記法が使えるようにしようと思いました。マークダウンを使えば、視覚的にもわかりやすくなりますし、質問・回答の幅も広がると考えたからです。
こういった背景より製作物のベースとなる機能を考え、開発を行いました。
実装機能
実装機能自体に難しい技術は特に使っていなく、あったらいいなと思うものを随時追加しています。
◯ログイン系
・ゲストログイン→フィードバックを周りの人にもらうためにもログインを簡単に!
・Twitterログイン(TwitterAPI)
→初めての外部API学習で実装。会社で使うことを想定したらいらないとのちのち気づく。一応残している。
・Googleログイン(GoogleAPI)→会社で使うならGoogleログイン必須!◯基本的な機能
・質問のCRUD機能
・回答(コメント)のCRUD機能
・検索機能(ワード検索・タグ検索)
・質問下書き保存機能(下書き保存中はトップに表示されない)◯その他
・質問作成、編集時のリアルタイムプレビュー機能(jQuery,marked.js,highlight.js)
・回答作成、編集時のプレビュー機能(jQuery,marked.js,highlight.js)
・マークダウン記法確認用のヘルプモーダル(Bootstrap)
・質問作成時の簡易テンプレート文作成機能(jQuery)
・質問のブックマーク機能(Vue.js)
・プロフィール編集時の画像プレビュー表示機能(AWS S3,Vue.js)
・質問・回答投稿時Slackの指定チャンネルへの通知機能(SlackAPI)
・機能テスト(PHPUnit)上記機能を実装するにあたっていくつかまとめましたので、是非参考にしていただけると幸いです。
◯まとめた記事
・TwitterAPI+LaravelでTwitterログイン機能を実装する
・Laravel(7.20.0)でゲストログイン機能を実装
・composer require時に起きたメモリー制限エラーとその解決策
・Laravel + AWS S3で画像アップロードを行う
・Vue.jsで画像プレビュー機能を実装
・【失敗】Laravelでのテスト時にデータが消えてしまった件について開発期間
基本的な機能とAWSのデプロイ(あと実はDockerでの開発環境の構築とそれにともなう学習も行ったりしていました。)等の最低限必要なことを1.5ヶ月(7~8月)ほどで行いました。
9月以降は、自分のペースでちょこちょこ機能の追加実装を行いました。
また、開発中学んだことはQiitaでまとめたりしていました。
GitHubの活動量はこんな感じです。(今回の開発以外の技術学習での活動も含んでいます。)開発を続けていくちょっとしたコツとして最近取り入れたことは、iPhoneのウィジェットにGitHubのContributionsを表示させることです。iPhone上で常に表示されているため、モチベーション維持として効果的でした笑。
やり方についてはこちらにまとめました。
iPhoneのウィジェットでGitHubの草を確認する使用技術
- 言語:PHP7,JavaScript
- フレームワーク・ライブラリ:Laravel(7.20),Vue.js(2.5.17),Bootstrap4,jQuery(3.5.1),marked.js,highlight.js
- DB:MySQL
- インフラ:AWS(VPC,EC2,RDS,Route53,S3)
- OS:Amazon Linux2
- Webサーバー:Nginx
技術選定理由
◯PHP/Laravel
元々学習中だったこともあり選定。また、公式ドキュメントはわかりやすく、情報も沢山あるため。◯jQuery,Vue.js
最初は、jQueryで実装していたが製作過程でVue.jsの学習を始めたことも有り途中から導入しました。(あまり良くはないかと思いますが)
非同期処理の実装にあたり使用しました。どちらも初学者でも比較的取り組みやすく、情報も豊富なため選択。◯marked.js,highlight.js
マークダウン記法を使用したかったためmarked.jsを使用。マークダウン中のコード部分にハイライトしたかったため、highlight.jsを使用。◯MySQL
今までの学習でMySQLを使用していたため選択。また、多くの企業のDB部分で採用されているため。◯AWS
多くの企業のインフラ部分で採用されているため選択。選考中の課題で指定されることもあった。AWSの学習は、主にUdemyの講座と書籍で大枠を学びました。
・AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得
・ゼロからわかるAmazon Web Services超入門 はじめてのクラウド (かんたんIT基礎講座)◯Nginx
Q-SuccessのWebサーバーシェアの調査より、Nginxの増加傾向があるという記事を見て選定。参考:Nginx系が増加し、Apache減少 - 8月Webサーバシェア
Nginxを使用するにあたり、学んだことはこちらにまとめました。
【学習記録】PHP-FPMとは?インフラ構成
使用したAWSのサービスは、VPC・EC2・Route53・RDS・S3です。
よく見かけるインフラ構成図を書いたことがなく、てっきり他の人はPowerPointで作っているのかな~とか思っていましたが、そんなことはなさそうでした。
調べてみてでてきた、Lucidchartというものを使用して構成図を作りました。本来は、DBなど複数用意して冗長化するべきなのですが・・・。
インフラ部分はまだまだ改善の余地はあるので、改善をしていきたいと思います。意識したこと
開発していく上で下記のことを意識しました。
・ユーザー目線で開発する
開発しても必要の無い機能を実装したところで意味がないので、ユーザー目線で考えてどういった機能があったらいいか想像しながら開発を行いました。・意見をもらう
さきほど、ユーザー目線で開発するとはいったもののやはりどうしても自分だけで考えて開発すると考えが偏ってしまいますし気づけないことがあります。そのため、実際に誰かに触ってもらいどういった改善が必要か意見をもらうことが非常に大事だと思います。せっかくの機会なので、もしこんな機能あったらいいんじゃない?というアイデアやアドバイスがありましたら是非コメントを頂けるとうれしいです。
・Qiita上でのアウトプット
書籍やUdemyの講座で学習したはいいものの、それだけだと正直すぐに忘れてしまいます。開発によるアウトプットでも身につきますが、Qiitaのようなサービスで学習したことをまとめてみると結構知識として残るのでおすすめです。忘れたとしても、自分の記事を読み返して思い出せます。
また、外部に発信するので適当なことは書けない→ある程度しっかり調べるような習慣がつきます。
つまりいいことだらけ!!!今回のモノ以外では過去にこんなものを作ってアウトプットしたりしています。
見ていただけると分かるかと思いますが製作物自体はちょっとしたものですが、色々学ぶことが出来ました。まずはちょっとしたものから作ってみることをおすすめします!よかったら是非見てください。
・ラズパイを使って、【ある作業】を自動化してみた
・小学生時代の僕へ、「OCRで【いつもの作業】やっておいたよ!」今後の課題
アプリに関する課題
- UI/UXの改善
- テストコードを増やす
- CI/CDを導入する
- 細かな修正
- 質問記事部分に画像を投稿できるようにする
個人的な課題とその対策としては
- インフラ部分の学習 → 実際に色々使う・Udemy等
- git周りの学習 → 実際に色々使う・Git使い方入門
- 可読性の高いコードを意識すること → リーダブルコード
- Linuxの基礎の学習 → Linux標準教科書(pdf版無料だったはず!)
などなど・・・。もちろんまだ色々課題点はありますが、少しずつ出来ることを増やしていきたいと思います。
まとめ
今回は、未経験・独学の自分がLaravelで社内向け質問アプリケーションの開発からデプロイまで行った話についてまとめさせていただきました。
今までデプロイもherokuで1度やったことがあるくらいでしたので、特にAWSでのデプロイ部分には苦戦しました。
今回は一人で全て行ってきましたが、コードの質はどうしても低くなってしまうのでメンターを付けてコードレビューしてもらいながらやったら良さそうだと感じました。
引き続き学習を続け、Qiitaで発信していきたいと思います。
よろしければ
LGTM
よろしくお願いいたします!!
- 投稿日:2020-11-21T10:20:30+09:00
Laravel+jQuery+fullCalendarで予定を非同期で登録する
先日投稿した記事と被っている箇所がありますがあしからず。
【技術スタック】
- Laravel 6.0
- AdminLTE 3 (ComposerでLaravelにインストール)
- jQuery 3.3.1+ (AdminLTEにデフォルトで入っている)
- FullCalendar 5.3.2 (AdminLTEでデフォルトで入ってるのは古いので別途新しいバージョンをCDNで導入)FullCalendar概要
オープンソースのカスタマイズ可能なjQueryのカレンダーライブラリ。
公式ドキュメント:https://fullcalendar.io/docs
※FullCalenderのバージョンによってFullCalendarのコードの書き方がかなり変わるようなので、注意が必要です。
ver.3まではjQueryの記述方法でカレンダーを描画していましたが、ver.4以降は生のjavascriptでの記述方法に変わりました。
- DOMの取得方法がネイティブのgetElementByIdになった
- カレンダーの生成方法が new FullCalendar.Calendar() になった
JavaScript カレンダープラグイン FullCalendar ~その1 スケジュール表を作成する~ | 打ち聞かせ 様より引用
全体の大まかな流れ
- モデル、テーブル作成しておく(FullCalendarのイベントに対応するカラム名にする)
- フォームに情報を入力してボタンをクリックすると、jQuery側でクリックを検知&フォームの情報を取得
- Ajaxを使い、2で取得した情報をPOSTでコントローラー側に送信
- コントローラー側で送信された情報をsave
基本の書き方が下記。
var calendar = new Calendar(calendarEl, { timeZone: 'UTC', events: [ { id: 'a', title: 'testEvent', start: '2020-11-01' } ] })https://fullcalendar.io/docs/event-parsing に記載のイベントオブジェクト一覧で、全てのイベントに関連するプロパティを見ることができます。
下記一部抜粋です。
プロパティ名 概要 id 文字列または整数。イベントを一意に識別します。getEventByIdに便利です。
start
イベントの開始時刻。イベントが明示的に allDay である場合、時、分、秒、ミリ秒は無視されます。 title
イベントに表示されるテキスト。 color
backgroundColorとborderColorを同時に指定するためのエイリアス。
上記の記述方法だと、 「testEventというイベント名が2020/11/1の日付に表示」されます。
今回は、 events の中身を、DBの値に置き換えていきたいと思います。1. モデル、テーブル作成しておく(FullCalendarのeventプロパティに対応するカラム名にする)
$ php artisan make:model Event -mで、モデル作成&マイグレーションファイルを作成します。
マイグレーションファイルを下記のように編集// create_events_table.php public function up() { Schema::create('events', function (Blueprint $table) { $table->bigIncrements('id'); $table->timestamps(); $table->date('start'); $table->date('end')->nullable(); $table->string('title'); $table->string('color')->nullable(); }); }$ php artisan migrateでマイグレーションをかけてeventsテーブルを作成します。
2. フォームに情報を入力してボタンをクリックすると、jQuery側でクリックを検知&フォームの情報を取得
// test.blade.php <div style="margin-top:30px; border:1px solid gray;"> <form id="form" action=""> <p><input type="text" name="title" placeholder="タイトル入力"></p> <p><input type="date" name="start" placeholder="日付入力"></p> <p><input type="color" name="color" ></p> </form> <button id="bt2"> Ajax->DBにPostテスト </button>CSSはガン無視です(笑)
inputタグのname属性に、送信したい値のキーを書いてあげるのがポイントです。// scriptタグの中 $("#bt2").click(function () { // bt2のidの要素をクリックしたときに発動 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); var formData = $("#form").serialize(); // ajax部分は後に記述 // });$.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, });はおまじないです。これを設定することによって、セキュアなAjax通信を行うことができます。
var formData = $("#form").serialize();
では、フォーム要素を取得して、name属性とvalue属性をキーとvalueの形式に変換します。
※ jQuery serializeでキーバリューにするサンプル | ITSakura 様を参照3. Ajaxを使い、2で取得した情報をPOSTでコントローラー側に送信
$("#bt2").click(function () { $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); var formData = $("#form").serialize(); console.log(formData); $.ajax({ //POST通信 type: "post", //HTTP通信のメソッドをPOSTで指定 //ここでデータの送信先URLを指定します。 url: "/postevent", //通信先のURL dataType: "json", // データタイプをjsonで指定 data: formData, // serializeしたデータを指定 }) //通信が成功したとき .then((res) => { console.log(res); // カレンダーの再描画 var calendarEl = document.getElementById("calendar"); var calendar = new FullCalendar.Calendar(calendarEl, { headerToolbar: { left: "prev,next today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek", }, locale: "ja", editable: true, googleCalendarApiKey: "GoogleのAPIKEY", eventSources: [ { googleCalendarId: "japanese__ja@holiday.calendar.google.com", //祝日の予定を取得 rendering: "background", color: "#FF6666", }, ], events: "/getevents", selectable: true, }); calendar.render(); //カレンダーを再描画 }) //通信が失敗したとき .fail((error) => { console.log(error.statusText); }); });4. コントローラー側で送信された情報をsave
//web.php Route::post('/postevent', '****Controller@postEvent'); //任意のコントローラー名を記述// コントローラー側 public function postEvent(Request $request) { $event = new Event(); $event->start = $request->start; $event->title = $request->title; $event->color = $request->color; $event->save(); return $event; }