Hina-Mode

とある呑んだくれエンジニアの気が向いた時に書く戯言

Microsoft ExcelでUTF-8、改行込みのCSVを正常に読み込む方法

CSVファイルにBOMをつけろ。

そのファイルをエクセルにドラッグ&ドロップすれば終わりです。
今まで自分でよくやっていた手法はデータ→テキストファイルからファイルインポートをする形式だったのですが、
その方法だとどういうわけか改行が入った文章を仮にクォートで囲っていたとしても正常に読み込むことができず四苦八苦しておりました。

BOMつけて、そのファイルをそのまま読めばどうやら別ロジックで別解釈してくれるようです(なんでだよ…

ほんと、過去何回も検索してその度忘れて、毎回謎に時間を取られてキレそうになったので、いい加減備忘録として登録した次第です。
皆様も良いエクセルとのお付き合いを。

Cordova androidのバージョンを7.0以降に上げたらfirebaseのプラグインでエラーが発生した問題の解決法

以下を参考にしました。

build failed with android 7.0.0 Error: ENOENT: no such file platforms\android\res\values\strings.xml' · Issue #13702 · ionic-team/ionic · GitHub

plugins/cordova-plugin-firebase/scripts/after_prepare.jsを以下のように直接書き換えることで対応が可能なようです。

- stringsXml: ANDROID_DIR + '/res/values/strings.xml'
+ stringsXml: ANDROID_DIR + '/app/src/main/res/values/strings.xml'

cordova androidのバージョンを6から7以降にすることで、ディレクトリ構成が代わり多くのプラグインでエラーが発生しそう…

CordovaでAndroidのbuildをする時、`Execution failed for task ':app:processArm64DebugResources'`というエラーが吐かれた場合の対処法

取り急ぎの自分用覚書、メモになります。

2018/03/20頃よりandoird版のビルドエラーが起きるようになりました。

いろいろ検索して見つけた結果が以下になります。

参考:https://github.com/arnesson/cordova-plugin-firebase/issues/610#issuecomment-374941040
https://stackoverflow.com/questions/49208772/error-resource-androidattr-fontvariationsettings-not-found

platforms/android/app/build.gradleに以下を記述します。
※該当ファイルが存在しない場合はplatforms/android/build.gradleに記述します。

configurations.all {
   resolutionStrategy {
       force "com.android.support:support-v4:27.1.0"
       force "com.google.android.gms:play-services-ads:11.8.0"
       force "com.google.android.gms:play-services-base:11.8.0"
       force "com.google.android.gms:play-services-gcm:11.8.0"
       force "com.google.android.gms:play-services-analytics:11.8.0"
       force "com.google.android.gms:play-services-location:11.8.0"
       force "com.google.android.gms:play-services-basement:11.8.0"
       force "com.google.android.gms:play-services-tagmanager:11.8.0"
       force 'com.google.firebase:firebase-core:11.8.0'
       force 'com.google.firebase:firebase-crash:11.8.0'
       force 'com.google.firebase:firebase-auth:11.8.0'
       force 'com.google.firebase:firebase-common:11.8.0'
       force 'com.google.firebase:firebase-config:11.8.0'
       force 'com.google.firebase:firebase-messaging:11.8.0'
   }
}

上記を記載後、再度ビルドすることで正常にビルドが通るようになりました。

FuelPHPの非同期処理パッケージを(ちょっと前に)自作したので改めて紹介します

FuelPHP Advent Calendar 2015 の17日目を担当します @hinashiki です。よろしくお願いします。
先日は12日目の記事も担当させていただきました。

去年、今年あたりにかけて、FuelPHPのパッケージを幾つか作成したので、一つだけ簡単にさせていただきます。

作成したものはFuelPHPで動かす非同期処理のパッケージです。
既に同様のパッケージについては他の方も作っていらっしゃったのですが

  • 自分のアプリ要件的にbeanstalkを入れるのが難しかった
  • Daemon化するのに別ファイルが必要だった

などの理由から見送らせて頂き、結局自作することにしました。

概要

実際のパッケージはこちらです。
packagistにも入ってますのでcomposerでinstallできます。
一応必要な案内は一通り(拙いですが)README.mdに記載してあります。

尚、利用前提条件として

  • ORMパッケージが利用出来る
  • DBが利用できる(MySQLでのみ、現状は動作確認してます)
  • Cronが利用できる(非同期処理の定期実行のため)

が必要となっています。

使い方

キューの挿入はModel_TaskQueueのsave_queueを利用します。

\Model_TaskQueue::save_queue(
    "Static::method",
    array($arg1, $arg2 ...)
);

第一引数にはstaticなクラスメソッド名を、第二引数には該当メソッドに渡す引数を配列で渡します。
その他の引数は後ほど説明します。
データはDBにINSERTされます。

で、実際のキューの実行はtaskとして処理します

php oil refine queue

実行時、溜まっているキューをDBのID順に引っ張って処理します。
1 taskにつき処理するキューは1つです。

並列処理したい場合にはcronで数秒おきに実行をしたり、複数サーバで処理したりすると良いかもしれません。
例)6秒おきにキュー処理したい場合(1分10回処理)

for i in {1..10}; do FUEL_ENV=production php oil refine queues &> /dev/null & sleep 6; done

オプション説明

上記は飽く迄基本処理であり、「もう少し細かい設定をしたい」場合のオプションが幾つか存在します。
3つほどピックアップして説明させていただきます。

並列処理の限界数指定

先の例の用に数秒に1回処理を抽出すると、サーバ側でタスク処理だけでパンクしてしまう事も、当然あります。
そこで本パッケージでは「1サーバで同時に動かせる限界数」を設定しています。
例) 同時処理限界数が3の時、4つめを動かした時の挙動

$ php oil r queue &
$ php oil r queue &
$ php oil r queue &
$ php oil r queue 
queue limit over.
$ 

という感じで、処理が開始される前に現在処理しているキュー数を確認し、負荷調整を行うことができます。

キューの優先順位の設定

キューには優先順位がつける事が出来ます。

Model_TaskQueue::save_queue() の第四引数で指定ができ、デフォルトは100です。
仮に優先処理したいキューに99などをあてておくと、デフォルトより優先的に処理する事が可能です。

キューの種別単位の同時実行数制限

Aの処理は2つ同時に実行したくない、Bの処理は4つまでしか実行させたくない、などの複数要件が重なる際に有効なオプションです。

config/queue.php に duplicate_type という指定ができ、

'duplicate_type' => array(
  1 => 1, // Aの処理
  2 => 4, // Bの処理
),

と設定すると、Aの処理は1つ、Bの処理は4つの同時処理が限界となります。
※この設定値は並列処理の限界数指定の影響を受けるため、限界値の設定はそれぞれ調整する必要があります。

尚、この種別設定は Model_TaskQueue::save_queue() の第三引数で指定できます。

まとめ

という感じでざっくりしたパッケージを造りました。
パッケージ作るというと
「全員に見られるし恥ずかしい」
「突っ込まれるの怖い」
「後々までの運用に責任持てない」
という不安もあるかと思いますが、出せばどうにかなるという適当感で私は出しちゃってます。

で、こうして外に出しておくと、自分の他の案件の作成時に使い回せますし、
「あー、こういうのないかなぁ」という他の人達の検索にももしかしたらヒットして、そこで役立つこともあるかもしれないので
どんどん外に出していきましょう(個人的にも楽したいのでそうして欲しいです(笑



この投稿は FuelPHP Advent Calendar 2015 の 17日目の記事です。

【FuelPHP】ORMパッケージのObserver機能を使ってユーザ作成時にIPを自動付与する

FuelPHP Advent Calendar 2015 の12日目を担当します @hinashiki です。よろしくお願いします。
普段は少人数で自社サイト運営をしながら呑んだくれたりマンガ読んだりアニメ観たりしております。

今回は掲題にあるとおり、DBへのレコード挿入時にObserver使えば便利だよ、という事を簡単に紹介します。

そもそもObserverってなんぞや?

ざっくりと説明しますと、DBへのINSERT, UPDATE時に何かしらのフックをいれることが出来る機能のことです


はじめに - Obervers - Orm パッケージ - FuelPHP ドキュメント

イベントベースのシステムは、特定のイベントに動作を追加できるようにします。 イベントが観測されると ORM は自動的にそれらを行うためには何があるのかどうかを確認するために追加されたすべてのオブザーバを呼び出します

と書いてありますが、要するに

  • INSERTの前後
  • UPDATEの前後

に特定動作を追加できるよーってことです。

では具体的にどんな感じで使うのか

上記の機能を使うためにはORMパッケージを入れる必要があるので、configファイルから設定を追加しましょう。

'always_load' => array(
    'packages' => array(
        'orm',
    ),
),


さて、では実際にコード記述に入ります。
試しに「usersテーブルにINSERTをしたら作成日時が自動的に保存される」という部分を作ってみます。

Modelの用意

fuel/app/classes/model/user.php を用意します。

class Model_User extends \Orm\Model
{
	protected static $_observers = array(
		'Orm\\Observer_CreatedAt' => array( // 実行内容が記述されているクラス名
			'events' => array('before_insert'), // INSERTの前に実行する
			'mysql_timestamp' => true, // php側の時刻ではなくmysql側の時刻を参照する
			'property' => 'created_at', // 保存するテーブルのカラム名
		),
	);

	protected static $_table_name = 'users'; // 保存するテーブル名
}

Orm\ModelクラスをextendsしたModelクラスを用意し、usersテーブルにはcreated_atカラムを用意します。

実行

あとはこのModelを使ってINSERTをすればOKです。

# Modelを使ってINSERT
$new = new \Model_User();
$new->property = 'something';
$new->save();

# DBクラスを使ってINSERTするとcreated_atには何も入りません。注意。
$query = DB::insert('users');

もう一歩進んで、本題

本題に戻りまして、IPアドレスの自動挿入についてご説明しましょう。
先ほどの「timestampを突っ込む」という本処理を実行していたのはOrmパッケージが持つObserver_CreateAtクラスでした。
では今度は「ip_addressを取得する」という本処理を自分で書いて持ってみましょう。

Observer_IpAddressの用意

fuel/app/classes/observer/ipaddress.php を用意します。

class Observer_IpAddress extends Orm\Observer
{
	public static $property = 'ip_address'; // デフォルトのカラム名
	protected $_property; // カラム名保持用プロパティ

	/**
	 * プロパティ名の変更があったらここで出来るよ的な処理
	 */
	public function __construct($class)
	{
		$props = $class::observers(get_class($this));
		$this->_property = isset($props['property']) ? $props['property'] : static::$property; 
	}


	/**
	 * 各イベント名機能。ここではINSERT前に取得したいのでbefore_insert()としてます
	 */
	public function before_insert(Orm\Model $Model)
	{
		if(is_null($Model->{$this->_property}))
		{
			$Model->set($this->_property, \Input::real_ip()); // IPアドレス入れ込む本処理
		}
	}
}
Modelへの記述追加

Observerを作成したら、先ほどのModel_Userの$_observersにObserver_IpAddressを追加してあげます。

	protected static $_observers = array(
		'Orm\\Observer_CreatedAt' => array(
			'events' => array('before_insert'),
			'mysql_timestamp' => true,
			'property' => 'created_at',
		),
		// 追加
		'Observer_IpAddress' => array( // 実行内容が記述されているクラス名
			'events' => array('before_insert'), // INSERTの前に実行する
			'property' => 'ip_address', // 保存するテーブルのカラム名
		),
	);

これで準備は完了です。
あとはModel_Userを通じてsaveを実行してあげれば、IPアドレスがusers.ip_addressに追加されます。

まとめ

いかがでしたでしょうか。Observerは他にも

  • 直前にValidationを実行する
  • 投稿された座標情報を自動取得して保存しておく
  • 論理削除用にとりあえずdeleted = 0を仕込んでおく

など、色々な使い方が出来ます。覚えておくと便利な機能だと思いますので是非活用してみてください。




この投稿は FuelPHP Advent Calendar 2015 の 12日目の記事です。