かしいのはてな

技術ブログ備忘録用

QueryBuilder::paginate() と Eloquent::paginate() の挙動の違いがあった

 

Laravel ver: 5.3.26

 

SQL的にcount() で取得するときには、主にそのテーブルの主キーをあてるほうがより速く実行することが出来ます。

 

今回、QueryBuilder::paginate() と Eloquent::paginate() の挙動の違いがあったためメモします。

データを取得するとき、第二引数に$column (default =['*']) を指定することが出来ます。

 

今回、DBオブジェクトが持ってるQueryBuilder::paginate()の場合だと、

/**
* Paginate the given query into a simple paginator.
*
* @param int $perPage
* @param array $columns
* @param string $pageName
* @param int|null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function paginate($perPage = 15, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);

$total = $this->getCountForPagination($columns);

$results = $total ? $this->forPage($page, $perPage)->get($columns) : collect();

return new LengthAwarePaginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}

 

 

    $total = $this->getCountForPagination($columns);
}

 

で、countを取得しています。

 

一方、Modelオブジェクトが持っているEloquent::paginate()だと、

 

/**
* Paginate the given query.
*
* @param int $perPage
* @param array $columns
* @param string $pageName
* @param int|null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*
* @throws \InvalidArgumentException
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);

$perPage = $perPage ?: $this->model->getPerPage();

$query = $this->toBase();

$total = $query->getCountForPagination();

$results = $total
? $this->forPage($page, $perPage)->get($columns)
: $this->model->newCollection();

return new LengthAwarePaginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}

 

    $total = $query->getCountForPagination();

 

と、$column名が引数に渡ってないため、呼ぶ側が明示してもcount(*) と実行されるみたいです。

 

以上、使ってみて気づいたことでした。

 

本体に報告してみたいのですがやり方はまた調べて、fixしてもらえるようにしたいと思います。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

baserCMSを使ってサイト公開した話

baserCMS Advent Calendar 2016 - Adventar 3日目を担当させていただきました。よろしくお願いします。

http:// http://www.adventar.org/calendars/1703

 

 

昼食にいつも使っている定食屋さんがあって、

日頃良くしていただいているので、サイトを作りましょうと話が上がったため

今年のお盆前にbaserCMSを使って公開しました。

kitchen-yumeya.com

 

baserCMSは当時(baserCMS 3.0.10)でのインストールでした。

パッケージは公式サイトからダウンロードします。

 

インストールは、以下のような作業を行いました。

  1. zipファイルを右クリックでダウンロード
  2. ダウンロードしたzipファイルを解凍
  3. 解凍したフォルダをサーバにアップロード
  4. インストールページを表示
  5. インストールページのガイダンスに従って、フォルダのパーミッション修正
  6. データベースの指定(今回、PostgreSQLにしました。)
  7. サイト上で使うテーマ選択
  8. インストール完了

 

インストール完了すると、指定したテーマが公開されます。

 

しかし、今回別のテーマにしたかったため、探してみたところ、「baserマーケット」というのがありました。

market.basercms.net

 

baserCMSでカスタマイズを行うのに便利なプラグインやテーマを販売しているサイトのようです。

プラグイン、テーマを購入するのには会員登録が必要なため、baserCMSインストール作業で使用したメールアドレスを使って会員登録しました。

 

会員登録後、早速テーマを探してみました。

用途別に様々なテーマを選択できるみたいです。

f:id:kashii1207:20161203100820p:plain

 

今回「飲食店」なので、こちらのテーマを使用させていただきました。

f:id:kashii1207:20161203101036p:plain

baserCMSで公開されてあるテーマはどれもクオリティが高くテーマごとにどうゆうところを意識して作ったかなどの「商品説明」が記載がしっかりされているため、選ぶ側としても納得して選ぶことができます。

しかも、無料配布されているものも数多くあるためbaserCMSを使用しているユーザにとってはとてもありがたいです。

 

テーマを決めたので、「カートに入れる」を押して購入手続きを進めます。

 

購入手続きの流れは以下の通りでした。

  1. 現在のカゴの中(カートの中身を確認)
  2. 支払い方法・お問い合わせ入力
  3. 入力内容確認
  4. 注文完了

簡単ですね。

「baserマーケット」はダウンロードコンテンツを販売するサイトなのでお届け先の入力は必要ありません。

 

購入完了後、早速適応してみました。

f:id:kashii1207:20161203102831p:plain

 

TOPのメインビジュアルは、管理画面から差し替える事が可能ですので、

お店の看板メニューがどどんと出るように差し替えました。

f:id:kashii1207:20161203103340p:plain

 

デフォルトで使われている画像や文言を差し替えたいときには、「固定ページ管理」で編集することが出来るみたいです。ここでは、各ページで使われている画像の差し替えなどを行いました。

 

余談ですが、固定ページでは管理しない部分は、テーマ一覧から編集することも可能です。

f:id:kashii1207:20161203103811p:plain

 

「レイアウトテンプレート 一覧」ページが表示されますが、主に以下のような用途ごとにメニューがわけられているようです。どうやら、Webサイトの構成に従って共通化している部分をまとめて管理しているみたいですね。

  1. レイアウト一覧(layout)
  2. エレメント一覧(Elements)
  3. Eメール一覧(Email)
  4. コンテンツ一覧(content)
  5. css一覧(css
  6. イメージ一覧(img)
  7. Javascript一覧(js)

※作業する際には、元に戻せなくなって動かなくなったとか怖いんで編集前に「複製」してバックアップしておくことをおすすめします。

 

 

サイトを公開したら、解析タグを入れたりするのに、GoogleAnalyticsなどで設定しておくといいですね。

www.google.com

 

できあがったGoogleAnalyticsのタグには、「UA-」から始まる文字列が作成されますので、baserCMSの管理画面の「システム管理」から設定してください。

 

 あとは、Googleエゴサーチしたときに紹介できるように設定しておくのもいいですね。

地図上に住所が表示されたりしますが、そこに「営業時間」「Webサイト」などの情報を入れたりすると、今日のランチどうしようかなって思う人に対して集客もできるので設定しておくのも効果はあると思います。

f:id:kashii1207:20161203114423p:plain

 

今回、お店の人に内緒でサプライズでやってみましたが、お店の人から「Google」から検索で☆がついてたからお客様が来たとか、中には地方アイドルがレポートさせてくださいとご来店があったとか嬉しい報告をたくさんしていただけましたし、なによりサイト作って大変喜ばれたのがうれしかったですね。

 

CMSでサイト構築をご検討の方は参考にしていただけるとありがたいですね。

以上です。

「第25回シェル芸勉強会 福岡サテライト」レポート

概要

シェル(主にbash)の理解と使い方を深める勉強会です。

東京を中心に福岡・大阪の2箇所のサテライト会場からはTwitterYoutubeを使ってリモート参加するという内容でした。

会場

みんなで同じ問題を解きます。(てか、ほとんど難しくてとけませんでした笑)

問題

みなさんのコメントおもしろくて笑いましたし、回答は秀悦すごい勉強になりました。

ツイッターまとめ

ライブストリームも見れるようなので、共有しておきました。

Youtube

 

福岡サテライト会場

各会場で、午前と午後で内容がわかれており、本件は午後の部となっております。

福岡サテライト会場では午後の開始の前に、午前の部は、ぱぴろん (@papiron) | Twitter さんからapacheのログファイルを通して、`awk`,`grep`,`sort`,`cut`,`uniq`などの使い方を始め、bashそのもののことを説明していただきました。

実はSoftware Design2016年12月号

の執筆に関わっている方で、期限がのこりわずかでお忙しいところ、午後の部が終了後もいろいろと説明していただきました。大変ありがとうございました!

 

そんなぱぴろん (@papiron) | Twitter さんのSlideがこちら

 

speakerdeck.com

今回のネタであるapacheのログデータは、この会主催の上田さんのブログで公開されているデータを使用させていただきました。

午後は、問題

 

非常に有意義な情報ばかりでしたので、かいつまんで以下ポイントを自分なりにまとめました。

ポイント

  • apacheのログは、ダブルクォーテーションをdelimiterに指定してあげるといい感じ
  • バッシュの開始と終了のプロセスが一番負荷がかかるので、なるべくまとめられうように工夫する
  • 並列処理すると、実際たたいておわるまでの時間がOS部分のAPIに対してのとプログラム自身が頑張った時間+OS部分に対して掛かって時間よりも早くおわる
  • 標準コマンドよりも、GNU系のコマンドのほうが処理速度がぜんぜん違う
  • 並列処理(マルチコア)してくれる、コマンドは最初に単機能コマンド実行するのがコツですので、でかいデータを扱う人は、注意しておく
  • `head *` でカレントディレクトリのファイルすべての先頭から10行表示してくれる
  • `cut -c` 文字数を指定(2文字目から12文字目)できる `cut -c2-12`
  • `cut -f`` フィールド列指定ができる (default delimiter = \t ごと) cut -f
  • 高速化のコツとして、一つ一つの処理をあえて分けるとコア数分だけ頑張ってくれる
  • エラー出力されるものは、historyに残らないので、明示的にexitでlogoutする
  • カーソルの移動とか、一個前の実行コマンドを↑とかで表示できるのは、Cursesがあるおかげ
  • Unixとして、標準入力(/dev/stdin)とか、標準出力(/dev/stdout)とか、エラー出力(/dev/stderr)をファイル単位で保存するのが考え方の基本
  • `awk`には、sleepがない AWK リファレンス | UNIX & Linux コマンド・シェルスクリプト リファレンス
  • `man ascii` で普段なれない文字コードのすべてがかかれてある。16進数の改行は0a
  • コマンドもbashから見ればテキストである
  • `tee` 流れ込んだファイルを一時的に保存を残しつつ、後ろの実行もできる make をしてる途中のファイルを残したいとき
  • echo コマンドは、改行コードをしらべたいときは、-n コマンドにする
  • 最新版のawkは、区切り文字 -Fに区切り文字が使われている gawkコマンド
  • sed Stream editor vi とコマンドは似て、そのふたつはedが祖。editorだけど、見えてないもの。 line editor
  • `tr -dc '1-9.'` で数字とドットだけ残したい
  • ping -c 回数分だけ飛ばす
  • grep -A1 特定の文字の次を飛ばす
  • sed -n 出したい範囲を正規表現で区切って出すことも出来る
  • grep -w A ワードとみなされる
  • yes ずっとy をつけさせる
  • tee 流れ込んだファイルを一時的に保存を残しつつ、後ろの実行もできる make をしてる途中のファイルを残したいとき
  • grep は行全体、awk は列を定義することはできる
  • grep で正確なものをしたいばあいは、正規表現を使う(grep コマンドそもそもが正規表現を使うッて意味)
  • 単機能は、処理は速い
  • 最終兵器は、最終段階のときにする
  • Linux の上に乗っているのは、もともとGNU系でC言語で書かれている
  • 最新のgrep コマンドは、数億行のデータを数秒でさばける
  • パフォーマンスチェック time コマンドを先頭つける
    • real 実際たたいておわるまで
    • user OS部分のAPIに対してのとプログラム自身が頑張った時間
    • sys OS部分に対して掛かって時間
  • xargs は、横表示 grep -o で縦表示
  • xargs だけだと、暗黙的に echo コマンドが実行される コマンドが指定されていればそのコマンドが実行される
  • 標準出力されたコマンドをパイプで繋いで、次に渡すときにどのコマンドすべてではないが、 - にわたすことができる
  • sed 's/置換元/置換先/g' 
    • s 置換
    • gをつけると、複数回実行してくれる
    • 置換先に& をつけると置換基の文字列がそのまま入る (←これはすごい勉強になった!)
    • 置換元に正規表現が使える、() でグループ化され、( と ) にはそれぞれ文字として意味があるので\ でエスケープする
    • 置換基に正規表現が使える、^ で先頭。$で文末。と言う意味となる
    • fold -w 2 で2文字ずつ文字列を分解する(sedの場合だったら、sed 's/../& /g')
  • gdate -d '2016-10-29 00:00:00' '+%s' s がUnixタイム -d で指定することができる省略時は実行した日
  • $() で実行した結果を標準出力してくれる `$(echo '60 * 60 * 24'|bc)` ->  86400

 

 

福岡サテライト会場では、イベント終了後も、ぱぴろん (@papiron) | Twitter さんの解説いただきました。ありがとうございました。

※私のマシンがmacGNU系を想定してます。

問1

ドメインからグローバルIPを引き出す問題でした。

nslookup コマンドを使ったやり方は、コマンド自体が非推奨とのことでしたので、dig コマンド ping コマンドを使ったやり方で。

$ dig www.usptomo.com | grep -A1 ';; ANSWER SECTION:' | grep -v ';; ANSWER SECTION:' | awk '{print $NF}'
157.7.203.188 

 grep -A で見つけた文字列の次after という意味で、数字を指定するとその数値分出してくれる。ただ、見つけた行を操作したいわけではないので、grep -v で無視した。awk のNFは列数なので、文末を表示したいときは、$NF でOK $0は1行全部 $1で1列目 ... とつづくようです。

 

$ ping -c 1 www.usptomo.com | head -n 1 | awk '{print $3}' | tr -dc '0-9.'

awk コマンド内に登場している$3ですが、3列目だけを出力している状態で、tr -dc で特定の文字だけつまり"数字とドットだけ残す"というやり方。

 

問2

 

2,3日前にネットを賑わせているあれからの問題。ネット芸人の力は計り知れない。メディアに影響を及ぼすこともあるんだなぁ。笑

togetter.com

ひらけ!ポンキッキ”という文字列を

ひらけ!ポンキッキ
らけ!ポンキッキひ
け!ポンキッキひら
!ポンキッキひらけ
ポンキッキひらけ!
ンキッキひらけ!ポ
キッキひらけ!ポン
ッキひらけ!ポンキ
キひらけ!ポンキッ

 

という風に表示したいとのこと。

結果からいうと

$ yes ひらけ!ポンキッキ | head -n 9 | awk '{for(i=1;i<NR;i++){printf "#"}printf $0$0;print ""}' | gtac |  cut -c 9-17

 というやり方で完了しました。

yesコマンドは、対話式コマンドといわれるもので、指定の文字列を入力するとそれをずっとだしてくれるものです。これを利用して、headコマンドで行数指定つまり、回数を9回指定する。awkコマンドでその行数分ループするわけですが上記からだとわからなかったので、内部のことを詳しく説明してくれました。

 

$ yes ひらけ!ポンキッキ | head -n 9 | awk '{for(i=1;i<NR;i++){printf "#"}printf $0$0;print ""}'
ひらけ!ポンキッキひらけ!ポンキッキ
#ひらけ!ポンキッキひらけ!ポンキッキ
##ひらけ!ポンキッキひらけ!ポンキッキ
###ひらけ!ポンキッキひらけ!ポンキッキ
####ひらけ!ポンキッキひらけ!ポンキッキ
#####ひらけ!ポンキッキひらけ!ポンキッキ
######ひらけ!ポンキッキひらけ!ポンキッキ
#######ひらけ!ポンキッキひらけ!ポンキッキ
########ひらけ!ポンキッキひらけ!ポンキッキ 

 一旦、# つきでひらけポンキッキを2回出して、

 

$ yes ひらけ!ポンキッキ | head -n 9 | awk '{for(i=1;i<NR;i++){printf "#"}printf $0$0;print ""}' | gtac
########ひらけ!ポンキッキひらけ!ポンキッキ
#######ひらけ!ポンキッキひらけ!ポンキッキ
######ひらけ!ポンキッキひらけ!ポンキッキ
#####ひらけ!ポンキッキひらけ!ポンキッキ
####ひらけ!ポンキッキひらけ!ポンキッキ
###ひらけ!ポンキッキひらけ!ポンキッキ
##ひらけ!ポンキッキひらけ!ポンキッキ
#ひらけ!ポンキッキひらけ!ポンキッキ
ひらけ!ポンキッキひらけ!ポンキッキ 

tac コマンドでひっくり返して、cut -c 9-17 で、ひらけ!ポンキッキ の次のひらけ!ポンキッキ を取り出すというやり方。GNU版cutコマンドはマルチバイト非対応だったそうなので、文字列の取り出し方は、awkをつかったやりかたで

###Linux用解答###
$ yes ひらけ!ポンキッキ | head -n 9 | awk '{for(i=1;i&lt;NR;i++){printf "#"}printf $0$0;print ""}' | tac | awk '{print substr($1,9,9)}'

 

問3

redirectのありがたみがよく言われる問題でした。通常ファイルに > で追記。 >> で上書きできるんですが、そのようなredirect機能をrbashすると奪われてしまう。保管も聞かなくて、不便な思いをしました。失って気がつくことってこうゆうことなんだなぁと感じました。

 

回答ですが、

eban (@eban) | Twitter さんの回答がすごくて何通りも文字列をファイル出力方法があるだなんて知らなかったです。ww

実は、rubyの開発やnkf コマンドの開発に携わってるすごい人らしいです。シェル芸界には、たくさんそうゆう人がいるんだろうなぁ。。

 

この問題を通して、Unixとして、標準出力とか、エラー出力をファイル単位で保存する考え方を知ることができました。

 

問4

 

以下のひらがなからワンライナーを始めて、濁点がつく字だけに濁点をつけてみてください。

$ echo すけふぇにんけん

という問題ですが、これめちゃくちゃ難しくてわけわかりませんでしたww

nkf コマンドには、様々な文字コードに変換できるということだけわかりました!笑笑

 

やり方としては、nkfをとおしてかたかなにして、半角カタカナにして、濁点の文字コードをつけて、ひらがなに戻して表示!みたいな。やばかったですww

 

問5

 プログレスバーのようなあの動きをコマンドラインで表現してくださいって問題でした。

 

yes | head | awk '{for(i=1;i<=NR;i++){printf "*"}print ""}' | sed "s/^/printf '/" | sed "s/$/\\\\r'; sleep 1/" | sh

これもわかりやすく解説していただいて、シェルに以下のように標準出力をコマンドに渡すということで、これも覚えておいて役に立ちそうなやり方でした。

$ yes | head | awk '{for(i=1;i<=NR;i++){printf "*"}print ""}' | sed "s/^/printf '/" | sed "s/$/\\\\r'; sleep 1/"
printf '*\r'; sleep 1
printf '**\r'; sleep 1
printf '***\r'; sleep 1
printf '****\r'; sleep 1
printf '*****\r'; sleep 1
printf '******\r'; sleep 1
printf '*******\r'; sleep 1
printf '********\r'; sleep 1
printf '*********\r'; sleep 1
printf '**********\r'; sleep 1

”改行せずに”先頭に戻り出力するというやり方。

問6

 

文字を解読すると言う問題でした。

慣れが必要みたいで、0a のところで、16進数の改行と気づくとその後のアプローチができるみたいです。

file コマンドに、どうやら様々なファイル形式を文頭を見て判別してるらしい。

The magic tests are used to check for files with data in particular fixed formats. The canonical example of this is a
binary executable (compiled program) a.out file, whose format is defined in <elf.h>, <a.out.h> and possibly <exec.h> in
the standard include directory. These files have a ``magic number'' stored in a particular place near the beginning of
the file that tells the UNIX operating system that the file is a binary executable, and which of several types thereof.
The concept of a ``magic'' has been applied by extension to data files. Any file with some invariant identifier at a
small fixed offset into the file can usually be described in this way. The information identifying these files is read
from the compiled magic file /usr/share/file/magic.mgc, or the files in the directory /usr/share/file/magic if the com-
piled file does not exist.

 

 

問7

本日(2016年10月29日)の範囲の毎秒のUNIX時刻で素数となるものを全て列挙してください。出力はUNIX時刻でなく、何時何分何秒か分かるようにしましょう。世界標準時で考えてください。という問題。

 

標準出力した結果をどうやって渡すか考えてました。

seq 0 86399 | xargs -I@ gdate -d '2016-10-29 00:00:00 @ sec' '+%s'

最終的に、こうなりました。 コマンドの実行回数を減らすことが高速化のコツとのことで。

seq 0 86399 | sed -e "s/^/2016-10-29 00:00:00 /" -e "s/$/ sec/" | gdate -f - '+%s' | gfactor | awk 'NF==2{print $2}'

 

問8

時間の都合上省略、幾何学的な問題でした

 

 

まとめ

場所をていきょうしていただいたベータソフトさんにも感謝ですし、解説をしていただいた福岡のぱぴろん (@papiron) | Twitter さんありがとうございました!オンラインで同じ時間を共有できてとても楽しい時間だったと思います。また次回も参加したいと思います。

 

あるディレクトリ以下のファイル内の文字列置換

大量のデータの中にある、特定の文字列を置換するときに、

今までは「mi」エディタで一括置換したり、

Windowsサクラエディタで置換処理をしていたのですが

 

今回は、コマンドラインからの実行方法を紹介します。

 

find . -name 'sample-2015-07-10.dump' | xargs sed -i "" 's/対象文字/置換後文字/g' 

 

 

YosemiteでHosterが使えなくなった時のメモ

$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.10.4
BuildVersion: 14E46

 

ローカルマシンの名前解決でつかってる「Hoster」が、Yosemiteだと使えなかったので、使えるように修正したときのメモです。

 

まず、ブラウザからパッケージのDL

RedWinder::MacApp::Hoster

 

zipを解答してできたパッケージを、右クリックで「パッケージ内容を表示」

 

Contents/distribution.dist の以下の箇所を修正する

-  if(!(my.target.systemVersion.ProductVersion >= '10.4')) {
+  if((my.target.systemVersion.ProductVersion+'').match(/10.[1-3]\./)) {

 

これでパッケージを起動することができ、アプリをインストールすることができます。

 

 

なお、今まで使ってたHosterの設定がきえた!!!

ような現象に自分はなったので、確認したところ

$ ls -al /etc/ | grep 'hosts*'
-rw-rw-r-- 1 root admin 2734 7 6 11:54 hosts
-rw-r--r-- 1 root wheel 0 9 10 2014 hosts.equiv
-rw-r--r-- 1 root wheel 2733 7 3 15:32 hosts.hosterback

 

 

「hosts.hosterback」という形でリネームされていたので、

ファイルを移してあげればOKです。

(参考URL)

blog.tottokug.com