基本的な文法とかいろいろ
javascriptとは
javascriptとは主にwebのブラウザ上で動作することを目的とした言語らしい。
ただし、流行りだした当初はブラウザ上で右クリック禁止やずっと付きまとう広告等のかなりユーザーからしてみるとうっとうしいものに使用されたため世間からは糞言語呼ばわりされたそうな。。
しかし、GoogleMapの非同期通信で大活躍をしてからというもの手のひら返しで優遇されて現在はwebにはなくてならない存在に。
さらに近年ではNode.jsなるものが出てきて更なる進撃を見せているらしい(自分の中の偏見なのであしからず)
扱い方
変数から連想配列、ファイルの扱いとかふつうに扱うに必要なことをつらつら書いていく。
記述法
基本的にはhtmlファイルの中にscripitタグで囲って記述する方法と、別ファイルとしてスクリプトを書くのかのふた種類がある。
別ファイルの中
別ファイルに記述した場合は、別ファイルにそのままスクリプトを記述するだけ。
特に難しい事はなく、そのまま書くだけ。
ただし、htmlの中でそのファイルの呼び出しだけはしなくてはならない。
私自身はそうしなけらばならない場合を除いてこの方法を使う。
なぜなら可読性が高いし、処理ごとにまとめてファイル化してしまえばよりメンテナンス性が上がるから。
html内に呼び出しの記述をするだけだけど、特別な理由が無い限り一つの場所に纏めて呼び出しした方が余計なバグを生まなくてすむ。
また、大抵はheadタグ内に記述するかbodyタグ終了直後に記述するのが普通。
[html]
<html>
<head>
<script src="jsファイルへのパス"></script>
<script src="/hoge/fuga/imo.js"></script>
</head>
<body>
<h1>やっはろー?</h1>
</body>
</html>
[/html]
また、この方式はオープンソースのファイルを呼び出す時にも使う。
bootstrapとかtinymceとか使うときもサーバーやローカルにファイルを落としてそのパスを指定する方法と、web上のどっかのサーバーに置かれてるファイルを指定する事も出来る。
もちろんweb上のどっかのファイルを指定した場合、インターネットに接続してないと扱えないしページの読み込む速度も遅くなるので注意する事。
htmlファイルの中
scriptタグのなかで記述する。
こちらも大抵はheadタグの中かbodyタグの終了直後に記述することが多い。
どちらかに統一して記述していくのが基本で、そうしないと非常に可読性が悪い。
[html] <html> <head> <script> var name = "もじれつとがめん"; //idがtitle_nameのタグの中に変数nameを代入する $('#title_name').text(name); </script> </head> <body> <h1>やっはろー?</h1> <span id="title_name"></span> </body> </html> [/html]
この方法で記述するときは、別ファイルに分ける事が出来ない理由がある時か、そもそも分ける必要がない位コードの量がすくない場合でしか私は使わない。
でも、どんなにコード量が少なくても個人的には別ファイルで記述する方が後々助かるだろうしお勧めする。
変数の扱い
javascriptでは、変数はphpやperl等の型の宣言が不要な物。
どんな形式の物でも入るので特に悩む必要は無い、、はず。
変数の宣言の仕方は var 変数名 と記述するだけ。だが、スコープもあるので関数を扱う場合には注意する事。
[javascript]
//変数の宣言
var name;
//変数の初期化と代入 name = ''; name = 'もじれつとがめん';
//変数の初期化と宣言
var title = '';
var site_name = 'もじれつとがめん';
[/javascript]
変数の宣言をしたら、それ以降は var は不要なので注意。
また、スコープだが基本的には関数内で宣言した変数は関数の外では使用できない。
逆に関数の外で宣言した変数は関数内で使用できる。
そのため、変数の名前がかぶって値がめちゃくちゃにならないように気をつける事。
スコープは初めイメージしづらいと思うので、関数に囲まれてない変数はどこでも使えて、関数内の変数はその中でしか存在しないとだけは覚えておくと楽かもしれない。
どこでも使える変数の事をグローバル変数とも言う。
[javascript]
//どこでも使える変数(グローバル変数)
var global = 'もじれつとがめん';
//関数の呼び出し(実行) test();
//ログには 'がめんともじれつ'が表示される console.log(global);
//ログには存在しない変数を使おうとした為undifnedと表示されるはず console.log(local); //関数 function test(){ //この関数の中でしか使えない変数 var local = 'モジレツトガメン';
//コンソールログに 二つの変数をつなげて出力する。
console.log(global + local);
//グローバル変数を操作する。
global = 'がめんともじれつ';
} [/javascript]
関数の扱い
javascriptの関数はまぁphpとかperlと似たような扱い。
関数は宣言部分と、呼び出し部分の二つからなる。
普通は宣言より前に呼び出しは出来ないとおもうが、javascriptはソースをいったん全て読み込んだ上で処理を書かれた順番に実行するのでそこらへんは平気。
ただし、関数の中に関数を設定した場合は例外となるので注意。
[javascript]
//実行されずにエラーが帰ってくる imo();
//関数呼び出し //もちろん呼び出しが後でも動作する test()
//関数の中の関数は、上位の関数がよびだされた後なら使用可能に imo();
//関数の宣言 function test(){ //引数なしの関数 var count = 0; while (1){ count++; console.log('現在の数字は' + count); if ( count >= 10 ) break; }
//この関数は直接呼び出せない
function imo(){
console.log('ポテトはウメェぞ!!!');
}
}
[/javascript]
関数を普通に扱うにはこれくらい理解すれば大抵は作れる。
クロージャなるものもあるらしいので、いずれ追記するとしよう。
配列の扱いについて
javascriptの配列はあらかじめ"なんの"配列か宣言しておく必要がある。
連想配列なら"{}"で、普通の配列なら""で変数を初期化するか、変数の宣言時に"new Array()"で初期化する事で対象の変数が配列としての扱いになる。
他言語と違うのはその変数が配列用ので初期化する事でその変数が配列で扱えるところだろう(他言語をよくわかってないので偏見だけど、、)
配列とは
配列について初めての人はそもそも概念が理解できないと思うのでちょっと自分の解釈で解説。
配列の初期化
配列・連想配列と共に宣言と同時に代入するか、空の配列を渡す事で初期化できる。
なんにせよ、初期化してからじゃないと配列は扱えないので記述するときは初期化する事を忘れないように。
初期化には幾つか方法があって、目的によって使い分ける。
new Array
配列を new Array で初期化する方法。 [javascript] //配列として初期化 var array_1 = new Array();
//初期化と同時に要素をつくる // array_2は imo すし 3 ろぼっと を持つ配列 var array_2 = new Array('imo', 'すし', 3, 'ろぼっと');
//初期化と同時に任意の数の空の要素を生成する
var array_3 = new Array(25);
//array_3の要素数である 25 が表示される
console.log(array_3.length);
[/javascript]
このnew Arrayだが、ぶっちゃけ今はあまり使われてないらしい。
というのも、マシンスペックが無かった時代は配列をあとからpush等で付け足したりすると処理が重くなったためあらかじめ要素を必要な数だけ宣言しておく...
といった背景があった為、よくこの方法で必要な数だけを先に生成していたがマシンスペックが向上してきにする必要がなくなった為あまり使われない宣言の方法になったっぽい。
私もこの方法より後述の方法の方をオススメする。
を使って初期化
配列を を使って初期化する方法。
個人的にはこちらの方法を使用して配列を初期化するのをオススメする。
[javascript]
//配列として初期化
var array_1 = ;
//初期化と同時に要素を生成する
var array_2 = ['imo', 'すし', 3, 'ろぼっと'];
[/javascript]
こちらは今の一般的な宣言方法だと、思いたい。
特に要素数を気にしないならこちらをオススメする。
{} を使って初期化
配列を {} を使って初期化する方法。
この方法は普通に配列を使用する場合は使わない。
連想配列を扱い場合のみ使用するもので、普通の配列と違うのは自分でキー、つまり要素を呼び出す時の名前を指定したい時に使用する。
[javascript]
//連想配列として初期化
var array_1 = {};
//初期化と同時に要素を生成する var array_2 = {0:'imo', 1:'すし', 2:'3', 3:'ろぼっと'};
//こんな宣言もできる
var array_3 = {'susi':'すし', 'num':5, 1:'最初'};
[/javascript]
このように要素一つ一つに名前であるキーを命名して要素をつくる。
他の二つの方法と比べるとめんどくさいかもしれないけど、実はこれは連想配列を扱う上では必須なのでキチンと理解しよう。
普通の配列
配列は一つの変数(厳密にはメモリを確保した場所に対してだが)に複数の要素を名前をつけて代入する事。
普通の配列と連想配列の二種類あるけど、厳密には両方とも連想配列になっている。
所謂普通の配列は
[javascript]
//配列の宣言と同時に要素を入れてる。
var array_test = new Array('いも', 'susi', 'hoge', 1, 3);
console.log(array_test[0]);//いもが表示される
console.log(array_test[2]);//susiが表示される
console.log(array_test[4]);//数字の 3 いもが表示される
var array_test2 = new Array(20); //array_test2の要素数である、 20 が表示される console.log(array_test2.length); [/javascript]
このように特に連想配列のようなキーなるものを指定せずに生成できる。
しかし、これは厳密には以下の連想配列と同義である。
[javascript]
var array_test = {'0':'いも', '1':'susi', '2':'hoge', '3':1, '4':3};
console.log(array_test[0]);//いもが 表示される
console.log(array_test[2]);//susi が表示される
console.log(array_test[3]);//数字の 1 が表示される
//もちろん要素の上書きも出来る array_test[0] = 'imo';//いも を imo に上書き
[/javascript]
つまり、普通の配列とは自動で数字のキーが連番で割り振られたものとなる。
この連番の数字のキーの事を配列のインデックスと呼ぶ。
なので、普通の配列として扱う場合はjavascript側が勝手にインデックスを付けてくれるので、実は連想配列だと言う事を意識しなくても扱う事が出来るという訳。
ちなみに配列はプログラムを扱う場合には間違いなく絶対覚えるし、なによりこれが無いとお話しにならない。
ループでまわしたり、とりあえず保存したりとまさに基本中の基本。
もし本当にプログラム学び立ての人がこの記事に目を通して理解の手助けになれば幸いです。
連想配列
では普通の配列(そもそも連想配列の略称的な意味で配列なのだけど)の正体でもある連想配列はどういうものかというと [javascript] var array_test = {'hoge1':'ほげ1', 'imo':'いも', 'sport':'ダンス', 'num':1, '1':'数字'};
console.log(array_test['hoge1']);//ほげ1 が表示される console.log(array_test['imo']);//いも が表示される console.log(array_test[1]);//数字 が表示される
//要素の上書き
array_test['sport'] = 'バスケ';
[/javascript]
このように扱う。
要素のキーは数字でも文字列でなら一部の単語(そもそもシステムで使用されるような単語)をのぞいて何でも指定できる。
そしてキーは必ずシングルクォートかダブルクォートで囲う事。
数字は別に囲わなくても良いけど、あえて明示的にする事で不要なミスを防ぐ事が出来るので是非やってみよう。
そして指定したキーは中身である要素をよびだすのに使うので、中にある要素が一目でわかる命名にしないとコードをいじる他人も自分にも被害が及ぶので注意する事。
まぁそもそも変数の命名の気をつけるべきだけどね。
複雑な配列である多次元配列たち
これまで紹介した配列は キー:要素 の単純な形式だが、本来の連想配列の用途として複雑な関係にあるデーターを分かりやすく纏めるのに使われるが、大きなデータや大量の要素を持つのが想定される場合その関係が結びついている場合はデータの細かい単位一つ一つで配列を作っていったら途方も無いし管理も難しいし、なにより本当にその結びつきが絶対なのか証明が出来ない。
その為に配列の中に更に配列を作る事で要素同士の結びつきを証明すると同時に管理もしやすくするのが、多次元配列である。
多次元配列の扱い方
多次元配列は簡単に表すと、配列の要素の一つに配列を入れるという物で宣言のやり方や要素の代入もそんな感じで扱う。
また、多次元配列にも配列のインデックスのみで扱うものと、連想配列のキーを指定して扱う二つがある。
配列のインデックスを利用した多次元配列
先ほど紹介した普通の配列を多次元で扱う。
[javascript]
//宣言だけ
//配列の要素が配列の二次元の配列
var array_1 = [
['imo', '男爵いも'],
['windows', 'mac', 'unix']
];
//男爵いも が表示される console.log(array_1[0][1]);
//unix が表示される
console.log(array_1[1][2]);
[/javascript]
このように大元になる配列の要素を更に配列にする事で、多次元にする事ができる。
呼び出しも配列の中の配列を指定するには配列のインデックスで指定していく。
でも、多次元の配列にするならこのようなインデックスで扱う多次元配列はオススメしない。
可読性が最悪だし、正しいのかも分かりづらいと思うからだ。
多次元配列を扱うなら、後述の連想配列の方が良い。
また随時追記していく予定。流石に量があるからね...
cron で pg_dump を実行した時に失敗していた
cron で pg_dump を実行するとなぜか空の .gz.dumpファイルが生成されていた
調査するとcron内でpg_dumpのコマンドを実行する際にコマンドのPAHTが適用されていないみたい? なので、bin配下の実行ファイルをcronのコードの中で直接指定する事で解決した。
ぶっちゃけ当時は凄く焦った。 だってDBやれ色々バックアップを一日毎に保存させたかったんだけど、それが10日間くらいずっととれてなくて本当にビビった記憶がある...
cronとは
cronとは設定したスクリプト(コマンド)を自動実行するデーモンプロセスの事、らしい。 正直あまり詳しくは調べてない。。。 最初はコマンドを時間設定して自動的に実行してくれる、程度の認識で良いと思うけど近いうちに調べておこうと思う。 便利だもの。 非常に参考になるリンクだけ置いとく。 http://whitemix.net/89/cron.html http://miya0.dyndns.org/pc/settei/crontab.html
pg_dumpとは
PostgreSQLで使用するバックアップ用のライブラリ。 インストールして、コマンドを入れると指定のDBを全てdumpして出力してくれる。 その出力してくれた物を再度PostgreSQLに読み込ませるとバックアップをとった時点の状態が復元できる。 web上に文献はたくさんあるので、詳しくはそちらを調べるとして今回は省略する。 一応公式のドキュメントだけ... https://www.postgresql.jp/document/9.2/html/app-pgdump.html
解決法
まずはcronの編集画面を開く。
これじゃなくても、cronの実行ファイルを用意しても良い。
このcronの記述方式はどちらが良いとかは宗教戦争っぽいのでそちらは別の機会に。
[shell]
$ crontab -e
[/shell]
現状の確認。
自分のは時刻を合わせる指示と、問題のバックアップをとる指示の二つがある
[shell]
0 /2 * * * ntpdate ntp.jst.mfeed.ad.jp
1 23 * * pg_dump -U pgsql DATABASENAME | gzip -c > /home/hogehoge/dbbackup/date +\%Y\%m\%d
dbback.dump.gz
[/shell]
これの pg_dump ~ じゃ無くて /usr/local/bin/pg_dump ~ のように修正する。
このパス指定は各自のディレクトリや使っているosで異なるのでそこは適宜変えること。
ちなみに、このコマンドはpg_dumpでバックアップを出力してそれをリダイレクトの ">" で 指定したファイルに保存してる。
date +\%Y\%m\%d
dbback.dump.gz この部分は実行した日付を "YYYYmmdd"の形式で取得してファイル名に利用している。
[shell]
1 23 * * * /usr/local/bin/pg_dump -U pgsql DATABASENAME | gzip -c > /home/hogehoge/dbbackup/date +\%Y\%m\%d
dbback.dump.gz
[/shell]
これでキチンとpg_dumpの実行ファイルが呼び出されてコマンドが無事に実行された。
おわりに
少なくともこんな事例の記事は日本語で書かれていなかったので一日ハマってた。 私が間抜けなのか、相当レアケースなのか判別付かないけどコマンドが上手く実行できてなかったらここら辺を疑ってみる教訓にはなった。
クローリングとスクレイピングしてみる
クローリングとスクレイピング
この二つは要するに、"自動で任意のwebページのDOMから必要な情報(要素)を抜き出して取得する"という事。
クローリングは自動でwebページを巡回してDOMを入手する事 スクレイピングはDOMを操作して要素を取得する事
今回は定期的かつ自動的にwebページから必要な情報を取得続けたいのでこの二つを使ってbotみたいなのをつくる必要がある。
ツールについて
node.jsとかrubyとか色々あるみたいだけど、触ってないから多少読むのにも書くのにも時間がかかりそう... なので、なじみのあるphpで出来ないかなーと思ってググると
http://person-link.co.jp/web/964 http://liginc.co.jp/programmer/archives/4921
この二つのサイトが良さげでいい感じに纏められてた。
この二つは別々のphpのツールを使って実装しているので今回は Simple HTML DOM Parser を使って実装してみる事にする。
やり方
あんまり難しく無くて、手順的には
- phpのコードにツールのソースをインクルード
- 対象のurlをhtmlを読み込む関数に代入
- 各操作を実行するだけ
この三つの行程で大体出来るらしい。
参考になりそうなサイト達はこれ http://qiita.com/chkk525@github/items/3d3fba394514fa2c4529 http://d.hatena.ne.jp/Kshi_Kshi/20101228/1293508350
スクリプトにインクルード
あんまり説明がいらない気がするので簡単に...
[php] //ライブラリをインクルード require_once('simple_html_dom.php'); [/php]
対象のurlの読み込み
問題はココかもしれない。 というのも、欲しい情報があるページは毎日変わるので自動で毎日取得するには読み込むurlを動的に取得する手段が必要になる。
[php] $url = 'http://39mamon.com'; $html = file_get_html($url); //$htmlの中にはオブジェクトが入っている [/php]
読み込むと、代入した変数にはDOM構造のオブジェクトが入るので、あとはそれを欲しい要素を取得するだけだ。
各操作の実行
各作業については現状欲しい情報がまだどの要素に入っているのか特定してないからどれくらい時間を取られるか不明だけども、 そんなに難しいとは今のところは思えない。 単純にオブジェクトの中身をjavascriptっぽい記法で要素を切り出していくだけだから。
[php] //読み込んだhtmlの中からimgタグを取得して、そのsrcプロパティを取得する foreach($html->find(‘img’) as $element){ echo $element->src.’’; } [/php]
このようにfindで要素を指定してプロパティも指定する事で、目的の情報を取得していくらしい。 もちろん子要素を取得したり、id指定をして特定の要素を指定する事もできる。
[php] //idがcenter_dateのdivの中にあるpタグを取得する foreach ($html->find(‘div[id=center_date]’ as $div_center){ foreach($div_center->find(‘p’ as $p1){ echo $p1->plaintext; } } [/php]
これでやりたい事の大半は出来るはず。 後は必要に応じて調べて追記する予定。
----追記-----
2015/06/14
http://qiita.com/ka215/items/79c30e9c15ae0462f457
このサイトで他のライブラリも紹介してた。
どうやらこの二つの方が実装するには良さそう。文献も比較的新しいし。
tdとthタグにwidthやheightを指定しても反映されない??
そもそもwidthとheightを指定きないもの?
ちょっと25×40のテーブルで動的に列(横)要素を付け足していくものを作らないといけなくて、キチンとhtmlを触ってなかったからそのツケが来たのだろうかと思うこの頃。
最初に疑うべきはそもそもこのようなプロパティ・スタイルを受け付けないのか調べると、、、 "html td width"とかで検索すれば出てくるリファレンスでも普通に指定している... まぁ指定できないなんて聞いた事ないし何かのプロパティと相殺し合っているんだろうかね。
でも、html4からすでに非推奨らしいからプロパティでは指定しない方が良いのかもしれない。 スタイルでは指定して良いっぽい。調べてないからはっきりとは言えないが。
遭遇してる状態
thには行数を示す文字が入っているから平気なのか普通に表示されるが、問題は何も入っていない空のtdタグ達。 こいつらは1x1の超ちっちゃい要素として表示される。。。 [html] <table id="right_table"> <tbody> <tr> <th>1</th> <td id="r_id1" class="r0"></td> <td id="r_id2" class="r25"></td> <td id="r_id3" class="r50"></td> <td id="r_id4" class="r75"></td> <td id="r_id5" class="r100"></td> <td id="r_id6" class="r125"></td> <td id="r_id7" class="r150"></td> <td id="r_id8" class="r175"></td> <td id="r_id9" class="r200"></td> <td id="r_id10" class="r225"></td> <td id="r_id11" class="r250"></td> <td id="r_id12" class="r275"></td> <td id="r_id13" class="r300"></td> <td id="r_id14" class="r325"></td> <td id="r_id15" class="r350"></td> <td id="r_id16" class="r375"></td> <td id="r_id17" class="r400"></td> <td id="r_id18" class="r425"></td> <td id="r_id19" class="r450"></td> <td id="r_id20" class="r475"></td> <td id="r_id21" class="r500"></td> <td id="r_id22" class="r525"></td> <td id="r_id23" class="r550"></td> <td id="r_id24" class="r575"></td> <td id="r_id25" class="r600"></td> <td id="r_id26" class="r625"></td> <td id="r_id27" class="r650"></td> <td id="r_id28" class="r675"></td> <td id="r_id29" class="r700"></td> <td id="r_id30" class="r725"></td> <td id="r_id31" class="r750"></td> <td id="r_id32" class="r775"></td> <td id="r_id33" class="r800"></td> <td id="r_id34" class="r825"></td> <td id="r_id35" class="r850"></td> <td id="r_id36" class="r875"></td> <td id="r_id37" class="r900"></td> <td id="r_id38" class="r925"></td> <td id="r_id39" class="r950"></td> <td id="r_id40" class="r975"></td> </tr> <tr> <th>2</th> <td id="r_id1" class="r1"></td> <td id="r_id2" class="r26"></td> <td id="r_id3" class="r51"></td> <td id="r_id4" class="r76"></td> <td id="r_id5" class="r101"></td> <td id="r_id6" class="r126"></td> <td id="r_id7" class="r151"></td> <td id="r_id8" class="r176"></td> <td id="r_id9" class="r201"></td> <td id="r_id10" class="r226"></td> <td id="r_id11" class="r251"></td> <td id="r_id12" class="r276"></td> <td id="r_id13" class="r301"></td> <td id="r_id14" class="r326"></td> <td id="r_id15" class="r351"></td> <td id="r_id16" class="r376"></td> <td id="r_id17" class="r401"></td> <td id="r_id18" class="r426"></td> <td id="r_id19" class="r451"></td> <td id="r_id20" class="r476"></td> <td id="r_id21" class="r501"></td> <td id="r_id22" class="r526"></td> <td id="r_id23" class="r551"></td> <td id="r_id24" class="r576"></td> <td id="r_id25" class="r601"></td> <td id="r_id26" class="r626"></td> <td id="r_id27" class="r651"></td> <td id="r_id28" class="r676"></td> <td id="r_id29" class="r701"></td> <td id="r_id30" class="r726"></td> <td id="r_id31" class="r751"></td> <td id="r_id32" class="r776"></td> <td id="r_id33" class="r801"></td> <td id="r_id34" class="r826"></td> <td id="r_id35" class="r851"></td> <td id="r_id36" class="r876"></td> <td id="r_id37" class="r901"></td> <td id="r_id38" class="r926"></td> <td id="r_id39" class="r951"></td> <td id="r_id40" class="r976"></td> </tr> ・・・・・中略・・・・・ <tr> <th>25</th> <td id="r_id1" class="r24"></td> <td id="r_id2" class="r49"></td> <td id="r_id3" class="r74"></td> <td id="r_id4" class="r99"></td> <td id="r_id5" class="r124"></td> <td id="r_id6" class="r149"></td> <td id="r_id7" class="r174"></td> <td id="r_id8" class="r199"></td> <td id="r_id9" class="r224"></td> <td id="r_id10" class="r249"></td> <td id="r_id11" class="r274"></td> <td id="r_id12" class="r299"></td> <td id="r_id13" class="r324"></td> <td id="r_id14" class="r349"></td> <td id="r_id15" class="r374"></td> <td id="r_id16" class="r399"></td> <td id="r_id17" class="r424"></td> <td id="r_id18" class="r449"></td> <td id="r_id19" class="r474"></td> <td id="r_id20" class="r499"></td> <td id="r_id21" class="r524"></td> <td id="r_id22" class="r549"></td> <td id="r_id23" class="r574"></td> <td id="r_id24" class="r599"></td> <td id="r_id25" class="r624"></td> <td id="r_id26" class="r649"></td> <td id="r_id27" class="r674"></td> <td id="r_id28" class="r699"></td> <td id="r_id29" class="r724"></td> <td id="r_id30" class="r749"></td> <td id="r_id31" class="r774"></td> <td id="r_id32" class="r799"></td> <td id="r_id33" class="r824"></td> <td id="r_id34" class="r849"></td> <td id="r_id35" class="r874"></td> <td id="r_id36" class="r899"></td> <td id="r_id37" class="r924"></td> <td id="r_id38" class="r949"></td> <td id="r_id39" class="r974"></td> <td id="r_id40" class="r999"></td> </tr> </tbody> </table> [/html]
こんな感じ。構造的には単純だけど、これで表示すると全てのtdタグがつぶれた状態で表示される。 ここに直接widthとか指定しても変わらないし、cssでも相変わらず。 変化があったのは、tdタグの中に改行を入れてやると上手く表示されたけど根本解決ではないので別の方法を模索する。
結局選んだ方法は...
幅を指定するcssやプロパティではなく、cssでpaddingを指定する方法にした。 今のところ自分が知りうる方法ではこのやり方が一番スマートな気がする。
[css]
right_table > tbody > tr > td {
background-color: white; padding:10px; } [/css] さっきのhtmlにこのcssを適応させればtdが極端につぶれる事なくpaddingで指定した分だけ幅をもって生成された。 でもこれ以外にも方法はあると思うのでご存知の方が入れば是非ご教授願います。
ブログにやる気が出ない&プログラマとしてのスキルがなくて絶望してる人へ
とにかくブログを更新し続ける
この資料を見てほしい。
ここで言われている、通り雑記から技術ネタまでとにかくブログで公開し続ける事で少しずつ知見がたまるのが分かった。 さらにpv数が増えれば、記事にコメントする人が増えて自分のコミュニティが広がり知識も深まるといいこと尽くめだ。 また文章の書き方も鍛えられるだろう。
勉強会等での発表
二つめに言われている、勉強会での発表。 これは度胸もつくし自分がどのレベルなのかよくわかる良い機会だと私は感じた。 これで、少なからず業界で有名な人と知り合いになれる可能性があり仕事につながる事もありえるので非常に有益だとおもう。
まとめ
とりあえず、この資料をみてだいぶ意欲が湧いてきたのでブログから続けようと思いたった。 今だと、本当にスキルの無いプログラマーだからな... アプリも中途半端だし、まずは作ろう。
php+postgresqlでクエリ生成時の過ち
phpでユーザーからの入力をレコードを取得する際の条件に代入しようとした時に遭遇したミス。
当時のシチュエーション ・クエリを生成する際の条件文にユーザーの入力を代入しようとした為、記号が入力される可能性がある時 ・今回は いくつかの記号で発生した。発生した記号は以下の通り %(パーセント), _(アンダースコア), '(シングルクォート)
調査してみる
実際に生成されたクエリをコマンドラインから実行してみたらエラーを確認。
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE '%'%'; [/sql]
これを実行すると
見たいな状態に... この状態の時は入力を受け付けるのだけどいっこうに抜け出す事が出来ない
[sql] TEST'#nukedasenai!; TEST'#nannde?; TEST'#'''; ERROR: operator is not unique: unknown % unknown LINE 1: .. FROM test WHERE test.text LIKE '%'%'; ^ HINT: Could not choose a best candidate operator. You might need to add explicit type casts. [/sql]
どうやら ''';のようにシングルクォートを続けて3個連続で入力した状態でセミコロンを入れ実行するとようやくクエリとして認識してくれる模様。 おそらく%に挟まれたシングルクォートの解釈がおかしいために発生している予感がするためsqlでのシングルクォートの扱いを調査してみる。
sqlでのシングルクォートについて 簡単に言うとクエリの中で文字列として扱う際に囲むモノで 文字列として扱いたい対象をシングルクォートで囲むと文字列として扱われる。 シングルクォート以外にもダブルクォート(")で囲っても同じである。 ただし、一部の記号は文字列としては扱われない。 % _ はその代表で LIKE等で使う部分一致させるために使用される為特殊な解釈をされる。 またその様な特殊な解釈をする文字を純粋な文字列として扱う場合は特殊な文字の直前にバックスラッシュ(\) か エンマーク(¥) を置く事で文字列として扱う事が出来る。 これをエスケープという。
エスケープだ!これをシングルクォートにすれば解決じゃないかな?と思ったが...
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE '%\'%'; TEST'# onazikekkani...; [/sql]
同じ結果に... シングルクォートのエスケープは特別なのかと思って今度はシングルクォートのエスケープについて調べるとビンゴ!
シングルクォートのエスケープについて シングルクォートをエスケープして文字列として扱うには二種類ある。 ・ダブルクォートで囲む この方法はまんまその通り。
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE "%'%"; [/sql]
ってするだけ。逆にダブルクォートをエスケープして文字列として扱いたい場合はシングルで囲むだけ。
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE '%"%'; [/sql]
・シングルクォートを2個連続で置く この方法もまんまその通り。
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE '%''%'; [/sql]
ってするだけ。こちらもダブルクォートバージョンがある。
[sql] TEST=# SELECT * FROM test WHERE test.text LIKE "%""%"; [/sql]
このことからクォート系はこうやって文字列として扱える模様。
まとめ ・クォート系をエスケープして文字列として扱う場合はバックスラッシュではなく 同じクォートを2個置く シングルクォートを文字列としたいならダブルクォートで囲む。(逆も可)
phpでの日付の取得の色々
ね、ねむすぎる...
うとうとしながら仕事で対面したphpで日付操作について。
月末とか昨日とか未来とかを簡単に取得したい
てな訳で、phpのデフォルト関数 date()を使いたいと思います。
date関数
基本
引数に取得したい形式と項目を文字列で渡す
項目についてはphpであらかじめ決められた文字があるのでそれを渡してやれば解釈してくれる。
戻り値は 形式にそった日付が帰ってくる
実例
[php]
//今日の日付を年月日で出す $timeの中は 2015-01-14
$time = date( 'Y-m-d' );
//今日の日付 日本語でも出来る $timeの中は 2015年01月14日 $time = date( 'Y年m月d日' );
//今日の日付 Dで英語だけど曜日も出せる 2015-01-14 wed $time = date ( 'Y-m-d D' );
//今日の日時 hは12時間表記で時を、iは分を0詰めで、sは秒を0詰めで 2015-01-14 11:01:11 $time = date ( 'Y-m-d h:i:s' );
[/php]
応用
別の関数と組み合わせると色々便利な事が出来るようになる。
strtotime関数と組み合わせる事で、過去の日付を求めたりするのが楽になる。
strtotime関数の詳しい説明はこちらの記事の下部にある。
strtotime関数は一つの引数に日付の形をした文字列と指定した日数を渡すことで計算した時刻のタイムスタンプを返す。
具体的にはこんな感じ。
[php]
//日付の形をした文字列は省略できる。その場合は現在の日時がデフォルトになる。
//これは$timeの中には明日の日時がタイムスタンプ形式で入っている
$time = strtotime('+1 day');
//日付の形をした文字列を入れるとその日時から、指定の日時を計算出来る
//date関数の後はカンマでは無く必ずドットで"つなげる"。あくまで一つの引数として渡すから。
//$timeの中には先月の最初の日時が入っている
$time = strtotime(date('Y-m-01') . ' -1 month' );
[/php]
つまりstrtotime関数を使えば日付の計算が非常に楽になるが、タイムスタンプ形式なのでこのままでは良く無い。
それをdate関数で任意の日付の形に直す。
実例
[php]
//今日が2015年の1月15日だとして
//$timeには先月の最初の日時が入っている 14-12-01
$time = date( 'Y-m-d', strtotime( date('Y-m-01') . '-1 month' ) );
//$timeには昨日の日時が入っている 15-01-14
$time = date ( 'Y-m-d', strtotime( date('Y-m-d') . '-1 day' ) );
//$timeには先月末の日時が入っている 14-12-31
$time = date( 'Y-m-t' , strtotime(date('Y-m-01') . '-01 month') ); [/php]
このようにdate関数とstrtotime関数を使えば組み合わせで日付の操作は大体出来る。
終わりに
仕事で割と期間を区切って集計とかするようになったので良く使うようになった。
まじで扱いが楽だから便利だなー