JQuery との別れ
こんにちは、専門学校に通いながらwebエンジニアのバイトをしている者です。
普段考えていることや、新しく知ったこと等を適当にブログに書いています。
今回は JQuery についてです。
自分は趣味でwebページを作ることがあり、ページ内のロジックに JavaScript を使用しています。(当たり前ですが)
その際に自分は JQuery を使用していたのですが、 最近 JQuery はあまり使うべきではないという話をよく耳にしており、何故ダメなのか疑問に思っていました。 そこで、JQuery のデメリットや、JQuery を使わない場合等をネットで調べたり、会社の先輩に聞いてみたりしました。
また、今回の記事は私見が多く含まれているので、あくまで考え方の一つとして捉えていただけたらと思います。
JQuery はスコープがでかい
JQuery を使うとDOM全体を操作出来てしまう為、JavaScript の長いコードを修正する際にコード全体を読まなければならないそうです。 また、対象の要素の親要素を操作出来る .parent() 等のメソッドを使用してしまうと、コードの修正がとても大変になってしまうみたいです。
これらの原因は、JQuery のスコープが大きいことにあります。 ですので、本来webページのロジックを記述する時はページ内のコンポーネントごとに行うことが理想です。 もちろん JQuery でもコンポーネントごとにコードを書くことも出来ますが、 全体を操作出来るメソッドが存在する以上、見づらいコードが生まれてしまう可能性は潰せないようです。
じゃあどうすればいいのか
生の JavaScript か、フレームワークを使うと良いとのことでした。
生の JavaScript は面倒なことが多いですが、可読性は高いようです。
また、フレームワークを使用すれば、ページ内のパーツをコンポーネントに分けて開発できるので、 スコープを縮めることが出来ます。
JavaScript のフレームワークは一度も使ったことが無かったので、現在開発しているwebアプリケーションに組み込んでみようと思っています。
まとめ
JQuery さよなら。
ある男の為に自作楽曲配布サイトを作る
Googleアドセンスの申請を通したくて久しぶりに記事を書きました。
自分は現在、IT系の専門学校に通いながらIT系のアルバイトをしています。 もちろん趣味でもプログラミングをしており、最近はアルバイトの影響でweb系の勉強を多くしています。 アルバイトではバックエンドの仕事が中心ですが、趣味ではバックもフロントもやってます。 しかし、勉強するだけでは本質的な技術は身につかないと思ったので、実際にwebサービスを作ることにしました。
webサービスを趣味で作った経験はまるで無いので、とりあえず簡単なサービスから作りたいなと思っていました。 そんな時、高校の頃の同級生が学校にも行かずにひたすら曲を自作しているというので、まずはそいつの為のサイトを作ろうと思いました。
サイトの機能は、楽曲再生・ダウンロード・コメント の3つが中心です。 たったこれだけなのかと思うかもしれないですが、 データベースを使ったり、動的にサイトを書き換えたりという処理をしたのは人生で初めてだったので苦労しました。
バックエンドは FuelPHP というフレームワークを使用し、フロントでは当然ながら JavaScript を使用しています。 バックエンドに Rails ではなく PHP を選んだ理由は、環境構築が圧倒的に楽だったからです。 Rails が強力なフレームワークであることは理解していますが、趣味で使うにはまだ知識が足りないなぁという印象でした。
公開するためのレンタルサーバは、Xサーバ の一番安いプランを利用しています。 一番安いとは言っても、個人が趣味で作った小さなwebサービスを公開する分には十分使えます。 料金の支払いは高校の同級生と割り勘です。
このサイトは8割近く完成しているので、今月中には公開出来るだろうと思います。 公開しましたら、是非曲を聴いてくださると嬉しいです。
ある男の Twitter → @k_t_mejohn
ある男が作った曲 → 作った曲
セキュリティ・キャンプ 2016 選択問題解答
ブログでセキュキャンの解答を晒している方が何人かいらっしゃったので、自分も晒してみようと思います。 ここ違くね?とかここは同じだ!とか思っていただければ幸いです。
選択問題1
実行結果のアドレスのサイズを見る限りですと、上記のプログラムは64bit の OS で実行されているのではないかと考えました。
理由は、32bit の OS で上記のプログラムを実行した際は上記の実行結果よりも小さなサイズであり、 64bit の OS で実行した際は上記の実行結果に近いアドレスとなったからです。
32bit の OS で実行した結果は下記の通りです。
hoge address = 0019F824 fuga address = 002D3208
他に感じたことは、スタックとヒープのおおよその先頭アドレスがわかるので、上記のアドレスの差から これら2つの領域に割り当てられているアドレス領域のサイズがわかるのでは無いかということです。 「おおよその」というのは、ヒープに OS の管理領域がある為、正確な位置がわからないという意味です。
選択問題3
パソコンの電源が入るとまず、システムBIOSがハードウェアを初期化して記憶装置からブートローダを読み出します。 そして読み出されたブートローダはMBRに記録されているプログラムを呼び出し、呼び出されたプログラムはOSを読み込んで起動します。
OS起動後に何かプログラムを実行させる時は、補助記憶装置に書き込まれたプログラムを実行することになります。 しかし問題文にあるようにCPUは主記憶上のプログラムしか実行できないので、 プログラムローダと呼ばれるものが必要に応じて、補助記憶装置に書き込まれているプログラムを主記憶装置に読み出しています。
その後、プログラムローダは読み出したプログラムの先頭アドレスに飛ぶことで、目的のプログラムが実行されています。 以上の処理が行われているため、私たちは補助記憶装置に書き込んだプログラムを実行することが出来ています。
選択問題4
プログラムは Windows Vista 32bit版 で Microsoft Visual C++ 2010 Express で作成・実行しました。 最初はこの問題を解こうとは思っていなかったのですが、チノちゃんが目に入ってきて問題を解くことを決意しました。 ソースコードは下記の通りです。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> #define TRUE 1 #define FALSE 0 #define MAX_MAGIC 2 #define MAX_SOURCE 20 #define MAX_DESTINATION 20 /* バイトオーダーの違いを吸収する */ typedef union{ unsigned int byte_4; char byte_1[4]; }byte_union; /*------------ | その他関数 | ------------*/ /* 文字列を小文字に変換 */ void str_to_lower(char *str,int size){ int i; for( i=0 ; i<MAX_SOURCE+1 ; i++ ) str[i] = tolower(str[i]); } /* バイトオーダー変換 */ void change_byte_order(byte_union *data){ const int INT_SIZE = sizeof(int) - 1; byte_union tmp_data; // バイトオーダー変換 int i; for( i=0 ; i<4 ; i++ ) tmp_data.byte_1[i] = data->byte_1[INT_SIZE-i]; // 代入 data->byte_4 = tmp_data.byte_4; } /*------- | 条件 | ------- */ /* Magicの検証 */ int Condition1(char *data){ if( strcmp(data,"RH") == 0 ) return TRUE; else return FALSE; } /* Sourceの検証 */ int Condition2(char *data){ str_to_lower(data, MAX_SOURCE); if( strcmp(data,"rise-san") == 0 || strcmp(data,"cocoa-san") == 0 ) return TRUE; else return FALSE; } /* Destinationの検証 */ int Condition3(char *data){ str_to_lower(data, MAX_DESTINATION); if( strcmp(data,"chino-chan") == 0 || strcmp(data, "chino") == 0 ) return TRUE; else return FALSE; } /* data に valid_order_brand が含まれているか検証 */ int Condition4(char *data){ const char *valid_order_brand[3] = { "BlueMountain", "Columbia", "OriginalBlend" }; int i=0; for( i=0 ; i<3 ; i++ ) if( strstr(data,valid_order_brand[i]) != NULL ) return TRUE; return TRUE; } /* data に invalid_order_brand が含まれていないか検証 */ int Condition5(char *data){ const char *invalid_order_brand[2] = { "DandySoda", "FrozenEvergreen" }; int i=0; for( i=0 ; i<2 ; i++ ) if( strstr(data,invalid_order_brand[i]) != NULL ) return FALSE; return TRUE; } /*----------- |メイン関数 | -----------*/ int main(void) { // 変数宣言(ファイルからデータを読み込む変数は、読み込んだデータを文字列として扱うために \0 の領域分を確保している) char Magic[MAX_MAGIC+1]; char Source[MAX_SOURCE+1]; char Destination[MAX_DESTINATION+1]; byte_union DataLength; char *Data; int byte_count = 0; int pass_flag = 0; int loop_count = 0; // ループ回数を出力するためのもので、ループ処理には使用されない // 条件が全て通ったときの pass_flag の値 const int PASS_FLAG_COUNT = 4; //ファイル読み出し FILE *fp; fp = fopen("pyonpyon.rh","rb"); if(fp == NULL){ printf("ファイル読み込み失敗\n"); exit(0); } // ファイルサイズ取得 fpos_t fsize = 0; fseek(fp,0,SEEK_END); fgetpos(fp,&fsize); fseek(fp,0,SEEK_SET); // ファイル終端まで読み出す while( byte_count < fsize ){ // データ読み込み変数初期化 memset(Magic,'\0',sizeof(Magic)); memset(Source,'\0',sizeof(Source)); memset(Destination,'\0',sizeof(Destination)); // 一連のファイルを読み出す fread(Magic,sizeof(char),MAX_MAGIC,fp); fread(Source,sizeof(char),MAX_SOURCE,fp); fread(Destination,sizeof(char),MAX_DESTINATION,fp); fread(&DataLength.byte_4,sizeof(int),1,fp); // pyonpyon.rh はビッグエンディアンだが、windowsはリトルエンディアンなので変換する change_byte_order(&DataLength); Data = (char *)calloc(DataLength.byte_4+1,sizeof(char)); fread(Data,DataLength.byte_4,1,fp); // バイトカウントに読み込んだバイト数加算 byte_count += MAX_MAGIC + MAX_SOURCE + MAX_DESTINATION + sizeof(int) + DataLength.byte_4; // 判定 if( Condition1(Magic) ) pass_flag++; if( Condition2(Source) ) pass_flag++; if( Condition3(Destination) ) pass_flag++; if( Condition4(Data) && Condition5(Data) ) pass_flag++; // ループカウント更新 loop_count++; // 結果出力 if( pass_flag == PASS_FLAG_COUNT ) printf("%2d回目:PASS\n",loop_count); else printf("%2d回目:REJECTED\n",loop_count); // メモリ開放 & paa_flag初期化 free(Data); pass_flag = 0; } fclose(fp); return 0; }
実行結果
1回目:PASS 2回目:PASS 3回目:PASS 4回目:PASS 5回目:PASS 6回目:PASS 7回目:PASS 8回目:PASS 9回目:PASS 10回目:REJECTED 11回目:PASS 12回目:PASS 13回目:PASS 14回目:REJECTED 15回目:REJECTED 16回目:PASS 17回目:PASS 18回目:PASS 19回目:REJECTED 20回目:REJECTED 21回目:REJECTED 22回目:PASS 23回目:PASS 24回目:PASS 25回目:REJECTED 26回目:REJECTED 27回目:REJECTED 28回目:REJECTED 29回目:PASS 30回目:PASS 31回目:PASS 32回目:REJECTED 33回目:REJECTED 34回目:REJECTED 35回目:REJECTED 36回目:REJECTED 37回目:PASS 38回目:PASS 39回目:PASS 40回目:REJECTED 41回目:REJECTED 42回目:REJECTED 43回目:REJECTED 44回目:REJECTED 45回目:REJECTED
選択問題6
まず簡単なシステム構成の前提ですが、ユーザ認証等の処理に使用する言語は PHP で、ユーザ情報を保存するデータベースは MySQL です。
上記の構成でユーザ認証のWebアプリを構築した場合、自分が一番最初に行うセキュリティテストは「SQLインジェクション」の対策が行われているかどうかのテストです。 SQLインジェクションを選択した理由は、攻撃者が手軽に実行できる攻撃でありながら、 開発者はフレームワーク等を使用していない場合は自ら対策を行う必要があるからです。
また開発者側がSQLインジェクション攻撃の存在を認識していても、サニタイズを忘れてしまう可能性もあります。 以上のような理由から、私は最初のセキュリティテストに「SQLインジェクション」の対策を行うことを選択しました。
FuelPHP でカラムを追加した時にやり忘れたこと
現在使用しているテーブルに新しくカラムを追加したのですが、 何故かコントローラからモデルオブジェクトを呼び出してカラムを使おうと思っても上手くいかなかったので、 同じ事象に遭遇した人の為に記事を書きました。
この問題はモデルのprotected static $_properties
がカラム追加をしても更新されない為に起こる問題でした。
protected static $_properties
はコマンドラインでモデルを作成すると自動的に作られます。
下記のように新規に追加したカラムをprotected static $_properties
に追加することで解決しました。
例
protected static $_properties = array( 'id', 'カラム名', 'created_at', 'updated_at' );
↓
protected static $_properties = array( 'id', 'カラム名', 'created_at', 'updated_at', '新規カラム名' );
無料サーバ Hostinger で FuelPHP を動作させる
Hostingerは無料で使用できるレンタルサーバです。
このサイトの他にもいくつか無料のレンタルサーバは存在しますが、大抵は広告がついていたりデータベースが使えなかったりと制限が多くあります。
しかし、このサイトにはそのような制限はありません。なおかつ、使いやすいダッシュボードに充実したサポートもついているのですごく気に入っています。 ただし、無料なのでページが表示される速度は物凄く遅いです。まぁ、お金を払えば100倍早く出来ますが。
もちろん、PHPも動作するので今回はこのレンタルサーバで FuelPHP を動作させてみようと思いました。 なお、FuelPHP のプロジェクトは実際に動作する状態になっていると想定します。
関係無いですが、Hostinger は残念ながら Ruby on Rails には対応していないようです。。。
まずはアカウント取得
1.まずはトップページにアクセスして、アカウント取得。
2.登録したメールアドレスに登録完了メールが来るので、アカウントを認証。
3.次に、表示されているページで一番左の Free コースを注文し、適当に設定。
4.これでサーバが使えるようになった、試しに登録したドメインにアクセスしてみる。(登録に時間がかかる場合もある)
ローカルの DB を Hostinger に移行する
Hostinger 上ではマイグレートをすることが出来ないので、ローカルでマイグレートしておいて DB をエクスポートします。
1.ローカルで phpMyAdmin を開き、プロジェクトに使用しているデータベースを選択して出てきたメニューから「エクスポート」をクリック。
2.デフォルトの設定のまま「実行」をクリックすると、SQLファイルがダウンロードされます。
3.Hostinger のダッシュボードから「MySQLデータベース」を選択し、適当な名前でデータベースを作成します。
4.データベースが作成できたらダッシュボードから「データベースの読み込み」を選択し、先ほどエクスポートしたSQLファイルを読み込ませます。
これで、データベースの移行は完了しました。
FuelPHP の環境設定をステージング環境に変更しておく
FuelPHP には下記の4つの環境が設定されています。
- 開発環境
- ステージング環境
- テスト環境
- 本番環境
ステージング環境とは本番環境でテストする時に使い、テスト環境は自動化テストを走らせる時に使うって考えています。 環境を変更するメリットは、環境ごとに DB に関する設定をする必要が無いからです。
詳しくは、ウェブ開発で大切な3つの環境を見てみると良いかも。
今回の場合はステージング環境だと判断したので、FuelPHPの環境をステージング環境に切り替えます。
切り替えるにはfuel/app/bootstrap.php
のFuel::DEVEROPMENT
をFuel::STAGING
に変更。
すると、下記のようになるはずです。
\Fuel::$env = (isset($_SERVER['FUEL_ENV']) ? $_SERVER['FUEL_ENV'] : \Fuel::STAGING);
ステージング用の DB 設定を編集
環境をステージングに変更しただけでは何も意味無いので、ステージング用の DB 設定ファイルを編集していきます。
fuel/app/config/staging/
にあるdb.php
の内容を、Hostinger で作成した DB の設定に変更しま。
なお、作成した DB の設定はダッシュボードの「MySQLデータベース」から確認できます。
FuelPHP のプロジェクトを Hostinger に移行する
FuelPHPに限った話ではないですが、フレームワークを使用したwebサイトは全体の容量が大きくなります。
ですので、Hostinger に FuelPHP のプロジェクトをアップロードするためにはサイトのファイルマネージャーでは無理なので、FTPクライアントを使用する必要があります。
今回私が使ったのは、FileZillaです。
使い方は超初心者向け!FileZilla(ファイルジラ)の使い方を参照してください。
FTPアクセスに関する情報は、ダッシュボードの「FTPアクセス」に記載されています。
アップロードするディレクトリは、public_html
です。
これで FuelPHP を動作させることが出来ると思われます。
何かわからないことや、間違っていることがあれば是非コメント下さい。
最後に気がついたのですが、本番環境にアップロードする時はpublic
以下をドキュメントルートに設定しましょう。
Rails c や PHP oil c が結構役立つ
今までweb開発をしていてあまりコンソールを使うことがなく、何のためにあるのだろうと思っておりました。 しかしここ最近頻繁に使うようになったので、自分の使い道をいくつか列挙しようと思います。
因みに、Rails c
は Ruby on Rails で、PHP oil c
は FuelPHP です。
==
や===
についての検証
同値判定は言語によって癖があり、Rubyでは1=='1'
はTRUE
だっけ??みたいなことがよく起こります。
そんな時、Rails c
などでコンソールを開いて実際に確認してみたりします。
メソッドの戻り値
FuelPHPでUpload::save()
は何を返すんだっけ?っと思ったことがあり、webページ上に
echo Upload::save();
と書いて表示させていましたが、
よく考えてみるとこれもコンソールを使えば簡単に検証できるということに気がつきました。
他にもモデルから返ってくる配列ってどんなんだっけ?だとか、こういう条件指定したら何が返ってくるのかなーって時に使ったりしてます。
テーブルにテストデータを挿入
コンソール上でモデルのインスタンスを取得し、保存すれば実際のテーブルにレコードが挿入されます。 当たり前のことですが、この使い方を知らなかった私はテストデータを挿入するためだけのアクションをわざわざ作っていました。
他にもレコード挿入時のバリデーションが正しく動作しているかの確認にも使えます。←テスト書け
パッと思いついたのはこれぐらいですが、要するに言語仕様の確認です。
まだまだweb開発初心者ですが上記のような当たり前のことを出来るようにし、開発効率を上げられるようになれたらと思います。
PHPでファイルアップロードがうまくいかない問題
最近 PHP のフレームワークである FuelPHP を使い始めたのですが、FuelPHP でファイルアップロードを実装しても特定のファイル(.wav
)のみエラーになってしまい困っていました。
少し調べてみると原因は.wav
であることが問題なのではなく、ファイルサイズが大きすぎることが原因だとわかりました。
しかもこの問題は FuelPHP の場合は下記のようなエラーが出てきてしまい、原因が特定しづらくなっています。(<form>
タグにenctype
がついてないぞって言われる)
Fuel\Upload\NoFilesException [ Error ]:
No uploaded files were found. Did you specify "enctype" in your
<form>
tag?
因みにMacで開発していたときは、ファイルサイズが上限を超えていたときはそもそも$_FILE
配列に何も入らないということも起きました。
上記のような事象が発生した場合はまずファイルサイズの上限を疑ってみるといいかもしれません。
php.ini
を編集して、アップロードサイズの上限を変更
原因がファイルサイズだと判明したので、php.ini
のupload_max_filesize
の値を大きくすれば解決すると思っていたのですが、どうやらこれだけでは上手くいかないようです。
このほかにもpost_max_size
とmemory_limit
の値も変更する必要があるみたいです、詳しくは下記のサイトを参照してください。
php.iniの設定を変えてもファイルをアップロードできないケース
アップロードサイズの上限については、php.ini
以外にも.htaccess
ファイルに記述しても問題ありません。
むしろphp.ini
ファイルの編集が出来ないレンタルサーバーもあるので、.htaccess
に記述しておいたほうが無難なのではないかと思います。
今回の事象で自分は.htaccess
ファイルの最後に下記のような記述を追加して対応しました。
なお、FuelPHP の.htaccess
はpublic/
にあります。
php_value memory_limit 40M php_value post_max_size 32M php_value upload_max_filesize 32M