スキップしてメイン コンテンツに移動

投稿

ダイソーで買った200円のドライバーセットでHDDを分解

HDDの処分 最近は個人情報の問題もあって、HDDを処分する前にちゃんとデータの消去を気にすることも多くなってきました。消去方法としては大きく分けて下記の3つがあります。 データ消去ソフトでフォーマット HDD内部のプラッタを物理破壊 データ消去を行ってくれる専門の業者や家電量販店(Sofmapやビックカメラで実施していると思います。費用発生。)に持ち込み。 データ消去ソフトでのフォーマットは簡単ですが、欠点として「フォーマットに時間がかかる」「セクタ破損などで中途半端に壊れたディスクのフォーマットができない」などがあります。 またHDD内部のプラッタの物理破壊については、HDDを分解するために、通常のプラスやマイナスドライバーではなく、星形ネジに対応したトルクスドライバーが必要とのこともあって、少し面倒です。 筆者は今回、今後もHDDの廃棄をするだろうなあと思い、思い切って自分で分解して廃棄することにチャレンジしてみました。(家電量販店に持って行くよりも安くできないかというどケチ丸出しですw) HDDの星形ネジ こんなやつです。ちなみに写真はSeagateのST2000DL003というHDDで撮影しました。 トルクスドライバー というわけで、分解のために Amazonでトルクスドライバー を探しました。 調べると T8のもだと使えそう とのことで、いろいろと物色。 セットのものとか T8一本で立派なやつとか 色々あったのですが、HDD壊すだけで800円かぁ(←どケチ)、と思って購入を躊躇。 ネット上で調べると100円ショップのダイソーでも、トルクスドライバーを販売しているとの情報をキャッチ!近所のダイソーに行って、探したところ星形のヘッド交換に対応した精密ドライバーセットがありました。 プラスが10種類、マイナスが8種類、六角が6種類、星形が6種類(今回ほしかったもの)のセットで、何とお値段税抜き200円!、税抜き200円!と安かったので、ダメもとで購入しました。 結論から言うと 買って大正解 でした。 ダイソーの精密ドライバーセット こんな商品です! 星形対応のヘッドを装着するとこんな感じ。ドライバーのグリップもゴムで滑らない様になっていて使いやす...

MySQLのinsertとupdate用のPDOのPrepared Statementを生成するPHPのプログラム

PHPでMySQLのinsertとupdateで使えるPDOのprepared statementを生成するプログラムを書いてみました。使用頻度の高そうなパターンのSQLを生成することを目標にしてプログラムを書きました。 SQLBuilderクラス メインとなるクラスです。SQLBuilderクラスの内部で使っているColumnインタフェースとColumnインタフェースを実装したBindableColumn、FixedValueクラスは、SQLBuilderクラスの内部のみで使用することを想定しているので、SQLBuilder使用時に意識する必要はありません。 <?php class SQLBuilder { private string $table; /** * @var Column[] */ private array $columns = []; public function __construct($table) { $this->table = $table; } public function add($column, $type): self { $this->columns[] = new BindableColumn($column, $type); return $this; } public function addFixedValue($column, $value): self { $this->columns[] = new FixedValue($column, $value); return $this; } public function buildStatementForInsert() { $targetColumns = implode(', ', array_map(fn(Column $column) => $column->getName(),$this->columns)); ...

複数の配列から要素を1つずつ選んで、すべての組み合わせを生成するPHPのプログラム

複数の配列から、要素を1つずつ選んですべての組み合わせを生成するプログラムをPHPで書いてみました。 ただし、組み合わせをすべて生成すると組み合わせ爆発を起こす可能性がありますので、使う際は本当に必要か慎重に検討してください。 <?php function iterateAllCombinations($sets, callable $callback) { $indexToKey = array_keys($sets); self::iterateAllCombinationsRecursive($sets, count($sets), $indexToKey, $callback, 0, []); } // 再帰的に呼ぶための関数本体 function iterateAllCombinationsRecursive($sets, $countOfSets, $indexToKey, callable $callback, $n, $generatedCombination) { if($n >= $countOfSets) { // この部分で生成された組み合わせを引数として、callbackが毎回呼ばれる。 $callback($generatedCombination); return; } $keyOfSet = $indexToKey[$n]; foreach($sets[$keyOfSet] as $e) { $generatedCombination[$keyOfSet] = $e; self::iterateAllCombinationsRecursive($sets, $countOfSets, $indexToKey, $callback, $n+1, $generatedCombination); } } 下記は、$callback内で生成された組み合わせをため込んだ場合の使用例になります。 <?php // 組み合わせを生成したい3つの配列 $sets = [ 'key1' => ['A', 'B', ...

PHPで呼び出されたメソッド階層を取得

デバッグ目的で、メソッドの呼び出された階層を取得したいときがあると思います。 PHPでは、Exceptionを生成してException::getTraceAsStringメソッドでStack Traceを取得する方法が簡単です。 下記にコードを示します。 <?php function extractTrace($endLineNumber, $startLineNumber=1) { $stackTrace = (new \Exception())->getTraceAsString(); $start = strpos($stackTrace, "#".$startLineNumber); $end = strpos($stackTrace, "\n#".($endLineNumber+1)); if($start !== false || $end !== false) { return substr($stackTrace, $start, ($end - $start + 1) ?: strlen($stackTrace)); } return $stackTrace; } 簡単な解説です。 引数でStack Traceを取得する範囲を指定できるようにしています。 \Exceptionを生成した個所からStack Traceが生成されるので、Stack Traceの1行目の"#0"の部分を取り除くためにデフォルトでは、$startLineNumberを1に設定しています。 $stackTrace = (new \Exception())->getTraceAsString();の部分を外部から引数で渡すのもありですが、毎回同じ処理を書く必要があるので、extractTrace関数内部に入れてあります。

PDOで指定したクラスにデータを割り当てて取得する方法

PDOで指定したクラスにデータを割り当てて取得するには、\PDO::FETCH_CLASSをMyPdo::fetch, MyPdo::fetchAllメソッドの引数に指定すれば簡単に実現できます。 通常はPDO::FETCH_ASSOCを指定して、array形式でデータを取得する方が手軽ですが、classでデータを扱うと、下記のメリットがあります。 arrayよりもclassでデータ取得した方がメモリ使用量が少ない arrayよりも、どんなデータを扱っているのかが明確になる それでは、\PDO::FETCH_CLASS使用例を下記に示します。 <?php $sql = <<<EOF SELECT id, name, weight, price FROM table_prodict EOF; $conn = new MyPdo(....); $conn->prepare($sql); $stmt = $conn->execute(); // クラスは第2引数で指定 $stmt->fetchAll(\PDO::FETCH_CLASS, Product::class); Porductクラスは下記を想定しています。 <?php class Product { public $id; public $name; public $weight; public $price; } \PDO::FETCH_CLASSの挙動についての補足です。 クラスを特に指定しないと、取得したカラムに対応したプロパティを持ったstdClassのインスタンスで結果が返ってきます。 指定したクラスに、クエリから取得したカラムに対応したプロパティがない場合(例えば、上記のProductカラムに$priceプロパティがない場合)は、動的にプロパティが定義されて取得したデータがセットされます。 \PDO::FETCH_PROPS_LATEを使うとプロパティにデータをセットする前に、クラスのコンストラクタが呼ばれます。クラスの事前処理が必要な場合に指定すると便利です。 クラスのプロパティ定義がprivateでも正しくデータはセットされます😲

PHPでarrayをgroup byする関数

通常はデータベース上でSQLを使ってgroup byをすれば十分ですが、下記のような場合プログラム側で実施するのもありです。 DBから取得したデータから別の複数の集計(group by)結果を得ることができる DBのgroup byの実行に時間がかかり、何度も似たような集計をDBに計算させるのは実行コスト(時間、CPU負荷)が高い 今回は汎用的にPHP側でgroup byを実行できるコードを書いてみました。 任意の複数フィールドで集計できるようにするため、多少コードが複雑になっています。 またkeyのencode/decode部分の処理で多少無駄があります。 <?php function groupBy(array $rows, array $groupByFields, callable $aggregate) { $groupByFieldsAsKey = array_flip($groupByFields); $map = []; foreach($rows as $row) { // キーになるならどんな関数でもOK。ここではjson_encodeを採用 $key = json_encode(array_intersect_key($row, $groupByFieldsAsKey)); $aggregatedRow = &$map[$key] ?? []; $aggregate($aggregatedRow, $row); } $result = []; foreach ($map as $key => &$aggregatedRow) { // キーをデシリアライズして、フィールドと値を集計結果の行にコピー $keyValue = json_decode($key, true); foreach($groupByFields as $groupByField) { $aggregatedRow[$groupByField] = $keyValue[$groupBy...