Laravelのエラーログに情報を追加する方法

ログの拡張

開発中であればエラーはそのまま表示されるので解決は比較的容易ですが、運用中に発生した場合はエラーログから調査するので少し時間がかかります。

エラーログにはデフォルトで発生時ログインしているuserIdが一緒に出力されエラーが発生したファイル名や行番号も出力されるので基本的にはそちらからエラーの調査は行えますが、特定のレコード時だけ発生したなどになるとそれだけでは時間がかかる時があります。

なので出力されるログの内容を拡張できないかフレームワークのソースを調べたところ

Illuminate/Foundation/Exceptions/Handler.php
にcontextと目的の関数があり

contextの関数をオーバーライドすればいい様子

以下実装例

app/Exceptions/Handler.php
/**
 * ログに記載する追加情報
 */
protected function context()
{
$context = parent::context(); try { return array_merge($context, [ // 一緒に記録したい情報 'uri' => env('REQUEST_URI'), ]); } catch (Throwable $e) { return $context; } }

以上!

SolrのUAX29URLEmailTokenizerを使う

Solrにはさまざまなトークナイザーが用意されており、その中に UAX29URLEmailTokenizer があります。
このトークナイザーは基本的には StandardTokenizer と同じ挙動なのですが、以下の要素をトークンとして切り出してくれるという特徴があります。

  • ドメイン名
  • URL(http(s)://, file://, ftp://)
  • Eメールアドレス
  • IPアドレス(IPv4とIPv6)

UAX29URLEmailTokenizer を使うフィールドタイプとフィールドを定義して動作を確認してみます。

<fieldType name="text_url" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="solr.UAX29URLEmailTokenizerFactory"/>
  </analyzer>
</fieldType>                                                                                                            
<field name="url_test" type="text_url" stored="true"/>

この設定で「http://www.example.com/example/です。」をトークナイズした結果は以下の通りです。

日本語の文書を扱う場合、通常の文章の部分が StandardTokenizer 相当でトークナイズされるといろいろ使い勝手が悪いので、たとえば形態素解析のトークナイザーと組み合わせることを考えます。

<fieldType name="url" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.UAX29URLEmailTokenizerFactory"/>
    <filter class="solr.TypeTokenFilterFactory" types="url_whitelist.txt" useWhitelist="true"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.KeywordTokenizerFactory"/>
  </analyzer>
</fieldType>

<field name="body" type="text_ja" stored="true"/>
<field name="url" type="url" stored="true"/>
<copyField source="body" dest="url"/>

UAX29URLEmailTokenizer の後ろに TypeTokenFilter を追加することで、必要なトークンタイプだけを残すことができます。TypeTokenFilter のホワイトリストとして url_whitelist.txt に以下の1行だけを記述して、URLだけを残すようにします。

<URL>

クエリ用のアナライザを別に定義したのは、URLのフィールドの検索では余計なトークナイズをさせずに文字列マッチ相当の動作にしたいからです。
urlフィールドをurlフィールドタイプとして定義し、text_jaフィールドタイプであるbodyフィールドのコピーフィールドにしています。

以下の文書を投入します。

[
    {"id":"1",
     "body":"昨日 http://blog.splout.co.jp/ をみた。"
    },
    {"id":"2",
     "body":"明後日は http://splout.co.jp/ をみる。"
    }
]

各フィールドにどういうトークンが納められたのかを確認します。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/terms?terms.fl=url&terms.limit=-1&omitHeader=true&wt=json'
{
  "terms":{
    "url":[
      "http://blog.splout.co.jp/",1,
      "http://splout.co.jp/",1]}}

urlフィールドにはURLだけが納められています。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/terms?terms.fl=body&terms.limit=-1&omitHeader=true&wt=json'
{
  "terms":{
    "body":[
      "co",2,
      "http",2,
      "jp",2,
      "splout",2,
      "みる",2,
      "blog",1,
      "明後日",1,
      "昨日",1]}}

bodyフィールドには通常の形態素解析結果が納められています。

この状態で検索してみます。まずは body フィールドを “http://splout.co.jp/” で。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=body%3Ahttp%5C%3A%5C%2F%5C%2Fsplout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"body:http\\:\\/\\/splout.co.jp\\/"}},
  "response":{"numFound":2,"start":0,"docs":[
      {
        "id":"2",
        "body":"明後日は http://splout.co.jp/ をみる。",
        "url":"明後日は http://splout.co.jp/ をみる。",
        "_version_":1656715432355168256},
      {
        "id":"1",
        "body":"昨日 http://blog.splout.co.jp/ をみた。",
        "url":"昨日 http://blog.splout.co.jp/ をみた。",
        "_version_":1656715432353071104}]
  }}

“http”, “splout”, “co”, “jp” がバラバラにトークンとして扱われるので、”http://blog.splout.co.jp/” も “http://splout.co.jp/” も両方がヒットしています。
次に url フィールドを同じく “http://splout.co.jp/” で。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=url%3Ahttp%5C%3A%5C%2F%5C%2Fsplout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"url:http\\:\\/\\/splout.co.jp\\/"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"2",
        "body":"明後日は http://splout.co.jp/ をみる。",
        "url":"明後日は http://splout.co.jp/ をみる。",
        "_version_":1656715432355168256}]
  }}

“http://splout.co.jp/” の方だけがヒットします。

urlフィールドの検索ではワイルドカードを使うこともできます。”http://*.splout.co.jp/” を指定して splout.co.jp のサブドメインだけを検索してみます。

$ curl -s 'http://localhost:8983/solr/urlTokenizer/select?q=url%3Ahttp%5C%3A%5C%2F%5C%2F*.splout.co.jp%5C%2F'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":1,
    "params":{
      "q":"url:http\\:\\/\\/*.splout.co.jp\\/"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"1",
        "body":"昨日 http://blog.splout.co.jp/ をみた。",
        "url":"昨日 http://blog.splout.co.jp/ をみた。",
        "_version_":1656715432353071104}]
  }}

文章に含まれるURLやメールアドレスの扱いは案外面倒なものです。
UAX29URLEmailTokenizer をうまく使えば、自前でURLやメールアドレスを抽出してstringフィールドに格納するよりもバグも少なく取り扱うことができるでしょう。

肥後橋グルメ探訪 Vol.1

こんにちは。LQヒロシです。

弊社オフィスのある肥後橋周辺は靭公園を中心においしいお店が沢山あります。これまで弊社ブログでそういう趣向の記事がなかったな、良いお店があるのに紹介しないってもったいないなと思い立ち、今回はグルメ記事を書こうと至った運びであります。(ネタに困ったわけではありません)

KiBar+CAFE (ケーアイバープラスカフェ) 

江戸堀のセブンイレブンを南に少し下ったところにあって、お店はビルの2Fで営業されています。オレンジの看板が目印です。夜はバーお昼はカフェとしてランチ営業してるみたいですね。

おすすめの座席は窓に面した8席のカウンター。眺めも上々でゆったりした気持ちでランチがいただけます。


気になるランチメニューはこちら
・プレートランチ
・カレーランチ
・スープランチ

個人的にこちらのカレーが好みでして早速注文してみたいと思います。

やってきました ^p^

カレーはキーマカレーですね。オクラにレンコン、パプリカの彩りがとても綺麗。そしてカレーのルーにとてもマッチ!!

ご飯も通常のお米と五穀米と選べるのもポイント高し!!

辛すぎずヘルシーで和風カレーの面持ちも感じるひとしな。

一緒に行った同僚はスープランチをセレクト。

スープも野菜たっぷりでぬくもりのある優しい味
パンが食べたい時はこちらがいいですねぇ〜 ^p^

KiBar+CAFE ではランチだけでなくカフェもやっているので、おやつ時に甘みとコーヒーを楽しみに行ってみたいですね。

それでは

ごちそうさまでした!


親知らずさようなら

こんにちわ。
リエです。

つい先日親知らずを抜いてきました。
下の親知らずは数年前に両方抜いたので今回は上の親知らずです。
右が生えてきて痛かったので抜いたのですが、抜歯後は腫れも痛みもマシでした。でも痛み止めは必須です。(飲まないと寝れなかった)

下は完全埋没歯で抜歯後はめちゃくちゃ腫れて、痛みも痛み止め効かないくらい痛かったのであの時に比べると我慢できるというレベルです。

私は全然虫歯がなくて、レジン法で治療した歯が2本だけというのが唯一の自慢だったりします。もちろん歯周病にもなっていません。
甘い物は大好きですが、虫歯リスクが上がるからダラダラ食いは絶対しないですし飴も基本的には食べません。(のど飴はノンシュガーのものを選ぶ)
という感じで日々予防に努めております。このまま健康な歯を維持して目指せ8020!

という感じで日々の予防プラス定期的なクリーニングと健診はめっちゃ大事なので、行ってない方はぜひ行くことをおすすめします。なんか歯医者さんの回し者みたいになった。

〜余談〜
この前下の奥歯が痛くなって焦って歯医者さんへ行ったのですが、硬いものの食べ過ぎが原因と言われました/(^o^)\思い返してみると前日ナッツをめっちゃ食べてたわ。

PHP Laravel bladeとvuejsと。

いよいよ花粉症の季節がやってきますね。
> 花粉さん、今年は注射治療しますがお手柔らかにお願いしますね。
マエダです。

さてこのタイトルなんなのかとご説明させていただきますと、みんな大好きLaravelのBladeテンプレートにControllerから渡された変数を利用して、vuejsの変数名を生成して、vuejsの変数を表示したい!

僕の日本語がヘンくてわかりませんね。(変)

Bladeテンプレートの変数の表示

こちら利用したことある方はおなじみの記述方法ですね。

<span>
{{ $name }}
</span>

Vue.jsの変数の表示(Blade内)

Laravel利用者はおなじみだと思いますが、BladeとVue.jsの波括弧とで構文エラーとなるのを先頭に「@」を付けることで回避する記述方法を利用します。

<span>
@{{ name }}
</span>

Vue.jsの変数をPHP変数で変更して表示

上記を踏まえまして、これってどうかなーってBladeテンプレートに書くと・・・

<span>
@{{ users.{{ $user_id }}.name }}
</span>

「[Vue warn]: Error compiling template」

波括弧の閉じるがどっちやねん!って怒られてしまいますね。。。

そこでの回避方法として、

<span>
@php echo("{{ users.{$user_id}.name }}") @endphp
</span>

急に波括弧を使わない!という選択。( ー`дー´)キリッ

そもそもそんなPHPとJavaScriptどっちつかずの設計にするなよとかのツッコミは受け付けません。
こうやったらどうですか?という優しいツッコミだけお願いします。

以上、vuejsに触れてみようのコーナーでした。

\\優しくツッコミをいれてくれる仲間を募集中です!!//
vuejsビギナーの僕がよくわからない利用方法を実験しているときに優しくツッコミいれてくれるそこのあなた。
以下ページよりご応募お待ちしております。
https://splout.co.jp/recruit/