スイーツ(笑)と呼ばないで!!
| |||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
11/24/02:57 [PR] |
07/26/00:15 プログラム言語の異文化交流・・先日、ちょっと頼まれて、html5のvideoタグを使って、mp4を再生しているソースを見ました。
html5を使うとAPIを使ってJavaScriptでいろいろと操作する機会も増えますよねー 今日はそんなJavaScriptについてのお話です。 テーマは「プログラム言語の異文化交流・・」と題して、 PHPバリバリ書いてるPGがJavaScriptを書くとうっかりやってしまうこと、 について書きたいと思います。 この世の中にはたくさんのプログラミング言語があり、 細かい違いはもちろんありますが、 条件分岐があったりループ処理があったりと、 すごーーーくざっくり言うと、似たようなもの、だったりしますね。 なので、PHPで一人前にプログラムを書けたりすると、 「ああ、JavaScriptではこう書くのね、了解ー」 という軽い感じでガリガリ書いてしまうというのもよく聞く話です。 でも、やっぱり言語にはそれぞれ固有の独自の仕様があったりするわけで、 そこを知らないと、それが理由でバグの温床になったりすることがあります。 JavaScriptの仕様で、意外と知られていないのがhoistingというやつです。 日本語だと「変数の巻き上げ」とか言ったりしますね。 以下、シンプルな例を用いて説明してみます。 var name=“yamada"; //グローバル変数nameを宣言し代入。 function printName(){ console.log(name); //変数nameの中身をコンソールに出力。 } printName(); //上で定義した関数printNameを実行。 このソースの実行結果は、yamadaと出力されます。 これはたぶんPHPプログラマの人もとても直感的に理解できると思います。 では、console.log(name);の下に1行だけ追加した以下のソースはどうなるでしょうか。 var name=“yamada"; //グローバル変数nameを宣言し代入。 function printName(){ console.log(name); //変数nameの中身をコンソールに出力。 var name=“tanaka”; //ローカル変数nameを宣言し代入。 } printName(); //上で定義した関数printNameを実行。 普段PHP書いていて、JavaScriptも同じような感覚で書いているPGの方だと、もしかすると 「え? そのままグローバル変数のname読むから、結果はyamadaで変わらないでしょ?そもそも1行追加したの出力の下の行だし・・」 という回答をするかもしれません。 でも、JavaScriptでは、その期待は裏切られることになります。 実は、上記のJavaScriptは内部的にはhoisting(=変数の巻き上げ)により、 var name=“yamada"; //グローバル変数nameを宣言し代入。 function printName(){ var name; console.log(name); //変数nameの中身をコンソールに出力。 name=“tanaka”; //ローカル変数nameを宣言し代入。 } printName(); //上で定義した関数printNameを実行。 と同じように解釈されます。 つまり、初期値の代入部分はそのままで、変数の宣言だけそのスコープ(この場合function)の先頭に巻き上がるんですねー 結果、上記ソースの出力は、初期化されていない変数の出力ということで「undefined」となります。 さて、JavaScriptにはこのようなhoisting(変数の巻き上げ)という仕様があるため、 そのスコープの途中で変数を宣言するのはバッド・プラクティスで、 そのスコープの最初でまとめて宣言するのがベスト・プラクティスと言われます。 つまり、functionの中であれば、functionの中のスコープで用いる変数はすべてそのスコープの頭で宣言すべきということですね。 言語によっては、変数の宣言はなるべく使うところの近くで行いましょう、という文化があるものもあります。 ただ、JavaScriptの場合は、そうではない、ということですね。 たまたま見たソースがスコープの途中で変数がたくさん宣言されていて、 「ああ、わかるわかる・・多くの人が通る道だな」 と思い、記事にしてみることにしました。 たくさんの言語があって、たくさんの文化があって、 なかなか深いところまで理解するのは大変です。 私も頑張らないとなーと思う今日このごろです^^;;;; PR
|
07/24/13:00 MySQLのStrict Modeについていろんな事情があって、CentOS7以降だと、 MySQLではなくMariaDBがデファクト・スタンダートになったわけですが、 未だCentOS6系のサーバーでMySQLを動かしている人も多いでしょう。 今日はそんなMySQLのお話。 私は一時期DB系の研究を業務にしていた時期なんかもあったんですが、 そんな私から見るとMySQLは超怖いDBでした。 何が怖いって、varchar(50)とか定義したところに、60文字をPHPで投げつけても、 エラーも出さず知らん顔で50文字だけ格納して成功ステータス返す、そんな奴だったんです。 ちゃんと格納されたと思ったら、数日後に・・「あれ?文字が途中で切れてるぞ?」とかなるわけです。 もちろん、MySQLに渡す前にPHPでvalidationをきちんと書いてあれば、ちゃんとエラー制御できるんですけどね。 ただ、コンバートとかで直操作する必要があったり、validationの実装ミスに気づけなかったり、というのはかなり怖いですね。 まるで、コンパイル言語がコンパイル時にバグに気づけるのに、 非コンパイル言語では実行時エラーしかとれない、とかそんなのに近いです。 皆さん、仮に次のような二人の部下を持った自分を想像してください。 問題が発生した時に、 部下A:「うぉぉぉぉぉぉ!!!!!!・・・・・やっちまったぜ・・orz」と大騒ぎする部下 と 部下B: 「できました^^」と笑顔で報告して問題については何も言わずそのまま放置する部下 どっちが良いですか? 私は間違いなく前者の大騒ぎする部下ですね^^ で、そんなMySQLなんですが、実はちょっと前からsql_modeというのがあって、 そこでStrict Mode(正確にはSTRICT_TRANS_TABLES)を選択すれば、 ちゃんと「普通に」仕事してくれるようになります。 ただ、今までint型に空文字を投げていたプログラムなんかは、エラーになります。 まぁ、intに空文字投げちゃそもそもダメでしょ、と思うわけですが、 人によっては「君、わかってるねー、気が利くねー」と思ってたようで、 そんな人には不評なようです。 そんな中、時代は流れまして、MySQL5.6では、このStrict Modeがデフォルトになりました。 さぁ、大変です。 今まで、intに空文字なげていたようなプログラムは全部エラーで落ちまくることになりました。 焦って騒いだ世の中の人たちが取った行動は・・・ 「Strict Mode・・・オフればいいんじゃね? そうすれば、また、世界は平和に・・」 です。 皆・・・目に見えない問題は「=存在しない」と思うんですね。 そうして Strict Mode・・・オフ (←いまここ) というプロジェクトが世の中にたくさん出来上がったんです。 いや、intに空文字投げちゃうPGの発想、理解できないわけじゃないですよ。 テキストボックスで金額入れてもらうところとか、 普通にpostされたデータ見ると、nullじゃなくて、空文字ですもんね。 HTTPのプロトコルは、 最終的に文字列型で格納されるのか数値型なのかなんてpostする時点では知る手段はないので、 PHP側で適切に判断してあげるしかないですね。 HTML5が普及して、input type=“date”とか新しいtype属性が増えて、 今まで、selectボックスで年月日を指定させていたところ(必ず数値で受け取ってた)が、 見かけ上はテキストボックスみたいなUIになるので、 結果的に空文字が投げられることも発生するようになった、 なんて変化もあります。 date型に空文字、なんて事故も起こるようになりますね。 MySQLがシャキッとしてやっと普通のDBになってきたんです。 我々もちゃんと使ってあげましょうー ちなみに、余談ですが・・・ LinuxのセキュリティでSELinuxというのがあります。 より強固なセキュリティになる機能で、もう何年も前にデフォルトでオンになりました。 これ、結構安心できる機能なんです。 でも、ちょっとだけ設定や理解が複雑。 で、世の中の多くの人は 「えっとー、linuxセットアップするなら、最初にー、selinuxはオフにするのー」 と覚えて実行しています^^ SELinuxの話はまたどこかで記事にするかもしれません。 とりあえず、できるところから地道に取り組んでいくしかないですねー ローマは一日にしてならず!! ここ数日、毎日ブログ書いていて暇人だと思われている気がするので、今日はこんなところで^^ |
07/22/18:37 HTML5の本当のすごいところは!?さぁ、このあと不定期で続くかもしれない、HTML5特集のPart1です。
皆さん、HTML5使っていますかー。 「ああ、DOCTYPEとかそれっぽく宣言してる」 「input要素でplaceholder使ってるぜぃ」 「input type=“date"とかするとカレンダー出たり新しいtypeが増えたよね」 とか、そんな返事が返ってくるかもしれませんね。 確かに、それらはHTML5の特徴的なところで、いろいろと語られているところでもあります。 ただ、私達ブログラマにとって地味にすごい拡張されているの、知ってます? 今日はそんな中から2つ程紹介しますね^^ これ知っているかしらないかで、JavaScript書く量がかなり変わります。 例えば、こんなシーンを思い浮かべてください。 ◎例題1 なんかのデータの編集画面です。 ずらーってinput要素やらselect要素やらが並んでいます。 一番下に、「上書き保存」「名前をつけて保存」などのボタンが並んでいます。 【超初心者の回答】 「あ、あれ、ボタンが2つ・・formのactionは1つしか指定できないし・・どっちのボタンか区別できないし・・うーん」 とか言いながら、formの中にformをもう一つ作ったりして実装できず・・・経験者に助けを求める。 【経験者(=普通のプログラマ)の回答】 「こういうのはな、jQueryとか使ってやるんだよ。submitされたタイミングでイベントとって、どっちのボタンが押されたかはidを取得して、それでactionの先を動的に変更してだな、そうするとpost先(=action)を変更できるんだよ。やっぱ、時代はjavascriptだぜー」 とか言いながら、やりよる感を出します。 【HTML5の達人の回答】 「えっとー、次の例見てみてください」 <form id="form_id" action="/test" method="“POST""> <input type="text" name="test_id" value="123" > <input type="submit" value="test1" > <input type="submit" formaction="/test2" value="test2" > <input type="submit" formaction="/test3" value="test3" > <input type="submit" formaction="/test4" formmethod="“GET"" value="test4"> </form> 「HTML5だとー、formaction属性が追加されているんですよねー。なので、submitボタンのformaction属性に/overwriteとか/copyとかつければsubmitのタイミングでaction勝手に変わりますー。javascriptとかいらないですー。」 「ちなみに、formmethod属性でgetとかpostとかも変えられるんでー。Laravelとかmethod毎にroute書ける系は超便利ー」 とか言いますね、きっと。 これ、かなり便利です。他に「削除ボタン」だろうが「プレビュー」ボタンだろうが、つけ放題ですね。 (ちなみに、プレビューを別タブで開きたいならformtarget属性でtargetも書き換えられます) ◎例題2 ページの上部に基本的にform系の要素はまとまっているんだけど、 ページの中間に長い説明文とか一覧とかがあって、 ページの最下部にボタンが並んでいる仕様のページが作りたいんだけど・・ 【超初心者の回答】 「うーん・・・formの中にsubmitボタンとか他のinput要素とかたくさん入れなきゃならないから・・ページの上部から下部まで、長ーいですけど全部formタグで囲っちゃえば良いですね。え・・・・途中に一覧の検索ボックスがある・・・formは入れ子にできないし・・・」 とか言いながら、実装できず。 【経験者(=普通のプログラマ)の回答】 「こういう時も、JavaScript最高だぜ。とりあえず、まとまっている部分はformタグで囲って、あとは離れたところのボタンのクリックイベントとって、JavaScriptでpostしてあげれば良いのさ。やっぱ、時代はjavascriptだぜー」 とか言いながら、やりよる感を出します。 【HTML5の達人の回答】 「えっとー、次の例見てみてください」 <form id="form_id" action="/test" method="“POST”"> <input type="text" name="test_id" value="123"> <input type="submit" value="test1"> </form> (なが~い文章とか) <input form="form_id" type="text" name="external_value" value=""456”" > 「HTML5だとー、form属性が追加されているんですよねー。そこにどんなに離れたformでもそのformのidを指定してあげれば、そのformの中にあるのと同じように扱ってくれるんですー。javascriptとかいらないですー。」 とか言いますね、きっと。 これ、かなり便利です。離れていようがないだろうか、お構いなしですね。デザインと構造は分離されています。 ということで、HTML5にきちんと対応しているブラウザ相手だとだいぶ工数が削減できることがわかりますね。 ここで、お客さんがプロジェクト後半になって「あー、やっぱりIE8も使いたいなー」とか言ってきたらどうでしょう。 そのためだけにたくさんの面倒なコードを書かないといけないですね。 「テストのブラウザが1つ増えて面倒だなー」とかってレベルではありません。 私もプロジェクトマネージャーを生業としていますが、やはりこのようなところはプロジェクトの最初できちんとお客さんと握っておくことが大事だな、と改めて思います。 ということで、HTML5を採用しているのにHTML5っぽく書いていないあなた、ちゃんと勉強してみると超楽になるかもしれないですよー^^ |
07/22/14:22 PHPの実行環境を一番簡単に作る方法!?Laravel4.2以降とかだと、必然的にPHPは5.4以降を使うことになる。
(ちなみに、Laravel5.1使うなら、PHPは5.6が必須) PHP5.4・・・このバージョンで思い当たるのは、そうBuilt-inサーバーが使えるね、ということ。 会社によっていろんなスタイルで開発していると思う。 クラウド上や社内に共用の開発サーバー立てたり、 個人のPCの仮想環境上に仮想の開発サーバー立てたり。 そんな選択肢の中で、一番お手軽なのはPHP5.4以降で準備されているBuilt-inサーバー。 私はmacユーザーなので、以下macでの例だけど、例えばこんな感じでPHPで書いたプログラムが動かせる。 1.phpのインストール まず、phpのインストール、これはmacユーザーならお馴染みのbrewコマンドで一発。 #brew install php56 とかやれば良いね。 2.ソースのドキュメントルートになるディレクトリに移動して適当なポート指定して起動 #php -S localhost:1234 以上、超簡単。これでブラウザでhttp://localhost:1234と打てばもうそのPHPアプリが動かせる。 1234の部分は、8888でも1111でもOK。このポート変えるだけでいくらでもいろんなソースを瞬時に何個でも起動できる。 linuxサーバーで必ず通るVirtualhostの設定とかhosts等DNS系の設定も不要。 ちなみに、余談だけど、brew search phpと打つと、php53とかphp54とかphp55とか出てくるね。好きなバージョンPHPを入れてください。 え? windowsの場合どうしたら良いかって・・・windows使いの先輩を捕まえて聞いてみてください^^ |
07/17/12:45 LaravelのSeederをどう使う?たまに社内SNSでSeederについて話題にあがる。
Seederは、一般的には、テーブル定義が変わった時なんかに、 一度テーブルの中身をリフレッシュして再度テストデータを埋め込む、 こんな利用シーンが多いだろうか。 今日見かけたのは php artisan db:seed --class=DevelopmentSeeder という1行。 —classとオプションを指定することで特定のSeederクラスを実行できる。 命名から開発環境のテストデータを作り直したいのだなと思う。 中を見てみると、複数のテーブルにinsertする記述がこの1つのファイルに書かれている。 みんないろんな使い方をしているようだ。 もちろん、使い方に正解があるわけではない。 今日は、自分だったらどうするかなー、というのを考えてみたいと思う。 前述の例の--classのオプションを指定しないでdb:seedを実行するとどうなるか。 デフォルトではLaravelが最初に用意しているDatabaseSeederというSeederが実行される仕様となっている。 Seederは別のSeederを呼び出すことができる。 runメソッドの中で $this->call(’Seederのクラス名’); という感じだ。 おそらくLaravelのSeederの設計思想としては、 DatabaseSeederのrunメソッドの中に複数のSeederをcallするような想定でいるのではないかと思える。 Laravelの公式ドキュメントのサンプルでも public function run() { Model::unguard(); $this->call(UserTableSeeder::class); $this->call(PostsTableSeeder::class); $this->call(CommentsTableSeeder::class); } なんて記述がある。 ここからもう一つわかることは、Seederはやっぱり基本はテーブル単位で作る想定よね、ということ。 さて、ここで少し話がズレるが、テーブル定義をリフレッシュする際に同時にSeederを実行したい時どのようなコマンドを打っているだろうか。 Laravelでは、実はmigrationと同時にSeederを実行する機能がある。 php artisan migrate:refresh --seed このように--seedオプションをつければ一発で実行できる。 この際呼ばれるSeederはデフォルトのDatabaseSeederだ。 こんなことからも、Laravelとしては、DatabaseSeederを親としてrunの中で子Seederを呼んで欲しいんじゃないかな、と思ったりする。 え、developmentとかproductionとか環境ごとにSeederが変わる場合はどうしたら良いかって? 私が考える正解は、 DatabaseSeederの中で環境毎のSeeder(例えば、LocalSeeder、ProductionSeeder等の「環境名」+Seeder)をcallし、その環境毎のSeederの中で、その環境必要に応じて各テーブルのSeederをcallしてあげればよい、 というもの。(本番では呼びたくないとかあるもんね) もちろん、if文で分けるなんてかっこ悪いことはせずに、環境の名称からクラスを特定するか、 より柔軟にするならLaravelのconfigは環境ごとに設定を記述できる仕組みになっているので、そこでその環境の親Seederのクラス名を書けば設定が上書きできるようにすると良いと思う。 ちなみに、artisanコマンドで環境を指定するには--envオプションを使えば良いね。 例えば php artisan migrate --env=local こんな感じで環境を指定できる。 ということで、いろいろ書いてきたけど、これはあくまで私ならこうするかも、というもの。 皆、それぞれ使いたいように使えば良いさー (沖縄風) |