2014-10-01

Laravel の独自パッケージを作成する手順

ここのところ多忙のためブログ投稿をサボってしまっていますが、Laravel(CakePHP)は常に触っていて、知れば知るほどその便利さがよくわかっきている今日このごろです。

さて、そんな多忙な中なのになぜブログ投稿をするのか?というと今はクライアント様の判断待ちで、さらにタイトルにある独自パッケージの作成方法を備忘録として残しておきたかったからです。

以前作成したこがあるのにやることが多くて忘れてしまっていました(汗)
ということで今回はLaravelの独自パッケージの作成法をまとめてみたいと思います。


[最終結論] Laravel 5.0ではもっと楽にできればいいなー^^


では、早速作業を開始しましょう。
前提としまして、パッケージの名前は、

sukohi/hoge

として話をすすめていきます。
これは、「ベンダー名(あなたの名前)/パッケージ名」になります。

では、ターミナルを開いて Laravelがインストールされている場所(artisanのあるフォルダ)まで移動して以下を実行してください。

php artisan workbench sukohi/hoge --resources


実行が完了すると、

laravel
├ app
├ bootstrap
├ public
├ vendor
└ workbench

という形で workbench フォルダが作成されています。
では、この中にある以下のフォルダを開きましょう。

laravel/workbench/sukohi/hoge/src/Sukohi/Hoge/

このフォルダで独自クラスの作成&「HogeServiceProvider.php」の設定をします。

では、独自クラスを作成しましょう。このサンプルでは「Hoge.php」です。
フォルダ構成は以下のようになります。


Sukohi
 └ Hoge
   ├ Hoge.php
   └ HogeServiceProvider.php


そして、このHoge.php 内にご自身でやりたいことができるようプログラムを作成しましょう。
書き方は通常のPHPクラスとまったく同じですが、クラス名とファイル名は同じにする必要があります。また、ネームスペースをいれることにも注意してください。


(Hoge.php)

<?php namespace Sukohi\Hoge;

class Hoge {

    // Something...

}


では、次に「HogeServiceProvider.php」の設定を見ていきましょう。
やることは2つ。
register() と provides() メソッドにそれぞれ決まり文句を追加するだけです。

1.register()

 public function register()
  {
  $this->app['hoge'] = $this->app->share(function($app)
  {
   return new Hoge;
  });
  }

※「hoge」「Hoge」はあなたのパッケージ名に置き換えてください。


2.provides() 

 public function provides()
 {
  return array('hoge');
 }


はい。
これでここの作業は終了です。


では、次に以下のような形でクラスを呼び出せるように Facades を作成しましょう。

Hoge::method();

HogeServiceProvider.phpがあるフォルダに「Facades」というフォルダを作成し、さらにその中に「Hoge.php」を作成してください。
フォルダ構成は以下のようになります。

Sukohi
 └ Hoge
   ├ Facades 
   ├ Hoge.php
   └ HogeServiceProvider.php

そして Hoge.phpの中に以下のプログラムを書き込みましょう。


<?php namespace Sukohi\Hoge\Facades;

use Illuminate\Support\Facades\Facade;

class Hoge extends Facade {

  /**
   * コンポーネントの登録名を取得
   *
   * @return string
   */
  protected static function getFacadeAccessor() { return 'hoge'; }

}

※太字の部分がベンダー名とパッケージ名になります。大文字/小文字に気をつけてください。



では、次に Laravel からこのパッケージを呼び出せるように設定しましょう。
(いつものパッケージを composer からインストールしたときの手順と同じです。^-^)

Laravel/app/config/app.php 

を開いて、配列の providers の最後に「HogeServiceProvider」を登録し、

'providers' => array(

 (他のパッケージ), 
 'Sukohi\Hoge\HogeServiceProvider', 

),


さらに同じファイルにある「エイリアス」も設定します。


'aliases' => array(

 (他のパッケージ), 
  'Hoge' => 'Sukohi\Hoge\Facades\Hoge',

),


はい!
これでパッケージが完成しました。
もしエラーがでるようなら、フォルダの階層がまちがっていないか(←これは私のことです^^)、もしくは composer dump-autoload 、 composer update などをするとうまくいくことがあるようです。

ということで少し複雑でしたが、独自パッケージを作成手順でした。
ちなみに、フリーランスとしてプログラムの著作権をすべて渡してしまう約束の場合、こういったパッケージの開発は私はしません。全部持って行かれるのが悔しいパッケージは後のことを考えると便利ですが作成するのに少し時間がかかるので。(笑)
なので、プロジェクトとは別でゼロからパッケージを作成するようにしています。
でも、これってプロジェクトにとってもマイナスなんだけどなー。。。
この辺みんなはどうしてるんでしょう?

とにかくお疲れ様でした。



[参考ブログ(というかほぼ訳しただけ)]

http://culttt.com/2013/06/24/creating-a-laravel-4-package/

Thank you the author(s) of Culttt.com.
Your tip is really useful!
So I've just followed your twitter. :)))

2014-08-10

Laravelのキャッシュが消えない!

こんにちは。
ちょうど今、珍しく私の住んでいる地域に台風が直撃しているようです。
みなさんもくれぐれもお気をつけ下さいね。

さてさて、今回は数日前にリニューアル公開したインフォブログランキングの作業中に起こった「Laravelのキャッシュが消えない現象」についてご紹介しようと思います。

(はい。最近Laravel漬けになっています。知れば知るほど「すごいなー」とつぶやいています^^)





[最終結論: バグではないけど、別の仕様を追加してほしい]


まず、私に起こった問題は以下のようなものでした。


日付が変わると新しいデータをDBから取得して、それをまたキャッシュとして保存する。

↓↓↓

でもキャッシュが削除されず同じデータのまま。


つまり、その日ごとにデータを表示したかったのでその都度DBにアクセスをせずキャッシュを利用した、ということです。

実際のプログラムは以下。

if(Cache::has('key')) {

    return Cache::get('key');

}

// DBからデータを取得

$dt = Carbon::tomorrow();    // 明日の日付を取得
Cache::put('key', $value, $dt);
return $value;


前回紹介したCarbonを使っています。
※現在はより便利なCache::remember() を使っています。


一見問題なさそうなのですが、、、?
実はこれではキャッシュが消えなくなる(可能性を持っている)のです。


なぜなら、元々Laravelのキャッシュの有効期限はタイムスタンプではなく、「分」を使っているから

なのです。

つまり、上の例でいうと、

1.Laravelは、$dt を使って明日が始まる時間まで何分かを取得。
2.その分数を有効期限とするキャッシュを作成

???

やっぱり問題ないのでは、、、?

これが大有りなんです。


なぜなら、Carbon(dateTime)から分を取得するとき intval() で数字が切り下げになってしまう

のです。

そう!
つまり、キャッシュはまだ日付が変わっていないのに有効期限が切れて削除され、そしてその当日のデータ(すでに保存されているものと同じデータ)をまた新しく保存してしまうというものです。

インフォブログランキングは手前味噌ですが、なかなかページビューが多いサイトなのでこの僅かな時間に新しいアクセスがあり、キャッシュがうまく更新されていないという状況でした。


???

でも、新しいキャッシュができたとしてもまた、明日までの有効期限だからすぐに新しいデータに置き換わるのでは???


実は、これもそうでもないんです。

結論からいうと、

分数がゼロの時はキャッシュは永遠に保存されてしまう

からなのです。
つまり、分がintval()で切り下げられてキャッシュを保存し、そのキャッシュが削除ときには残り時間は予定の時間まで1分未満になります。

その1分未満はintval() でゼロに変換されてキャッシュが消えない状態になってしまうということですね。

ということで、インフォブログランキングをよろしく Laravelでキャッシュを使用する時にはお気をつけ下さい。^-^

※おそらく間違いはないと思っていますが、自信がない部分もありますのでこの記事に修正が必要でしたらぜひ教えてください。よろしくお願いいたします。m_ _m

ではでは〜。




2014-08-07

PHPで日付を扱うなら Carbonライブラリが便利すぎる!!

個人的にまた災難が起こってしまった後、はじめての投稿になります。
みなさんもお体にはくれぐれもお気をつけ下さい(汗)

さて、今回はPHPの日付に関する記事になります。
というのも、最近ハマっているPHPフレームワーク「Laravel 4」には Carbonが標準搭載されているようで、これを使ったらもう昔には戻れない!と思ったのでぜひ紹介&備忘録としてその使い方を公開したいと思います。




[最終結論] 直感的に使えるのでとても便利です!なんならLaravel以外での開発でも使っていこうと思いました。


では、使い方に行く前に注意点を少し。
Laravel での使用を想定しているので、基本的に static な使い方で書いてます。
必要に応じて new Carbon(); してインスタンスを作ってくださいね。
あと、PHPは5.3以上必要です。

また、よく使うだろうというものだけで、全てのメソッドは網羅していません。詳しくはCarbon(英語) を確認してください。


1.基本的な使い方。


・今の時間は?

 Carbon::now();

・今日が始まる時間を知りたい

 Carbon::today(); // (例)2014-08-07 00:00:00

・じゃあ、昨日は?

 Carbon::yesterday(); // (例)2014-08-06 00:00:00

・明日も教えて。

 Carbon::tomorrow(); // (例) 2014-08-08 00:00:00

・タイムスタンプがほしいんだけど?

 Carbon::today()->timestamp; // (例) 1407337200



2.足したり引いたりする使い方。


・今からちょうど一日後/前の時間は?

 Carbon::now()->addDay();
 Carbon::now()->subDay();

・3日後/前

 Carbon::now()->addDays(3);
 Carbon::now()->subDays(3);

 ※その他にも

 秒: second(s)
 分: minute(s)
 時間: hour(s)
 年: year(s)
 月: month(s)

 でも同様のメソッドが用意されています。

 例) addSecond(), subYears(5)


3.文字列から指定する使い方。

・次の水曜日は?
 
 new Carbon('next wednesday');

・今週の木曜日は?

 new Carbon('this thursday');

 ※この辺は英語の知識が必要になりますね。昔学校で習ったはずですが、、、(笑)


4.各種データを取得する使いかた。

 $dt = Carbon::now();
   
 $dt->year;
 $dt->month;
 $dt->day;
 $dt->hour;
 $dt->minute;
 $dt->second;
 $dt->daysInMonth;

 ※いつものごとく、月($dt->month)の数字はゼロから始まるので+1が現在の月のようです。
 ※逆に上記に数字を代入することで時間をセットすることもできるようです。便利!


5.多分必要になった時にとても感謝するだろう使い方。


・年齢

 Carbon::createFromDate(1980, 1, 1)->age;

・週末?

 if (Carbon::now()->isWeekend()) {

  echo 'パーティ!'; // 本家のサンプルにこう有ります(笑)

 }

・もう過ぎた?まだ?

 $dt = Carbon::now()->subDay();
 
 if ($dt->isPast()) {

  echo 'もう過ぎた!';

 }


 $dt = Carbon::now()->addDay();
 
 if ($dt->isFuture()) {

  echo 'まだ!';

 }

・タイムゾーンが知りたい

 Carbon::now()->timezoneName;


6.アロー演算子「->」の使い方。

 $dt = Carbon::now();
   
 echo $dt->year(1975)
     ->month(5)
     ->day(21)
     ->hour(22)
     ->minute(32)
     ->second(5);

 ※Laravelのように一気にかけるのはコードがスッキリして好きです。^^


と、ざっとこんな感じですね。
あとは日付の比較やBetween を使った便利なものもありますが、すこし複雑になるので気になった方は本家のCarbonのGitHubページをご覧ください。

それにしても技術は確実に進歩していっています。
より簡単に高度なプログラムが、しかも直感的に使えるようになってきていますね。

なお、Carbon はMITライセンスなので、開発者にはホントにありがたいです。
Brian Nesbittさん、ありがとうございます。


ということで以上です。
お疲れ様でした!


2014-07-03

AWS で"eb init" せず push するための設定

最近は新しい技術に触れる機会が多いのでとても刺激的な日常を過ごしています。^-^
ここのところ、新しいものをあまり勉強する機会がなかったのですが、自分のもっているスキルがいかに古くなってしまっているかを実感させられています。

(しかも嬉しいことに新しいことを学ぶ楽しさを思い出させてくれました。)

・・・ということで今回はAWS(Amazon Web Services) のGit を使ったデプロイシステム「EB」で、すでに作成されたレポジトリに後からアクセスする方法です。





[最終結論]: amazon が提供する zipファイルの中にしっかりと専用のファイルが入っていました。(汗)



では、まず前提としてなぜ "eb init" を使わないか、というと今回の案件の前任者がすでに作成していたので、新しくリポジトリを作成する必要がなかったからです。

もし、まだリポジトリを作成してない方はこのページは全く関係ないので注意してください。そして、もちろん git と eb はインストール済みという前提ですので、こちらも注意してくださいね。



では、順を追って実際の作業を説明します。


1.まず、AWS Elastic Beanstalk Command Line Tool からEBのパッケージをダウンロードして解凍しておきましょう。


2.ターミナル/コマンドプロンプト(以下のようなやつです)を開いて push したいプロジェクトまで移動しましょう。



例) cd /move/to/your/path


3.以下のコマンドを実行しましょう。


/(EBパッケージを解凍したフォルダ)/AWSDevTools/(Linux か Windows。←環境に合わせて選択)/AWSDevTools-RepositorySetup.sh

※Ubuntuなどの場合、もしかすると sudo とかが必要かも。


4.以下のコマンドを実行

git aws.config


5.以下の情報を入力

 ・パブリックキー
 ・シークレットキー
 ・リージョン(東京とか)
 ・AWS(EB)内のアプリケーションの名前
 ・環境

これで成功すれば、その場所で


git aws.push


とコマンドを打てば自動でデプロイしてくれます。
さらに、本番環境とテスト環境をもっている場合、


git aws.push --environmentの名前


とすると該当する環境の違う方へもデプロイができるそうです。(、、、が私は一度も試しておりません。^^;)


[参考ページ(というよりほぼ日本語訳にして丸写し。。)]:




Dan Hoerst, I appreciate you and your tip.
I could solve my problem earlier than I expected because of you!! :)


最後に、昔住んでたバンクーバーホテルの裏にあった図書館です。帰りたい、、、(笑)



2014-06-26

PHP + JavaScript(jQuery) でチャットするComet を作ったみた【ダウンロード可】

最近、おかげさまでホントに色々な案件に携わらせてもらっていて開発者としてまだまだレベルアップを感じている今日このごろです。^-^

ということで、今回は前々から気になっていた 擬似的なComet によるチャットシステムが必要になり、この部分は今後もきっと必要になる機会が多いんじゃないかと思いましたので、PHPとJSをパッケージ化して GitHub にアップしてみました。



使い方は README.md をご覧ください。(書き方はむちゃくちゃですが^^;)

[GitHub(Comet)]: https://github.com/SUKOHI/Comet/tree/master


[参考URL]: http://rewish.jp/blog/tech/php_with_jquery_comet

今回↑のページにはお世話になりました。ありがとうございます。 m_ _m


[追記]: 実際にテストページを作ってみました。





「 こんな短いブログ記事初めて(笑) 」

2014-06-10

Grunt が「Warning: watch ENOSPC」と警告を出した時の対処

現在、とても優秀な前任者から引き継いだ案件にとりかかっています。
この案件の中で彼がCSSやJavaScript の結合や軽量化をしてくれる「Grunt」と呼ばれる技術を使っていたので私もトライしてみたのですが、きちんとインストールしたにも関わらず「Warning: watch ENOSPC」という警告を多発していたので対処法を探ってみました。




[最終結論] ファイルを監視しておける数には限界が設けられているので、この数が足りなくなると警告が出される。


では、まずは私のPC環境から。

OS: Ubuntu 14.04
Grunt: 0.4.5

[エラーが出た状況] Grunt watch を使ってファイルを監視しようとすると以下のように毎回表示されていました。



少し Google で探ってみると以下のページにそのものズバリの回答と対処法が説明されていました。



これを読む限り、ユーザーが監視しておけるファイル数には限界が設けられていて、例えばDropBoxなどを利用しているとこの初期値を使い果たしてしまう。
そのためGruntがエラーを返していた、ということらしいです。


では、どのようにすればこの問題に対処できるか、というと・・・?


コマンドラインで、


echo fs.inotify.max_user_watches=100000 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p


を実行すればOKです。

※ちなにみ参照ページとは違い100,000という数に変更しています。


この命令は先ほど説明したファイル監視できる数を増やす命令文になります。
これを実行してから「Grunt watch」をすると、、、?




はい!うまく起動されてファイルが変更されるのを待ってくれています。


ということで今回は短い記事でしたが、私の場合はDropBoxがその原因になるという思いがけないものでしたので今回のTipをご紹介しました。

お疲れ様でした。m_ _m



Thanks, KDS!
Your tip helped me at once!

2014-06-01

Ubuntu 14.04 で再生されてる音を録音する方法

もうかれこれWindows→UbuntuへメインOSを変更して10ヶ月ほどが経ち、正直ほぼ何の問題もない今日このごろです。

そして、今回は以前windowsでもやったことがある「PC内で再生されている音を録音する」というのをUbuntuでもやってみたくなり、挑戦したところあっさりと実現できましたのでここに備忘録としてその方法を残したいと思います。




[最終結論] Audacity をインストールすれば後は設定だけでOK。


まず録音をするソフトウェアをインストールしましょう。
今回はターミナルを使わず簡単にインストールできる「Ubuntuソフトウェアセンター」を使います。

検索ボックスの中に「Audacity」と入力して検索すれば以下のようなマークのソフトウェアが出てくるのでそれをインストールしてください。



インストールが完了したらこのAudacityを開きましょう。

そして、音声の調整ができる pulseaudio というものがすでにインストールされているはずですので、これも起動してください。
(もしインストールされていなければ、Audacityと同様にUbuntuソフトウェアセンターからインストールできます。)

では、以下のようにAudacityの録音ボタンをクリックして録音を開始します。




次に、pulseaudio の方で以下のように、「録音」タブの中にある「ALSACapture から」の部分を

Monitor of 内部オーディオアナログステレオ

へ変更します。
この設定でPC内で再生されている音を録音することができます。

※なので、録音が終わったら元に戻しておくほうがいいと思います。試してませんが、おそらくこの設定のままでスカイプとかができなくなってしまうので。




さぁ、これで準備は万端です。
後はつないだ電子ピアノなどで音を鳴らせば Audacity 内で録音されていきます。

※ちなみにパソコンのスペックや環境によっては録音の遅延が起こり、なんともぼやけた音が録音されることがあります。その際は他のアプリケーションを閉じるなど工夫してみてください。

以上です。
おそらく他にもいろいろな録音設定があると思うのですが、今回のケースでは何の問題もなかったのでもし不具合が起こったら、また追記したいと思います。


ではでは。
最後に僕の中で一番天国に近い場所、バンクーバーの写真をご覧ください。^-^