- 投稿日:2020-05-17T23:33:14+09:00
valetを一度アンインストールしたら使えなくなったので、色々試行錯誤してみた
brew install dnsmasq
brew services restart dnsmasq
sudo brew services start --all で治った。
ping example.testみたいので、試すと楽
- 投稿日:2020-05-17T23:15:37+09:00
【Laravel・Eloquent】modelの関数名になぜscopeをつけるのか
scopeの定義方法
class Hoge extends Model { public function scopeFuge($query, $code) { //処理 } }関数名にscopeを追加し、引数
$query
と$code(引数名は自由)
を定義します。引数
$queryとは
この引数は、whereで取得されるのと同じBuilderインスタンスが渡されます。
$code(引数名は自由)
コントローラから渡された引数がこの値に代入されます。
例
Person.php(Model)
class Person extends Model { public function scopeNameEqual($query, $str) { return $query->where('name', $str); } }PersonController.php(Controller)
use App\Person; class PersonController extends Controller { public function search(Request $request) { $item = Person::nameEqual($request->input)->first(); //〜その他処理は割愛〜 return view('person.find, $param); } }scopeを呼び出す時は、関数名のscopeを省略します。
なぜscopeを使うのか
scopeを使うことにより、上記の2つの引数が利用できるようになります。
- 投稿日:2020-05-17T22:32:43+09:00
【VSCode】Laradockでデバッグできるようにしようぜ!!【Mac】
VSCodeの拡張機能を使ってデバッグ環境を作る方法を解説します。
拡張機能のダウンロード
予め
PHP Debug
という拡張機能をインストールしておきます。.envの書き換え
laradockディレクトリ下の
.env
を下記の2つの変数をfalseからtrueに書き換えます。WORKSPACE_INSTALL_XDEBUG=true PHP_FPM_INSTALL_XDEBUG=trueXdebugの書き換え
- laradock/php-fpm/xdebug.ini
- laradock/workspace/xdebug.int の変数を下記のように書き換えます。
xdebug.inixdebug.remote_host=docker.for.mac.localhost xdebug.remote_connect_back=0 xdebug.remote_port=9001 xdebug.idekey=Listen for XDebug xdebug.remote_autostart=1 xdebug.remote_enable=1 xdebug.cli_color=1 xdebug.profiler_enable=0 xdebug.profiler_output_dir="~/xdebug/phpstorm/tmp/profiling" xdebug.remote_handler=dbgp xdebug.remote_mode=req xdebug.var_display_max_children=-1 xdebug.var_display_max_data=-1 xdebug.var_display_max_depth=-1containerの再構築
docker-compose up -d --build nginx mysql
--build
オプションで起動します。イメージがある状態でも再度ビルドしてcontainerを立ち上げてくれます。Visual Studio Codeの設定
プログラム実行の設定(デバッグの設定)を行うのが
.vscode/launch.json
ファイルです。作業ディレクトリのlaunch.jsonファイルを作成して、下記を記述します。user_app_nameのところには自分のappディレクトリの名前をいれてください。
vscode/launch.json{ "version": "0.2.0", "configurations": [ { "name": "Listen for XDebug", "type": "php", "request": "launch", "port": 9001, "pathMappings": { "/var/www": "${workspaceFolder}/user_app_name" }, "log": true } }デバッグの実行
ソースの行番号の左側を押して、ブレークポイントを設定。
サイドバーのデバッグのボタンを押して、[Listen for XDebug]を選択し、RUNの△を押せば準備完了。ブレークポイントのところで止まるようになります。参考
- PHP on Laradock w/ Visual Studio Code(VS Code)でデバッグ環境 (特にon Mac) - Qiita
- VSCodeでMacOSにC言語デバッグ環境を構築 | だえうホームページ
- Vagrant + Virtualbox + Docker + Laradoc + Laravel + VSCode + XDebug の 環境を設定したメモ。 - Qiita
- docker+laravel+VSCode+Xdebugという開発環境を作る - Qiita
- 脱print文!Visual Studio Code + LaradockでPHPのコードを快適デバッグ - bitA Tech Blog
- 投稿日:2020-05-17T21:18:53+09:00
HomesteadのBoxインストールエラー対策(Windows + Vagrant アップデート手順)
環境
OS:Windows10 Pro
Vagrant:2.2.41.背景
Laravel5.x系の環境を利用していたが、laravel6.x系をインストールするのに、Homesteadを新しくしようとしたら、BOXのインストールエラーが出てしまったので、その時の対応メモ
$ vagrant box add laravel/homestead homestead: Calculating and comparing box checksum... The specified checksum type is not supported by Vagrant: sha512. Vagrant supports the following checksum types: md5, sha1, sha2562.対応
どうやらVagrant2.2.6からはCheckSumのサポートが変わった模様。Vagrantを2.2.9(2020.05 最新)にアップデートする。
VagrantのWindowsインストーラーを使ってアップデート(インストールすると、古いバージョン情報もクリーンしてくれるので、手動クリーニング作業などは不要でした)・Vagrantのインストーラー
https://www.vagrantup.com/downloads.htmlC:\Users>vagrant -v Vagrant 2.2.9以前のバージョンで利用していたローカルLaravel5.8系のサイトもVagrant upで起動・確認し影響ないことを確認。
再度実行
C:\Users\murat>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' (v9.5.1) for provider: virtualbox box: Downloading: https://vagrantcloud.com/laravel/boxes/homestead/versions/9.5.1/providers/virtualbox.box Download redirected to host: vagrantcloud-files-production.s3.amazonaws.com box: box: Calculating and comparing box checksum... ==> box: Successfully added box 'laravel/homestead' (v9.5.1) for 'virtualbox'!HomeStead + Vagrantで仮想サーバ起動してブラウザ経由でPHPファイル表示できたので、とりあえずここまで。
- 投稿日:2020-05-17T21:08:35+09:00
phpの「=>」(ダブルアロー演算子)と「->」(アロー演算子)
「=>」:ダブルアロー演算子
連想配列のこの「キー」にこの「値」を入れますよー
というのを表すための演算子。phpの
ダブルアローがわからなければこれを読むんだ!!http://raichel.hatenablog.com/entry/2015/01/15/012116
「->」:アロー演算子
インスタンスの持つ、プロパティにアクセスするための演算子。
この記事で私は理解した。
https://techacademy.jp/magazine/19296
インスタンスは「クラスを実体化したもの」。
インスタンスがわからないときには、オブジェクト指向を学ぼう。
- 投稿日:2020-05-17T20:49:14+09:00
LaravelでJSONリクエストを受け取る
前提条件
eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っていますControllerにメソッド追加
(1) /sample/app/Http/Controllers/SampleController.phpにrequestJson1メソッド、requestJson2メソッドを追記
public function requestJson1(Request $request) { return view('sample.requestJson'); } public function requestJson2(Request $request) { $data = [ 'a' => $request->input('a'), 'b' => $request->input('b.bb'), 'c' => $request->input('c')['cc'] ]; return $data; }(2) /sample/routes/web.phpに下記を追記
Route::get('sample/request-json1', 'SampleController@requestJson1');
Route::post('sample/request-json2', 'SampleController@requestJson2');viewの作成
/sample/resources/views/sample/requestJson.blade.phpファイル作成
requestJson.blade.php<html> <head> <title>sample</title> <script type="text/javascript"> function ajax(){ var form = document.getElementById("sampleForm"); var reqData = {"_token": null, "a": null, "b": {"bb": null}, "c": {"cc": null}}; reqData._token = form._token.value; reqData.a = form.a.value; reqData.b.bb = form.b.value; reqData.c.cc = form.c.value; var req = new XMLHttpRequest(); req.open(form.method, form.action); req.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); req.responseType = 'json'; req.send(JSON.stringify(reqData)); req.onload = function () { var json = req.response; alert("a:" + json['a'] + "\n" + "b.bb:" + json['b']+ "\n" + "c.cc:" + json['c']); } } </script> </head> <body> <form id="sampleForm" action="{{ url('sample/request-json2') }}" method="post" onsubmit="ajax(); return false;"> @csrf <input type="text" name="a" > <input type="text" name="b" > <input type="text" name="c" > <input type="submit" > </form> </body> </html>Laravelでjsonリクエストを受け取るようにするために
req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
を書きました
LaravelのControllerクラスはjsonを受け取るからと言って特別な記載は要りません
Content-Typeヘッダプロパティにapplication/jsonが指定されていれば、inputメソッドで値を取得できます動作確認
http://localhost/laravelSample/sample/request-json1
インプットフォームに値を適当に入力して送信ボタンをクリック
インプットフォームに入力した値がalertで表示された
- 投稿日:2020-05-17T20:40:00+09:00
laravel ルーティング
Route::get('/hoge', 'HogeController@index');【意味】
→「/hoge」パスにゲット送信でリクエストが来たら、HogeControllerのindexアクションへつなぐ(indexアクションの中で処理する)という意味。
名前つきルーティング
Route::get('/hoge', 'HogeController@index')->name('hoge');【使い所】
→コントローラやビューの中で URL を指定する時。素のPHPではソースコードに直にパスを書いていた。
しかし、この方法だと、パスに変更があった時に、多くの箇所を変更する必要がある。
そこで、ルートに名前を付け、ルート名で URL を指定することで、この問題を解決できる。
- 投稿日:2020-05-17T19:58:11+09:00
【Laravel】.env.testingの使用方法と注意点
LaravelでPHPUnitを使うときにテスト用の`.env`を設定するのにハマったので記事にしました。
環境
Docker 19.03.8
PHP 7.3.16
Laravel 6.18.3.env.testingの設定方法
本番DBを汚さないようにPHPUnitを実行する時のみテスト用のDBを使うようなことはよくあると思います。
その方法の一つとして
.env.testing
を作成し、phpunitにその設定値を読み込ませるやり方があります。
.env.example
をコピーして.env.testing
を作成し、以下の箇所を変更します。env.testingAPP_ENV=testing // testingに変更 APP_KEY= // 空にしておく // 接続したいDBの情報を設定する DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=test_database DB_USERNAME=root DB_PASSWORD=そうしたら
phpunit.xml
を開き、APP_ENV
の値をtestingに変更します。phpunit.xml<php> <env name="APP_ENV" value="testing" force="true"/> <env name="DB_CONNECTION" value="mysql"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_DRIVER" value="array"/> <env name="MAIL_DRIVER" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="SESSION_DRIVER" value="array"/> </php>最後に
.env.testing
に新規にアプリケーションキーを設定したら完了です。
これをしないと.env
のAPP_KEY
を参照しに行ってしまい、本番用のDBのデータが全部飛ぶので注意しましょう。php artisan key:generate --env=testingハマったポイント
docker-compose.ymlなどで環境変数に
APP_ENV
やDB_DATABASE
などの設定をしている場合、注意しなくてはいけない点があります。
phpunit.xml
で環境変数を上書きする際に、デフォルトだと<server>
タグになっていますが、これを<env>
タグに変更する必要があります。phpunit.xml<php> <server name="APP_ENV" value="testing" force="true"/> <server name="DB_CONNECTION" value="mysql"/> ... </php>phpunit.xml<php> <env name="APP_ENV" value="testing" force="true"/> <env name="DB_CONNECTION" value="mysql"/> ... </php>
<server>
タグと<env>
タグは以下のような違いになっています。$_SERVER['APP_ENV'] = 'testing'; // <server> $_ENV['APP_ENV'] = 'testing'; // <env>今回は
docker-compose.yml
で環境変数としてAPP_ENV
などを定義していたので、さらにそれを上書きする必要がありました。参考文献
Laravel 7.x テスト: テストの準備
Laravel × Docker でテスト用のデータベースコンテナを使う
- 投稿日:2020-05-17T18:49:33+09:00
ControllerからViewへの変数受け渡し
概要
Laravelの諸機能について忘れないようにアウトプットする自分用メモ。
ControllerからViewへの変数受け渡し
参考:https://qiita.com/ryo2132/items/63ced19601b3fa30e6de
参考:https://qiita.com/_Mizuki/items/df3a62fbe18bbbbc9ced
参考:http://blog.tojiru.net/article/230164798.htmlControllerからviewに値を渡す場合、ベターな方法が複数あるらしいので調べた。
phpのcompact関数
viewに値を渡す際、compact関数を使用する方法がわりとベターらしい。
compact関数の理解が怪しかったので確認した。
公式の解説では変数名とその値から配列を作成する。とのこと。公式の例
<?php $city = "San Francisco"; $state = "CA"; $event = "SIGGRAPH"; $location_vars = array("city", "state"); $result = compact("event", $location_vars); print_r($result); ?> // result Array ( [event] => SIGGRAPH [city] => San Francisco [state] => CA )良くわからん...。
自分なりに分かりやすかった例。$arr = array( 'apple' => $apple, 'orange' => $orange, 'lemon' => $lemon, ); // ↑ // 同じ意味 // ↓ $arr = compact('apple', 'orange', 'lemon');連想配列のkeyと変数名を勝手に紐付けてくれるらしい。
Controllerからviewへの変数の受け渡し
viewに値を渡すときにcompact関数を使用する場合は以下のようにするといい。
public function fruit() { $apple = 'apple'; $orange = 'orange'; $lemon = 'lemon'; return view('fruit', compact('apple', 'orange', 'lemon')); }Laravel独自のコレクションなのかと思ってたけど、そういうワケじゃないんですね...。
そもそもviewヘルパ関数がどんなだったっけと思って見直した。第二引数に連想配列渡すだけなんだ。それを作りやすいからcompact使っているだけ。
つまりこの書き方でも一緒です。public function fruit() { $apple = 'apple'; $orange = 'orange'; $lemon = 'lemon'; $fruit = ['apple'=>$apple, 'orange'=>$orange, 'lemon'=>$lemon]; return view('fruit', $fruit); }withメソッド
Controllerからviewへの受け渡しにwithメソッドを使用する場合。
public function fruit() { $apple = 'apple'; $orange = 'orange'; $lemon = 'lemon'; return view('fruit')->with('apple', $apple)->with('orange', $orange)->with('lemon', $lemon); }もしくはこう
public function fruit() { $apple = 'apple'; $orange = 'orange'; $lemon = 'lemon'; return view('fruit')->with([ "apple" => $apple, "orange" => $orange, 'lemon' => $lemon, ]); }ちょっと可読性悪いですね。
個人的ベスト
- 配列を渡す
状況にもよりますが、配列作って渡してあげる方法が一番好きです。
viewヘルパ関数の第二引数が大きくなるのはあまり好きではない。// 画面にフルーツを渡す public function fruit() { $fruit = $this->returnfruit(); return view('fruit', $fruit); } // フルーツの配列を返す private function returnfruit() { $apple = 'apple'; $orange = 'orange'; $lemon = 'lemon'; return compact('apple', 'orange', 'lemon'); }
- 投稿日:2020-05-17T17:30:58+09:00
laravel
facade/eloquentは辞めようという人が割と居て、そうだろうなーと思ったリンク集。
Laravel ファサードを利用しないメリット - ytake blog
- 投稿日:2020-05-17T16:37:58+09:00
webpackでビルドしたscriptに、HTMLから値を渡すアレ
LaravelやRailsみたいな環境で、バックエンドからフロントエンドに値を渡したいときのアレです。i18n対応とか。
方法忘れて2時間くらい溶けたのでメモ。今回の用途
LaravelのViewから
@lang('hoge.fuga')
ヘルパ関数で、i18n済みメッセージ文字列を渡したい今回は省略しますが、セキュリティ対策は各環境でお願いします。
Laravel View
コツってほどでもないですが
mix()
は一番最後。dokoka.blade.php... 中略 <script> var __SYS_GLOBALS_ = { HOGE_FUGA_MESSAGE: "@lang('hoge.fuga')" }; </script> ... 中略 / <script src="{{ mix('/js/app.js') }}"></script> </body> </html>Typescript側
モジュールとして、どこか新規ファイルに下記のように書いておけば良いです。
ただしインポートするとエラーになります。インポートはしない。不思議ですよね。__SYS_GLOBALS__.tsexport {}; declare global { const __SYS_GLOBALS__: any; }インポートするとTS内で再定義されてしまうのでしょうか、その場合確かに(TS内には)実体はないのでエラーになりそう。
TS2304: Cannot find name '__SYS_GLOBALS__'.あとはお好みで定数を使います。
nanika.tsalert(__SYS_GLOBALS__.LOADING_NOW_MESSAGE);まとめ
こんな設計はいけません。わかってはいるのですが、そういうときもあるのです。[終]
- 投稿日:2020-05-17T06:52:30+09:00
有料のWebサービスをリリースするまでに取り組んだこと・知見をまとめました【個人開発】
1. 作ったサービス
ツイ消し職人
https://twikeshi.net/ツイ消し職人は大量のツイートを消したい方向けのツールです。
3,200件を超えるツイートを一括削除できます。
無料のツールなどでうまく削除できなかった方は是非ご利用ください。
既存のフォロワーをそのままに、Twitterをやり直すことができます。2. 自己紹介
こんにちは、ひろと申します。
今年の3月に会社を辞め、現在はフリーランスエンジニアとして活動しています。メガバンクのシステムエンジニア →
広告代理店(東証一部上場企業)のWebエンジニア →
フリーランスエンジニアという経歴です。仕事でコードを書き始めたのは前職からで、プログラミングの経験年数は2年と9ヶ月くらいです。
3. なぜ作ったのか
私は今年の3月にフリーランスとして独立しました。
それに伴い、学生時代から使っていたTwitterアカウントの運用を変えようと思い、今までのツイートを削除してやり直すことにしました。
アカウントを作り直す選択肢もあったのですが、フォロワーを減らしたくなかったため、ツイ消しの道を選びました。
調べてみるとツイートの一括削除ツールがいくつか見つかったため、それを使ってツイ消しをすることにしました。しかし、既存のツールではツイートの削除ができませんでした。
私の今までのツイート数は19万件で、Twitterアーカイブをダウンロードしたところzipファイルのサイズはなんと31GB。スマホの7GBプランなら4.5ヶ月分の通信量が必要になってしまう、とんでもない容量です。
そう、私がツイ廃だったのが全ての原因です。普通のツイ消しサービスは、API制限の関係で3,200ツイートが削除の上限となってしまいます。私の19万ツイートに対してはあまりに無力すぎました。
もちろん、API制限を回避するためにTwitterアーカイブをアップロードして削除を行うサービスもあります。
しかし、31GBのzipファイルを送りつけると必ず500エラーが返ってきてしまい、私の試した範囲では、まともに動くものはありませんでした。海外の有料サービスでさえダメでした。(具体的なサービス名は出しませんが、日本円で1,600円払いました。手痛い出費です)そこで私は、「ツイ廃でもツイートを削除できるサービス」が必要だと思い、ツイ消し職人の開発を始めました。
4. リリースするまでに取り組んだこと
取り組んだ全てのことを記載しています。
一. サービスの命名
最初は「ツイートクリーナー」という名前にしていました。
開発中盤に「ツイ消し職人」という名前を思いつき、変更しました。
ランサーズなどで募集するのも良いと思います。二. ドメインの取得
ムームードメインでtwikeshi.netを取得しました。
欲しいドメインが埋まっている場合は、twikeshi-app.netのように工夫するのも良いと思います。三. 商標権の取得
今回はお金がなかったので保留しています(いつでも取れるように商標調査は終えています)。
今はToreruなどの便利なサービスがあり、ものすごく簡単に出願できます。
48,000円で5年間有効になります。
商標権の取る取らないを選択するのは自由ですが、後から商標を第三者に取得されて商標権の侵害警告を受けた場合、サービス名やドメインを変える必要があるリスクは認識しておく必要があります。四. プライシング
海外の同じようなサービスを参考に値付けを行いました。
現在は700円(税込)で提供しています。その後、プライシングに関する本を3冊読んで(この本とこの本とこの本)考え方が変わったので、そのうち値上げするかもしれません。
どんなに高くても、その価格で買いたい人がいます。私自身も、このサービスを他の人が作っていたとしたら、喜んで利用していました。
間違っても、本来ターゲットでない人を取り込むために値下げするのはやめてください。
例えば、私は友人達に「ツイ消し職人の適正価格はいくらだと思う?」と質問をすると、2人が「100円」と答えました。
しかし、断言しますが彼らは100円でも絶対に利用しません。何故ならば、彼らはこのツールの価値を理解していないからです。ツイ消しをしようと思ったことがない人に相場感を聞いても意味がありません。
逆に、本っっ当にツイ消しをしたくて困っている人からすれば、このツールが例え1万円でも喜んでお金を払うはずです。五. 技術選定
1. バックエンド
バックエンドはLaravelで開発しました。
私は前職でSpring Bootを使っていましたが、このフレームワークではTwitterログインを実装するのに苦労しそうだったため、一からLaravelを学ぶことにしました。
Railsと悩みましたが、後述する理由によりレンタルサーバーで運用したかったので、Railsは諦めました。
Laravelはコードもドキュメントも読みやすいため、使っていて楽しいですね。
ドットインストールのLaravel入門がとても分かりやすかったのでオススメです。
役割 技術 PHPフレームワーク Laravel データベース MySQL Twitterログイン Laravel Socialite Twitter APIライブラリ TwitterOAuth メール送信 SendGrid 2. フロントエンド
CSSフレームワークにはMaterializeを採用しました。これも初めて使ったのですが、ドキュメントが分かりやすく情報量も多いのでオススメです。
今回はフロントで処理をする必要が無かったので、基本的にJavaScriptは使っていません。ファイルアップロードの画面は、アニメーションを付けるためにVue.jsを使いました。Vue.jsは以前から使っていたので、特に困ることはありませんでした。
次はNuxt.jsに挑戦するために勉強中です。
役割 技術 CSSフレームワーク Materialize JavaScriptフレームワーク Vue.js 決済 Stripe Checkout 3. インフラ
バックエンドの項目で触れましたが、サーバーにはレンタルサーバーを採用しています。
役割 技術 レンタルサーバー エックスサーバー Heroku / VPS / AWS EC2 / GCP App Engineなどの選択肢もありましたが、主にコストと運用の観点から除外しました。個人開発は自分でインフラを選べるのが良いですね。
今後もどんどんサービスを作っていく予定なので、サーバー費がかさむのはイヤだし、サービスを作る度に環境を構築するのも避けたかったのです。もちろん要件によってはレンタルサーバーが使えない場合もあります(ミドルウェアの設定変更や追加インストールが必要な場合など)。
rootユーザーが使えないと困る場合は、状況に応じて各サービスを比較検討しましょう。
サーバーはHerokuだけどストレージにはAWS S3を使って、DBにはGCP Cloud SQLを使うといったトリッキーなこともできます。柔軟な発想で最適な構成を作りましょう。参考に、私の考える主なインフラサービスのメリット・デメリットをまとめておきます。
※App Engineは詳しくないので簡易的な記載になってます
インフラサービス メリット デメリット VPS(IaaS) ・安い
・root使える・借りる度にお金がかさむ
・環境構築や設定が必要EC2(IaaS) ・root使える
・マイクロサービス沢山ある・高い
・借りる度にお金がかさむ
・環境構築や設定が必要App Engine(PaaS) ・環境構築不要 ・高い
・借りる度にお金がかさむHeroku(PaaS) ・安い
・環境構築不要・借りる度にお金がかさむ
・30秒タイムアウト辛いレンタルサーバー(ほぼPaaS) ・安い
・1台でアプリ沢山動かせる
・環境構築ほぼ不要・root使えない 六. 設計
小規模なサービスなので、ここにはほぼ時間をかけていません。
ワイヤーフレームなどは作らず、実際に画面をコーディングしてレイアウトを決めました。
DB設計もパパッと考えて終わり。
開発の中で必要になったときに都度、テーブルやカラム・画面を増やしていきました。
サービスによっては色々な機能を思いつくと思いますが、まずはスモールスタートでリリースすることをゴールにしましょう。YAGNIは正義。七. 開発
一番時間をかけたのはこの工程です。
他の仕事が並行していたため正確ではありませんが、全体で2〜3週間はかかったと思います。
伝えたい情報がある場合はコメントを書いています。
有料サービスのみ必要になる項目には「☆」を付けています。1. サービスの機能開発
一. Twitterログイン
ツイ消し職人では、決済完了時とツイート削除完了時に確認メールを送信しています。
そのため、Twitter AppのAdditional permissionsとして、Request email addressにチェックを入れています。二. ☆決済
Stripe Checkoutは神。
JavaScriptをちょろっと書くだけで決済を提供できます。返金もボタンポチるだけです。
ツイ消し職人はクレジットカード、Google Pay、Apple Payに対応しています。三. アーカイブアップロード
Twitterが生成したデータを読み取らないといけないので、アーカイブのどのファイルに何の情報があるのかを全て自分で調べました。
そして、ツイートの削除に本当に必要なファイルだけをアップロードさせることで、ファイルサイズを31GB→200MBまで減らすことができました。アーカイブからはツイートの削除に必要な情報を正規表現で抽出する必要があります。
最初は、JavaScriptを使いフロント側で情報を抽出し、サーバーには最低限のデータだけ送るようにする予定だったのですが、少し時間がかかりそうだったので諦めました。FileReader.readAsText()に100MBのファイルを食わせるとクラッシュしてしまうことが判明し、ファイルをチャンクして処理する必要が出てきたためです。
コンソールにエラーは出力されず、サイレントでクラッシュするので問題の特定に時間がかかりました。マジでやめてほしい。
サーバ側で抽出処理をやっても特に問題はないので、サーバ側で処理するようにしました。四. ツイート削除
ノーコメント
五. 非同期処理
アップロードされてそのままツイートの削除を行うと、画面がタイムアウトしてしまいます。
そのため削除処理はLaravelのキューを使って非同期にしています。
失敗時の再実行もできるようになるので便利ですね。六. メール送信
必ずユーザーに到達するようにSendGridを使っています。
返信や問い合わせを受けるためにはメールサーバーの設定が必要なので注意してください。
サーバーが用意できない場合は、G Suiteなどのホスティングサービスを利用しましょう。七. ログ出力 + Slack通知
本番での例外発生時にはSlackにスタックトレースを飛ばすようにしています。
他にも、ツイート削除処理成功時など、正常系でも重要なものはSlackに通知を飛ばしてます。ログは、出せる項目をなるべく出すようにしています。
Laravelのログ出力について記事書いてるので興味あったら読んでください↓
【Laravel】ログのフォーマットを変更してIPアドレスやユーザー名などを出力する2. リリース準備
一. LP(トップページ)作成
ユーザーに効果的に訴求できる文言を考える必要があります。
デザイナーの人は腕の見せどころだと思います。
文字や画像・アニメーションを使っていい感じのレイアウトにしましょう。ペライチなどのツールを使っても良いと思います。
コンバージョンに直結するので、一番力を入れるべき部分です。外注も考えましょう。二. 利用規約・プライバシーポリシーの制定
この本が大変参考になりました。コピペできるひな形データも付いてくるのでオススメです。
三. ☆特定商取引法に基づく表示の作成
同上。
有料サービスの場合は必須です。
本名や住所、電話番号を晒さないといけないので、ここが一番の難関ではないでしょうか。
私の場合、IP電話アプリ(SMARTalk)を使い050から始まる電話番号を載せています。四. Googleアナリティクス・Search Console設定
ノーコメント
五. meta description設定
Googleの検索結果でタイトルとともに出るやつです。
meta keywordは不要です。六. ファビコン設定
GIMPで作りました。
サービスのロゴがある場合はファビコンにも活かせます。七. OGP設定
GIMPで作りました。
OGP画像を動的に生成するサービスでは、トップページ用の画像を同じ方法で作るのも良いかも。
CTRに直結するので、ここも外注を検討しましょう。八. サイトマップ設定
Search Consoleで送信します。
sitemap.xml Editorを使うと簡単に作成できます。
サイトが新しく、外部からのリンクが少ない場合はあったほうが良いみたいです。九. SNSシェアボタンの設置
↑こういうのです。
ユーザーに拡散してもらえる仕組みを作っておくことは重要です。
ちなみにツイ消し職人は全く拡散されていません。悲しい。十. お問い合わせフォームの設置
自分で作るのがめんどくさい場合は、Googleフォームやformrunなどを活用しましょう。
お問い合わせフォームの代わりに、チャットサポートツールを入れるのもオススメです。3. リリース
一. デプロイ
Laravel + レンタルサーバーの場合はgit pullすればほぼ終わりです。
あとは.env書いてマイグレーションしてキャッシュ系のコマンドを叩くだけです。
もちろん、GitHub ActionsなどのCIを設定するのも良いと思います。私の場合は、以下のようなデプロイスクリプトを用意しています。
deploy.sh#!/bin/sh git pull composer install --optimize-autoloader --no-dev php artisan config:cache php artisan view:cache php artisan route:cache二. テスト
本番環境で全ての機能がうまく動くことを確認しました。
中規模〜大規模サービスの場合は、検証環境の用意とテスト自動化がされていないと運用がしんどくなります。八. リリース後
1. 知り合い・友人への拡散
LINE, Twitter, Facebookなどで拡散して使ってもらいましょう。
2. プレスリリースを出す
お金があればPR TIMESなどの有名サイトに出すのがオススメです。
(もしくは、法人ならスタートアップチャレンジの条件を満たすと無料になります)私はお金がなかったので、valuepressのフリープランで配信しました。
3,200件を超えるツイートを一括削除できるツイ消しサービス「ツイ消し職人」を提供開始3. アプリ紹介サイトに登録
私の場合、AnyMakeやmakepost、Eggineer、Applishowを活用しています。
4. 新聞の広告枠に出稿する
リリース直後にスポーツ新聞の方から電話があり、新聞とサイトに広告を載せないかと打診がありました。
条件が合わなかったためお断りしましたが、人によっては選択肢になり得ると思います。5. アフィリエイト広告に出稿する
現在検討中です。
お金がある場合は、A8.netなどの大手ASPを使うのが良いと思います。
もしもアフィリエイトやマネートラックならば初期費用0円・月額費用0円で始められるようです。6. SNS広告に出稿する
現在検討中です。
私の場合はTwitterユーザーをターゲットにしたサービスなので、Twitter広告と相性が良いです。
とりあえず試してみて、どれくらい成果が出るかチェックしてみようと思います。7. 保守開発
本番環境でのエラーを監視し、新しく発現したバグがあれば修正しましょう。
手元で再現しないエラーは...ユーザー問い合わせを待つしか無い。。もちろん、機能追加などサービス改善のための開発は怠らないようにしましょう。
大幅リニューアルや作り直しなどの選択肢もあります。8. ブログなどでの発信
この記事のことですね。
Qiita, Crieit, Note, ブログなどの選択肢があります。
サービスを知ってもらうだけでなく、転職活動などでも役に立ちます。
- 投稿日:2020-05-17T01:14:35+09:00
PHP Laravel オブジェクト思考 用語集
目的
- Laravelの最低限理解しておきたい用語をまとめる
事前情報
- 必要な物が出てきたら随時追記してゆく。
- Laravelに限らず、PHPやその他のフレームワーク、オブジェクト指向に関する用語なども一緒に記載する。
- 筆者のメモ的要素が強いので
クラス
- オブジェクト思考でよく設計図に例えられるものである。
インスタンス
- クラスを元に作られた複製の事である。
$変数名 = new クラス名(引数);
として作ることができて変数の中にインスタンスが格納される。インスタンス化
- クラスからインスタンスを作成することである。
オブジェクト変数
- インスタンスが格納された変数の事である。
$変数名 = new クラス名(引数);
の$変数名
に当たるものを指す。メソッド(メンバ関数)
- クラスの中に書かれた関数の事を指す。
- オブジェクト変数内のメンバ関数の戻り値を変数に格納したい場合は
$戻り値を格納したい変数名 = オブジェクト変数->メソッド名(引数);
とする。プロパティ(メンバ変数)
- クラスの中に書かれた変数の事を指す。
オブジェクト変数->プロパティ名;
で呼び出すことが可能である。クラスメソッド(静的メソッド)
- オブジェクトを生成せずにクラス(設計図)の状態で呼び出せる関数のことである。
::
(ダブルコロン演算子)で呼び出すことができる。クラス名::メソッド名;
で呼び出すことが可能である。- 戻り値を変数に格納したい場合は
$戻り値を格納したい変数名 = クラス名::メソッド名(引数);
とする。- 呼び出し元がクラスである点に注意すること。
クラスプロパティ(静的プロパティ)
- オブジェクトを生成せずにクラス(設計図)の状態で呼び出せる変数のことである。
::
(ダブルコロン演算子)で呼び出すことができる。クラス名::プロパティ名;
で呼び出すことが可能である。- 呼び出し元がクラスである点に注意すること。
インスタンスメソッド
- インスタンス内にある関数の事を指す。
->
(アロー演算子)で呼び出すことができる。オブジェクト変数->メソッド名(引数);
で呼び出すことが可能である。- 戻り値を変数に格納したい場合は
$戻り値を格納したい変数名 = クラス名->メソッド名(引数);
とする。インスタンスプロパティ
- インスタンス内にある変数の事を指す。
->
(アロー演算子)で呼び出すことができる。ビジネスロジック
- システムの実際に処理をしている部分の事を指す。
- 変数に格納したり、値を処理したりする部分の事を指す。
- 意外と何を指すかは意外と曖昧である。
- システムの処理する部分のことである。
- システム固有の処理のことである。
ルートプレフィックス
- グループ内の各ルートのURLの最初に指定した共通の文字列を付与する。
例えばいくつかのルーティングで指定するURLの最初に「admin」と付けたい場合は下記の様に記載する。
web.php//グループ化で URLの最初にadminと付けたいルーティング情報を包む Route::prefix('admin')->group(function () { //URLの最初にadminとつけるルーティング情報を記載する Route::get('users', function () { // このルーティング情報にはURL"/admin/users"でアクセスできる }); Route::get('home', function () { // このルーティング情報には URL"/admin/home"でアクセスできる }); // 下記のルーティング情報には URL"/admin/test"でアクセスできる Route::get('test', 'TestController@index'); });名前付きルート
- ルーティング情報に名前がついているものである。
下記の様なルーティング情報が記載されている物とする。
web.phpRoute::get('user/index', 'UserController@index'); Route::post('user/index', 'UserController@save');先に記載したルーティング情報のget側に「index」、post側に「input」、ルートパラメータを含むものに「user_detaile」という名前をつける際は下記の様に記載する。(つける名前は一意にすること)
web.phpRoute::get('user/index', 'UserController@index')->('index'); Route::post('user/index', 'UserController@save')->('input'); Route::get('user/detail/{user_id}', 'UserController@detail')->('user_detail')先に記載したルート情報のget側にリダイレクトしたい場合はroute関数を用いてリダイレクトさせることが可能になる。例を下記に記載する。
//どこかのコントローラのアクション内などで下記を記載する。 return redirect()->route('index');先に記載したルート情報のpost側にデータを送りたい場合はroute関数を用いてデータを送ることが可能になる。例を下記に記載する。
//ビューファイルなどで下記を記載する。 <form action="{{ route('input') }}" method="POST"> <input type="submit"> </form>先に記載したルート情報のルートパラメータを含むものにリダイレクトしたい場合はroute関数に引数を用いることでリダイレクトさせることが可能になる。下記に例を記載する。
//どこかのコントローラのアクション内などで下記を記載する。"user/detail/1"にリダイレクトさせたい時 return redirect()->route('user_detail', ['user_id' => 1]);ルートアズ(筆者が勝手に付けた、本当は違う名前かもしれない、すいません)
- 名前付きルートの「名前」の最初の部分にグループ化されたルート情報に共通した文字列を付与する。
- 下記に記載例を載せる。
web.php//グループ化で 名前の最初にtestと付けたいルーティング情報を包む Route::as('test.')->group(function () { //名前の最初にtestとつけるルーティング情報を記載する Route::get('users', function () { // // 下記のルーティング情報にリダイレクトする際はreturn redirect()->route('test.users_1')とする })->name(users_1); Route::get('home', function () { // 下記のルーティング情報にリダイレクトする際はreturn redirect()->route('test.home_1')とする })->name(home_1); // 下記のルーティング情報にリダイレクトする際はreturn redirect()->route('test.test_1')とする Route::get('test', 'TestController@index')->name(test_1); }); ``` # # クロージャ - 無名関数のことである。 - 関数名を指定せず作成した関数のことである。 - 名も無き関数
- 投稿日:2020-05-17T00:07:48+09:00
LaravelでTenancyを使用し、DBをユーザーごとに動的に切り替える方法
Laravelの利点にDBの扱いやすさがありますよね、これまでDB周りで詰まったことはほとんどありませんでしたが、DBを動的に変更する機能で詰まったので、備忘録として残しておきます。
使用環境
・MAC
・Laravel7.5
・Tenancy ←本記事の主役作りたかったもの
Laravelで※シングルサインオン(SSO)機能のAPI認証基盤の構築。
DBはユーザーが新規で登録されるごとに新規で構築され、ログイン中のユーザーごとに切り替える。
※Single Sign Onの略。1つのIDとパスワードを入力して、複数のWebサービスやアプリケーションにログインする仕組み。詰まった箇所
・ユーザーが新規登録される毎にDBをプログラム内で(自動で)構築する
・DBが構築される毎に構築されたDBにテーブルを作成する(マイグレーションを実行する)
・ログイン中のユーザーごとにDBを切り替える詰まった原因
LaravelでDBを扱うにはconfig/database.phpにDB情報を、前もって記入しておく必要があります。
(PDOでDBに直接接続するなど別方法もありますが、ここでは割愛させてください。)
しかし、今回作りたかった機能としてDBを動的に切り替える必要があるのですが、config/database.phpに前もって記入することができなかったからです。解決策
・Tenancyを使用し、マルチテナント環境を構築する。
https://reffect.co.jp/laravel/laravel-multi-tenant-stancl-tenancy
Tenancyの使用方法については?に記載されています。?のコードでテナント(ユーザーごとの環境)・テナントごとのDBとテーブルの構築までします。
//ユーザー登録機能内にテナント作成機能を追加(一部抜粋) //リクエストされたユーザー名 $user_name = $request['user_name']; //メインドメイン $baseURL = 'qiita.com'; //ユーザー名でテナントを作成 $tenant = Tenant::new()->withDomains($user_name . '.' . $baseURL)->save(); //migrate実行(実行したいマイグレーションファイルは/database/migrations/tenantに格納しておく) $exit = \Artisan::call('tenants:migrate', ['--force' => true,]);これで以後は、「リクエストされたユーザー名.メインドメイン」のURLにアクセスすると、
そのユーザー用のページにアクセスすることができ、ユーザーに対応したDBに自動で切り替えられます。
(ここら辺の動きを詳しく知りたい方は?をどうぞ)
https://tenancy.dev/実際にはこんな感じでテナント用ページにアクセスし、API認証機能を実装しました。
$tenant_name = 'foo.'; $baseURL = $tenant_name . 'qiita.com/'; $client = new \GuzzleHttp\Client(['base_uri' => 'http://'. $baseURL]); $response = $client->request( 'POST', 'changeProfile', [ 'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$api_token ], 'form_params' => [ 'profile' => $profile, 'email' => $email, ], ] );