Posted on

Imagickを利用するにあたって

PDFファイルの1ページ目をイメージファイルjpgに変換するサンプルです。
imagickのサーバーへのインストールは、このブログからは除きます。
当初

$im = new Imagick();
//画像を生成したいPDFを読み込む
$im->readImage('hoge.pdf');
//特定のPDFのページ 0が表紙
$im->setImageIndex(0);
//サムネイルサイズ 640pxに収める
$im->thumbnailImage(640, 640, true);
//シャープ
$im->sharpenImage(0, 1);
//生成
$im->writeImage('out.jpg');

$im->destroy();

を元に関数を作成したのですが、
この記述では、階層が深いPDFを指定した場合は、エラーになるという致命的な問題が
潜んでいます。
そこで、ソースを

$im = new Imagick();
//画像を生成したいPDFを読み込む
$image = file_get_contents('/var/www/xxxx/xxxx/hoge.pdf');
$im->readImageBlob($image);
//特定のPDFのページ 0が表紙
$im->setImageIndex(0);
//サムネイルサイズ 640pxに収める
$im->thumbnailImage(640, 640, true);
//シャープ
$im->sharpenImage(0, 1);
//生成
$im->writeImage('/var/www/xxxx/xxxx/out.jpg');

$im->destroy();

で動くようになりました。
しかし、透明の箇所が真っ黒になるという不具合がありなおかつ
複数ページあるPDFと1ページのみのPDFでは動きが違うという問題にも直面
この難題を解決するのに、3時間程度要しました。
解決済みのサンプルがこちらです。

        $im = new Imagick();
        //画像を生成したいPDFを読み込む
        $image = file_get_contents('/var/www/xxxx/xxxx/hoge.pdf');
        $im->readImageBlob($image);
        $totalPage = $im->getImageScene();

        //サムネイルサイズ 640pxに収める
        $im->thumbnailImage(640, 640, true);
        //シャープ
        $im->sharpenImage(0, 1);
        // バックグラウンドを白にする。
        $im->setImageBackgroundColor('white');
        //特定のPDFのページ 0が表紙
        if ($totalPage != 0) {  // 複数ページの場合
            $im->flattenImages()->setImageIndex(0);
        } else {    // 単一ページの場合
            $im = $im->flattenImages();
        }
        //生成
        $im->writeImage('/var/www/xxxx/xxxx/out.jpg');
        $im->destroy();

以上です。

Posted on

JavaScriptトラップ集

業務上JavaScriptを使用していて、ハマったorハマりかけたポイントをまとめてみました。

1、indexOf(危険度:★★★☆☆)

文字列内に特定の文字列が存在するかを判定したい時に、
indexOf()を使用すると便利ですが、

 
 let tmpArr = '小谷翔平';
 let searchArr = '谷';
 console.log(tmpArr.indexOf(searchArr)); //結果:1 ⇒ 文字列の2文字目に存在

気をつけなければならないのは、
特定の文字列が存在しない時に返って来るのが、falseでは無く-1だという事です。

 
 let tmpArr = '小谷翔平';
 let searchArr = '鈴';
 console.log(tmpArr.indexOf(searchArr)); //結果:-1

PHPの同じような関数のstrposではfalseで返ってくるので、
業務で両方使っていると紛らわしいですね。

また、indexOfで特定の文字列が一番最初に存在する場合は、
0が返ってくるので、以下のような使い方はバグのもとになります。

 
 let tmpArr = '小谷翔平';
 let searchArr = '小';
 if(!tmpArr.indexOf(searchArr)) { //0だと通ってしまう
	//文字列が含まれない場合はなんらかの処理
 }

2、parseIntとNumberの違い(危険度:★★☆☆☆)

JavaScriptで文字列を数字に変換したい場合、
主にparseInt()、Number()の2種類の方法があります。

 
 let tmpArr = '1234';
 console.log(Number(tmpArr)); //結果:1234
 console.log(parseInt(tmpArr)); //結果:1234

両者の違いですが、parseIntの場合は数値以外の文字列が含まれる場合でも、
数字を抽出して返却してくれるケースがある事です。

 
 let tmpArr = '1234abc';
 console.log(Number(tmpArr)); //結果:NaN
 console.log(parseInt(tmpArr)); //結果:1234

詳しい事はこちらで。
このあたりはトラップが多いので、replace()等であらかじめ数字を抽出したうえでNumber()をかけるのが良さそうです。

 
 let tmpArr = 'abc1234';
 console.log(Number(tmpArr.replace('abc', '')); //結果:1234

3、JavaScriptとphpでの空配列の扱い(危険度:★★★☆☆)

JavaScriptとphpでは条件式での真偽値がちょくちょく違うので要注意。

//JavaScriptの場合
 console.log(Boolean([])); //結果:true
//PHPの場合
 var_dump((Boolean)[]); //結果:false

空の配列では真偽値が逆になります。
ここら辺も闇が深そうなので業務で両方使う場合は注意が必要そうですね。

4、JavaScriptのDate関連(危険度:★★★★☆)

JavaScriptではDateオブジェクトで日時を扱いますが、
こちらのページに詳しいように、
いろいろとトラップが多いので注意が必要です。

特に個人的にハマったのが、getMonth()の挙動です。

 
 let date = new Date('2019-02-04T03:24:00');
 console.log(date.getMonth()); //結果は2では無く、1

他にも、日付を得るのはgetDay()ではなくgetDate()とかいろいろと紛らわしいです。

Posted on

LodashのTemplateとsortByを使って並び替えと再利用に強いページを作ろう

フロントエンドの業務でAJAXでバックエンドと接続して内容を取得してデータを表示する、なんていう場面は多々あると思います。

ただ、AJAXで取得したデータを一つ一つ要素を作成して流し込んでいく事が面倒だったり、表示の並びなどはViewだけでちょっと触るだけで変更できればバックエンドの処理が減って良かったりします。

今回は、jQueryとJavaScriptの便利ライブラリ集Lodashのテンプレート機能とソート機能を使ってみたいと思います。

続きを読む LodashのTemplateとsortByを使って並び替えと再利用に強いページを作ろう

Posted on

deferredに感動したが、その感動を伝えきれない

「ボタンを押したらXMLから値をajaxで取ってきてフォームに入れて、その値を即座に10倍した値を別のフォームに入れたい」
という設定でコードを書く。


この画像の条件で「読め」を押すと、まず50の入っているフォームが2000に上書きされて、その下の10倍に20000が入るはず。

…。これで数日かかりました。なぜ読み込む前の値を読んでしまうのか。
「successコールバックに書く」という方法もなくはない。なくはないが
実際は「読み込んだ値をすぐ別のajaxで送信して」的なことが発生していた。

訳が分からなくなる…。

調べてみると、jQuery.Deffred と .then() という書き方があることに気づく。
ざっくりいうと、
「processedとかrejectedが返されるまで待機」
「$.ajaxはこっそりprocessedとかrejectedを返している」
「$ajax().then()のthen節にふたつfunctionを入れることができて、前半はprocessedのあと、後半はrejectedのあと実行される」
「.then()を直結連鎖させると上からprocessed側が実行されていく」…

とりあえず、.thenだ。と。


ajaxで値が変わるのを待ってから値をフォームから読んで書き直している。
これがやりたかったことだった。

まだまだ、使い方には研究が要りそうだ。

var deferred = new $.Deferred()

からの

return deferred.resolve().promise()


processedの結果を返したりとかもあった。

簡単なコードで連鎖に成功すると気持ちが良い。今はその感動だけ伝えたい…。

Posted on

公開フォルダーにないPDFファイルを表示する方法

PDFファイルアップロードの機能を作成する場合、公開フォルダでない場所にアップロードして、
そのPDFファイルをaタグで別タブに表示したい場合があります。
そこで、その場合のサンプルを記載します。

ファイル名やIPアドレスはご使用の環境にあわせてください。
main.php(表示したいファイルをフルパスでGETで渡す。)




download

表示したいフォルダのファイルをオープンしてPDFとして表示させるためのphpファイル
pdfdisp.php


以上です。試してみてください。

Posted on

アウトオブ眼中

ボタンをクリックしたら隠しdivの中のフォームをコピーして、
通し番号を発行して表に追加する、みたいな処理をよく書きます。
通し番号の入る場所は仮にダミー文字列(今回はQQQQ)を置いておいて、ボタンが押されたときの処理でまとめて書き換える感じです

何度か書いているうちにdata-属性に行番号を持たせることで、:lastから現在の最大行番号を把握し、
次の行番号を探る、なんてことをやるようになりました。
隠しフィールドよりずいぶんすっきり見えます。attrで持たせると文字列で保存されるので、取得時に0を引いて数値に解釈しなおすことをお忘れなく。 …【1】
追加するときだけじゃなくて削除にも役立ちます。$(“tr[data-no=’行番号’]”,”#fueruTable”).remove() で行ごと削れます。

ところで、これはこれで面倒なことが一つあって、これを実際submitしたとき。

QQQQはダミーフィールドなので使わないはずだし、何よりdataに関してforeachとか回すなんてことになると邪魔。
サーバー側にunset($_POST[‘data’][‘QQQQ’])を噛ませて長いことやってました。

ある時、formの閉じタグ位置を間違えて、隠しフィールドをformの外に追いやってしまったんです。
それでsubmitしたらどうなったかというと

QQQQがいない。
これはこれで何か問題がある気もするけれど、ただテンプレートとして置いておきたいだけで、そもそもsubmitする気のないフィールドは
そもそもform内に置かなければよかった!

考えてみれば当たり前のことなのに、長いこと気づかなかったのでついブログに書き出してしまいました。
submitしないフォームはformタグの外、アウトオブ眼中!他の事例でも使えたら使うつもりでいます。

Posted on

就職していた期間の合計を取得する方法

2000/01/08から2005/05/31まで就労
2006/01/08から2010/05/31まで就労
2011/01/08から現在も就労
の全就労日数を求める方法を紹介します。

データ構造サンプル
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(40) NOT NULL ,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1 ;
CREATE TABLE works (
id INT NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL ,
start_date DATE NOT NULL ,
retire_date DATE NULL DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1 ;

データの情報としては、
users.id:1,users.name:奥進太郎
works.id:1,works.user_id:1,works.start_date:2000/01/08,works.retire_date:2005/05/31
works.id:1,works.user_id:1,works.start_date:2006/01/08,works.retire_date:2010/05/31
works.id:1,works.user_id:1,works.start_date:2011/01/08,works.retire_date:null

1回毎の就労日数を求めるVIEWを作成します。
CREATE VIEW work_diffs AS
select works.user_id AS user_id,
(case when isnull(works.retire_date) then (to_days(curdate()) – to_days(works.start_date))
else (to_days(works.retire_date) – to_days(works.start_date)) end end) AS work_diff
from `works`;

上記VIEWをgroup byで合計すると、全就労日数が取得できます。
CREATE VIEW work_sum_diffs as
select work_diffs.user_id as user_id,sum(work_diffs.work_diff) as sum_work_diff
from work_diffs group by work_diffs.user_id;

usersとwork_diffsをJOINすれば、users毎の全就労日数を取得することができます。

Posted on

jQueryカラーピッカーspectrum.jsの使用方法

案件にて、色を扱いたいといった事があって、サクッと色を選べるプラグインが無いかなと探してみた所、spectrum.jsというイイ感じのプラグインが見つかりましたので、ご紹介したいと思います。

spectrum.js

DEMO

使用方法

このプラグインはjQueryに依存しますので、jQueryを先に読み込ませます。
そして、使用したいhtmlにspectrum.jsとspectrum.cssを読み込みます。
jquery.spectrum-ja.jsは日本語対応です。必要である場合は使用します。





inputにクラス名を付けておきます。


bodyタグの最後にscriptにてspectrumを呼び出します。
パレットに予め色を用意しておきたい場合は、paletteプロパティに配列で色を#RRGGBB形式で入力しておきます。

	jQuery(function($){
		$(".picker").spectrum({
			color: "#f00", //初期色
			showPalette: true, // パレット表示あり
			palette: [ // パレットで使う色を指定
				["#f00", "#0f0", "#00f", "#ff0", "#f0f", "#0ff"]
			]
		});
	});

IE11でsubmitしても値が反映されなかった時の対応

IE11を使用してシステムにsubmitした際、データが飛ばないので探ってみると、カラーピッカーを使用した後にinputのvalueに#RRGGBBの形で値が設定されていませんでした。

spectrumに用意されている`change`イベントでinputを#RRGGBB値に書き換えるようにしてやれば解決しました。

    jQuery(function($){
        $(".picker").spectrum({
			color: "#CF85A1", //初期色
			showPalette: true, // パレット表示あり
			palette: [ // パレットで使う色を指定
				["#CF85A1", "#CCD58D", "#94DAC0", "#A49CDF", "#ACA4E4"]
			],
            change: function(color) {
                $(this).val(color.toHexString());
            }
        });
    });

簡単な設定で細かい色指定ができるので、これは重宝しそうです。

Posted on

引越します

注:ブログ移転記事ではありません

4月後半となると、新生活に伴う引越もひと段落して、生活が軌道に乗った頃かと思います。
奥進システムでも、引越を進めています。
SVNからGitの引越で、事務所が物理的に動いているわけではないですけどね。

SVNからGitに乗り換えるにあたって、やることを調べていて、
最初こそおっかなびっくりやってたんですが、今となれば手順がはっきりしてきたので、
簡易版ではあるけれど、引越の為にやったことを今回のブログに書こうかと。

一応準備:
・Git Bashでプロジェクト展開先に入っておく
・他のGit操作がなんか面倒ならSourceTreeなど見繕っておく

1:Git Bash上、git-svnでSVNリポジトリをGitリポジトリに転換して抽出

git svn clone -s svn+ssh://[プロジェクトのアドレス]

SVNで使ってたtrunkが取り出される感じです。
もし最終リビジョンだけでいいなら -r HEAD をアドレスの前に付ければよし。

2:SVNに関する設定を抹消する

ここは色々と試していました。なんとかSVNと縁を切る方法はないかと。
SourceTreeから毎回「SVNブランチ作る?」と作れもしないのに聞かれるのにウンザリしていたものですから。

結局、2ステップにまとまりました。
プロジェクト直下.gitフォルダの中を操作するので、隠しフォルダの表示をお忘れなく

2-1:configファイルのsvn-remote “svn”以下項目を削除

このファイルに[svn-remote]で始まる項目があると思います。そこをテキストエディタで開いて消すだけです。

2-2:svnフォルダも丸ごと削除

もしかしたらもうちょっとうまいことやる方法あるのかもしれないですけれどね。
今のところ問題はないのでこちらもバッサリ削除。

3:ついでに.gitignoreとemptyファイルを用意しておく
.gitignoreは無視リスト、
毎回管理するかどうか聞くなとするファイルをリストしておけます。(詳しい書き方はご自分で。)
emptyファイル今こそファイルは入っていないけれど将来的にないと困るフォルダを抑えておくカカシみたいなもの。
gitはファイルのないフォルダを覚えていてくれませんからね…。

.gitignoreみたいにドット始まりのファイルをWindowsで作りたいなら、
ファイル名を”.gitignore.”とするといいみたいです。

もちろん、この変更は「Gitに」コミットしておきましょう。

5:あとは適当にリモートとつなげてプッシュ

まだローカルにGitリポジトリがある状態です。
チームで共有するために、リモートリポジトリを作ります。

とりあえずはこんなところです。
細かい設定をできる限り追うことなくSVNと縁を切る方法、
少なくとも、configファイル編集とsvnファイルの丸ごと削除だけは大事です。

Posted on

phpexcelのEXCEL列表記のテーブル作成

phpExcelにて列を指定して値を表示する際に、
EXCEL列の配列になったものをインデックスで指定して表示できれば、
横に長い表を作成する際に役に立つと思いこのテーブルを作成しました。


// EXCELの横座標を設定する。
$col1 = array("","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$col2 = array("","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$col3 = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$col4 = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$colArr = array();
$idx = 0;
foreach ($col1 as $val1) {
    if ($val1 == "") {
        foreach ($col2 as $val2) {
            foreach ($col3 as $val3) {
                $colArr[$idx] = $val1 . $val2 . $val3;
                $idx++;
            }
        }
    } else {
        foreach ($col4 as $val2) {
            foreach ($col3 as $val3) {
                $colArr[$idx] = $val1 . $val2 . $val3;
                $idx++;
            }
        }
    }
}
$col = 0;
$row = 1;
$sheet->setCellValue("{$colArr[$col]}{$row}", "日付");  // A1に「日付」表示
$col = 26;
$sheet->setCellValue("{$colArr[$col]}{$row}", "日付");  // AA1に「日付」表示
$col = 702;
$sheet->setCellValue("{$colArr[$col]}{$row}", "日付");  // AAA1に「日付」表示
$col = 1378;
$sheet->setCellValue("{$colArr[$col]}{$row}", "日付");  // BAA1に「日付」表示
$col = 16383;
$sheet->setCellValue("{$colArr[$col]}{$row}", "日付");  // XFD1に「日付」表示 ここがEXCEL横の最大値です。

PHPEXCELにて、列表記をインデックスで扱いたい時の配列です。