souichirou のすべての投稿

[PHP]何日後などの日付を求める方法(加算)

PHP

当日から何日後を算出するのをよく使うので今更ながら覚書

今日(今)の求め方

何日後を求めるのは色んな方法があるが、変数によって算出を変えたい場合もあるので、単純な方法で計算している

strtotime($Today)で今日をUnix タイムスタンプに変換しているが、本来は strtotime(“now”) で構わないです。
こういう場合は日付を元に他の処理も実施したりするのでdate()関数で算出した値を基準とするようにしています。文字列を関数の中に書き込むのに慣れないのもありますが・・・

Unix タイムスタンプにした値に求めたい日付分のUnix タイムスタンプを足しています
3日後ならば 60秒*60分*24時間 = 1日 * 3日間
60日後ならば 60秒*60分*24時間 = 1日 * 60日間
といった具合です

これを覚えているとカレンダーを作るときに便利なんですよね。
今日から30日間の日付を作成したい場合にfor文で簡単にできます

[JavaScript]URLを元に階層(ディレクトリ名)を取得する方法

JavaScript

JavaScriptにおいて、アクセスされているURLを元に階層(ディレクトリ名)を取り出す方法です
ディレクトリ名によって処理を分けたい場合に使用しています

PHP版はこちら

方法

URLをスラッシュで区切られた部分で配列にします

PHPと違って配列には後ろから入るので扱いにくいかな

[PHP]URLを元に階層(ディレクトリ名)を取得する方法

PHP

PHPにおいて、アクセスされているURLを元に階層(ディレクトリ名)を取り出す方法です
ディレクトリ名によって処理を分けたい場合に使用しています

JavaScript版はこちら

方法

URLをスラッシュで区切られた部分で配列にします

これを使えばGETで値を渡されたようにも扱えるので便利です

AccessでCSVデータを取り込もうとしたら『データベースファイル’|1’が見つかりません』とでた場合の対処法

Office365

ルーチンワークといっても半年に2回あるかないかの作業でOfficeのAccess2013(アクセス)を使ってCSVを取り込んむ処理をしている
作業は前回のフォルダをコピーして名前を作業日に変更した上でやっているので処理に使うAccessも前回と同じものを使っていて違うのはCSVファイルの中身のみ

その作業の中でCSVの取り込みをインポートウィザードを使って実施しようとしたら『データベースファイル’|1’が見つかりません』とエラーがでてCSVが取り込めなかったときの覚書です

エラーまでの過程

・Accessで【外部データの取り込み】→【テキストファイル】
・CSVデータを指定して項目の設定をする
・最後の【完了】を押下するとエラーで取り込めない
AccessでCSVの取り込みエラー

いつもと同じ工程で作成したCSVデータだし、取り込みウィザードではデータは正常に表示されているのでCSVデータのエラーではなさそうだ。。。

原因

CSVデータを入れていたフォルダ名に落とし穴があった!

今回は2つの処理をしないといけなかったのでフォルダ名に2つの要件を明記していた
【A処理&B処理】という具合に

この【&(アンパサンド) 】が原因!
AccessでCSVの取り込みエラー002

アンパサンドを別の文字に置き換えると正常に取り込みが終了して処理を続けることができました
フォルダ名がダメなんだからファイル名にもアンパサンドを付けるのはNGだと思われます

ウイザードが動くんでいけると思い込んでいたが、コマンドプロンプトで&(アンパサンド)がついたフォルダに移動しようとしてもエラーがでるのと同じで、&(アンパサンド)がついていると裏側の処理で命令が途切れてしまっているんだろう

試しにCドライブ直下に『000&111』というフォルダを作成してみてください
コマンドプロンプトを立ち上げて

と打つと

と表示されます
&(アンパサンド)がついていることで、移動の処理は【000】までで終わって、次の処理をしようとしても【111】っていうコマンドは存在しないので、『移動も出来ないし、コマンドも存在しないよ』と2つのエラーが生じます

ということで、
ファイルやフォルダ名に&(アンパサンド)はつけないこと

WEBサイトのファイルをS3へ自動でバックアップする

Amazon Web Services

Sublime TextやAtome、Notepad++を使っていると、FTP接続して直接サーバー上のファイルを編集できるので、自宅のデスクトップPCやノートPCでちょっと編集することが簡単になってきました
ローカルにファイルを同期しなくてもできるので、「Aのサイトのスタイルシートを編集したい」「Bのサイトをスタイルシートを変更したい」というのがすぐにできちゃいます

しかし、サーバ側のファイルを直接編集しているのでローカルのファイルが最新である保障がなくなってしまい、サーバに障害が発生してまうと一大事!
Gitを使えばサイト自体のファイルはある程度復元可能ですが、コミットしていなければ・・・
バーチャルホストで運用していて、他のサイト同士で処理を統一するためのファイル(function.phpなど)をサーバー上の別の場所へ保存している場合もバックアップしておきたいものです

さらに、サーバ上でバックアップファイルを作成していてもバックアップファイルをダウンロードしていなければ元も子もないので、バックアップファイルは別の場所に保管しておきたいですよね。自動で

ということで、AWSのS3をバックアップ用のストレージとして利用してみます
S3は保存容量と転送容量に対して課金されますが、保存すること自体の金額はかなり安いです(1GBあたり3.729円)
保存したデータをダウンロードするときはちょっと高くなります(1GBあたり15.82円)

合計20GBのデータを保存しても、約80円
全ファイルの復元が必要になってダウンロードしたとしても、約300円

データを復旧できると考えれば安いものではないでしょうか
サーバにプログラムを仕込んでおけば自動でバックアップしてくれるので気を煩わす必要もありません

バックアップファイルを保存する場所を準備

既存のフォルダから直接ファイルをS3に送ってもいいですが、コマンドを間違えるとファイルを消してしまう可能性があるので、一旦別の場所にファイルをコピーします
※ファイルが2重で存在することになるのでサーバ自体の空き容量に気をつけてください

AWS コマンドラインインターフェイスの準備

AWSをコマンドラインで操作するためにAWSから提供されているツールを使用します

・概要
 https://aws.amazon.com/jp/cli/

・インストール方法
 http://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html

S3バケットの準備

GUI画面で作れるので難しくありません
ここでは『hoge-web-bk』としたとします

・バケットの作成方法の説明
 http://docs.aws.amazon.com/ja_jp/AmazonS3/latest/gsg/CreatingABucket.html

シェルスクリプトファイルの作成

準備は整ったので、あとはシェルスクリプトを作ってサーバに作業させるだけです

バックアップの要件として
・いつバックアップが作成されたかS3側で分かりやすくしたい
を考えました

自動でやっている分、いつS3へ保存されたのか目視で分かるほうが緊急対応の時に判別しやすくなるので戻り作業が減ります
S3バケットに保存する際のフォルダ名に日時を設定することにしました

cronを使って毎日バックアップを保存する設定にしています
毎朝4時に設定したとすると、バックアップで作成されるディレクトリ名は『2016102804』と日付の後に時間がついてS3へ保存されます

1ヶ月経過したらS3から削除するようにしていますので、10月28日に実施すると09月28日のデータがS3から削除されることになり、S3には1ヶ月分のデータが日付ごとにアップロードされていることになります

この設定はバックアップの必要性・データ容量を考慮して変更してください
容量が大きければS3のデータ保存利用料が増えていきます
画像ファイルを遠隔で修正することは少ないので、拡張子を指定して、画像ファイルは月次バックアップ
htmlやphp,css,jsファイル等は編集の頻度が高いので日時バックアップにするなど工夫次第でAWSからの課金量も抑えられます

ファイルを圧縮せずにS3へアップロードしていますが、特定のファイルだけ取得したくても圧縮ファイルのダウンロードが必要となるので、ダウンロードの際に発生する課金を考えたら個別の方がいいかなという理由です

cronの設定

バックアップ用のシェルスクリプトが出来上がりましたのでcronに設定を入れます

cronでの実行権限を与えます

cronに設定を追加します

あとは正常にバックアップされているか、料金が想像以上に発生していないかをしばらく注意してみましょう

全てのデータのバックアップは不要ということで更新されたファイルだけ随時バックアップしておきたい場合は、コピーの仕方を変更するだけで1時間ごとに変更があったファイルをS3へ保存していくなども可能です

[PHP]重要な文字列を暗号化して保管し、利用するときは復元する方法

PHP

重要な個人情報をフォーム等から受取り、データベースへ保存する際には気をつけなければいけません
社内のシステムであってもダンプデータを持ち出されれば個人情報が丸見えの状態で取り出すことができてしまいます

パスワードなんかは確認の際に利用するだけなのでハッシュ化して、保存されている値とPOSTされた値を比べればいいので復元する必要はありませんが、顧客の住所などを保存したい場合は後で再利用するので復元できる形で保存する必要がでてきます

PHPを使ってMySQLなどのデータベースに保存する方法をご紹介します

使用する関数は mcrypt

まずは暗号化する処理です

ここで暗号化は完了ですが、復元させるためにデータベースに保存する項目はIVキーと暗号化されたデータとなります
IVキーとは『単に暗号化ルーチンに異なる初期値を与えるためだけのもの』ということで、一緒に保存して構いません
重要なのはパスフレーズの方です。パスフレーズまで漏れると誰でも復元できてしまうようになります

今回はPHPの内部にパスフレーズを記述していますが、FTPサーバから不正侵入された場合にはファイルを直接参照されてしまいますので、サーバ内の外部からアクセスできない場所に文字列を保存したファイルを置いておき、includeなどで呼び出した方がセキュリティとしては高まります
例)
/var/etc/security/hoge など

データベースに保存するのはIVキーと暗号化されたデータになりますが、この2つの値はどちらともバイナリデータです
保存するにはカラムのデータ形式をバイナリに指定していてもいいですが、バイナリデータとして保存するとSQLで抽出した際の視認性が好きじゃないということでBase64でエンコードした値を保存するようにしています

バイナリーだとこんな感じに見えるのが
M�(���z��53�a

Bace64でエンコードすると
TaB/KMTUA/Z66scGNTMWsGE8RdrSgPwraNRtcWRLmCQ=

みたいになります

Base64でエンコードしたデータはデコードでそのまま復元できますし、カラムの形式もVARCHAR型で構いませんので難しいことを考えなくてもよくなります

Base64にエンコードするには

この値をデータベースに保存すれば暗号化処理の完成です

続いては復元の方法です

パスフレーズの設定を細かくするかどうかにもよりますが、そんなに複雑な処理もなく重要な情報を復元できる形で暗号化できますので、万が一に備えて暗号化を進めていくのもいいかもしれません

APNGやGIFアニメがブラウザで繰り返し再生されない場合の対処法

PHP

APNGやGIFアニメファイルをブラウザに表示させたときに、一度再生が終わってしまうとページをリロードしても繰り返し動いてくれないときがあります
これはWEBブラウザがキャッシュを利用してしまっているために再読み込みしても再生が終わった時点の画像を表示してしまうのが原因です

※GoogleChromeやInternetExplorerはAPNG形式のファイルはサポートされていませんのでそもそも動きません。。。

20161018_anime
画像自体に2回のループを入れていますが、再生が終わるとリロードしても繰り返されません

解決するには画像ファイルをキャッシュさせないことになりますが、WEBサーバ側でやってしまうと設定によっては対象のの画像ファイル拡張子(pngなど)全てがキャッシュされないようになり、それはそれで画像ファイルが毎回呼び出されるのでサーバ側の負荷があがってしまいます

そこで、対象の拡張子を全てキャッシュさせないのではなくて、対象の画像ファイルをキャッシュさせないようにします

一番簡単なのは、ページを読み込み直しされる度に拡張子の後ろにランダムな文字列をつけてあげることです
例)
hoge.png?123456

拡張子の後にクエスチョンマークを付けます。
リロードのたびに後ろの文字列を変更することでブラウザは同じファイルだと判断できなくなりますので読み込み直しが発生し、新規のファイルとして認識することでアニメーションが再生されるという方法です

後ろにつける文字列はどうするかってことですが、タイムスタンプを算出してつけてしまうのがユニーク値にもなりやすく手っ取り早いです

[PHP]の場合

[JavaScript]の場合

これを画像の埋め込みファイル名にセットすれば毎回違うファイルと認識されるのでキャッシュに左右されなくなります

[PHP]文字列にまとめた値を配列に変換する

PHP

[PHP]配列の値をまとめて文字列として結合するで紹介しましたが、文字列にまとめた値を配列として変換する方法です

今回も動物園を例えにします

元となったのは
$array_a = array(“たぬき”, “きつね”, “ねこ”);
A動物園には3種類の動物がおり、それをカンマ区切りの文字列としたため

$implode_arra_a = “たぬき,きつね,ねこ”;

となってデータベースへ保存されているとします。

この値をデータベースから取り出して表示させたい場合は配列に戻して処理をすることになります

使用する関数は explode(区切り文字,対象となる配列)

カンマ区切りで結合されたA動物園の値を配列に戻す

[PHP]配列の値をまとめて文字列として結合する

PHP

配列のデータをまとめて文字列として結合してしまう方法です

たとえば、動物園ごとに保有する動物のデータを取得してデータベースへ保存したい場合に

$array_a = array(“たぬき”, “きつね”, “ねこ”);
$array_b = array(“さる”, “ライオン”, “ねこ”,”たぬき”);
$array_c = array(“ペンギン”, “ゴリラ”, “きりん”,”サイ”,”ぱんだ”);

など、動物園ごとに種類も違えば数も違うし増減もある
そうなると、ある程度の量を予測してカラムとして確保するのも行として追加していくのもメンテナンスを考えると面倒です
そこで、配列の値を特定の文字で区切った形でまとめてしまえば1行のデータで格納できるようになります

使用する関数は implode(区切り文字,対象となる配列)

A動物園の値をカンマ区切りで結合する場合は

カンマ区切りで結合してしまうと、手作業で修正したCSVファイルを取り込む事案が発生することを考えた場合にちょっと危険です。
そこで、普段では発生する恐れのないであろう文字の組み合わせで区切ったりしています

セミコロンを3つ連続させる

まとめた文字列を配列に変換する方法も紹介しています
[PHP]文字列にまとめた値を配列に変換する

YouTube Player APIの使い方 – プレイヤーの動作を制御する篇

YouTubeのIFrame Player APIを使ったプレイヤー埋め込みに対して、任意の処理を加えていきます
YouTubeプレイヤー部分を利用するのではなく、独自のボタンを配置して、再生や停止、早送りを実装します

下記の動画に対して制御していきます

状態表示:


単語をクリックすると動画の制御ができます

・再生
・一時停止
・30秒早送り
・30秒巻き戻し
・次の動画へ
・前の動画へ

制御する部分の記述は

JavaScriptは下記になります

早送りと巻き戻しに関しては
getCurrentTime()で現在の再生位置が取得できるので、その位置を元に30秒加算・減算してseekTO()で移動させているだけです

これでYouTubeのIFrame Player APIを使ったプレイヤーの基本的な制御はできます
JavaScriptを使うといっても複雑な処理をしないといけないわけではないので使いやすいAPIです

また、JavaScriptを使うことによるメリットも大きいです
画面サイズに合わせてレスポンシブの処理を入れたいときはCSSで切り分けたりしますが、JavaSciptでブラウザサイズを簡単に取得できるので、その値を元に算出し、プレイヤーの準備の時に初期サイズを設定し、画面サイズを変更された場合もJavaScriptで挙動を取得してサイズを設定しなおせばいいだけです