MySQLでFOREIGN KEYを張る際に形式が正しくないと怒られた時の対策

下記のようなSQLを実行したところ

CREATE TABLE `a` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `b` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`a_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`a_id`) REFERENCES `a` (`id`)
);

このようなエラーが発生した

ERROR 1005 (HY000) at line 30: Can't create table `schemaspy_tmp`.`b` (errno: 150 "Foreign key constraint is incorrectly formed")

これは外部キー制約で指定した元の型と先の型に差異があるために発生しているので統一してあげる

CREATE TABLE `a` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `b` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`a_id` SMALLINT(6) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`a_id`) REFERENCES `a` (`id`)
);

何年も動いているカオスシステムではこういうことが起きるのである

Qiitaの全記事を一括編集する

Qiitaの全記事を取得して、特定の文字列が含まれていたら編集みたいな処理をしたり、記事を移行した場合の移行先リンクの追加などを行う時にこんな感じでできると思います。

<?php
class Qiita {
const ITEM_LIMIT = 20;
private $token;
public function __construct($token) {
$this->token = $token;
}
public function getInfo() {
return $this->getRequest('https://qiita.com/api/v2/authenticated_user');
}
public function getItems($page) {
return $this->getRequest(
'https://qiita.com/api/v2/authenticated_user/items?' .
http_build_query(['page' => $page, 'per_page' => self::ITEM_LIMIT])
);
}
public function patchItems($id, $data) {
return $this->patchRequest('https://qiita.com/api/v2/items/' . $id, $data);
}
private function patchRequest($url, $data) {
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token,
'Content-Type: application/json',
],
]);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result);
}
private function getRequest($url) {
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token,
'Content-Type: application/json',
],
]);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result);
}
}
$token = 'mosura';
$setouchi = new Qiita($token);
$max = ceil($setouchi->getInfo()->items_count / Qiita::ITEM_LIMIT);
$result = "";
for ($i = 1; $i <= $max; $i++) {
echo PHP_EOL;
foreach ($setouchi->getItems($i) as $remoteItem) {
$url = "https://blog.sioyaki.com/entry/" . date("Y/m/d/His", strtotime($remoteItem->created_at));
print_r($setouchi->patchItems($remoteItem->id, [
"body" => "Qiita:Teamへの移行のため、この記事は " . $url . " に移行されました。この記事は移行のために一定の期間を置いて削除します。",
"tags" => [["name" => "Hatena", "versions" => ["0.0.1"]]],
"title" => $remoteItem->title,
]));
}
}
echo PHP_EOL;

今回Qiita::Teamに移行するには記事を全部削除しなければいけないようだったので、一括して削除する前に移転先を記載しました。

Qiitaの記事をMovableType形式でエクスポートする

ポイントはCONVERT BREAKS: markdownってところでした。これをしないとちゃんと記事が展開されない。

<?php
class Qiita {
const ITEM_LIMIT = 20;
private $token;
public function __construct($token) {
$this->token = $token;
}
public function getInfo() {
return $this->getRequest('https://qiita.com/api/v2/authenticated_user');
}
public function getItems($page) {
return $this->getRequest(
'https://qiita.com/api/v2/authenticated_user/items?' .
http_build_query(['page' => $page, 'per_page' => self::ITEM_LIMIT])
);
}
private function getRequest($url) {
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token,
'Content-Type: application/json',
],
]);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result);
}
}
$token = 'token';
$outputPath = '/home/user/Downloads/qiita.html.txt';
$setouchi = new Qiita($token);
$max = ceil($setouchi->getInfo()->items_count / Qiita::ITEM_LIMIT);
$result = "";
for ($i = 1; $i <= $max; $i++) {
echo PHP_EOL;
foreach ($setouchi->getItems($i) as $remoteItem) {
echo "+";
$body = "";
$body .= "AUTHOR: user\n";
$body .= "TITLE: " . $remoteItem->title . "\n";
$body .= "BASENAME: " . date("Y/m/d/His", strtotime($remoteItem->created_at)) . "\n";
$body .= "STATUS: Publish\n";
$body .= "ALLOW COMMENTS: 1\n";
$body .= "CONVERT BREAKS: markdown\n";
$body .= "DATE: " . date("m/d/Y H:i:s", strtotime($remoteItem->created_at)) . "\n";
$body .= "-----\n";
$body .= "BODY:\n";
$body .= $remoteItem->body . "\n";
$body .= "-----\n";
$body .= "--------\n";
$result .= $body;
}
}
echo PHP_EOL;
file_put_contents($outputPath, $result);

脱AppleをしてLinuxに鞍替えしてからクラウド主体になり身軽になった

f:id:setouchinatsu:20190326135159p:plain

Apple製品の価格高騰に伴い、Macbookを買い換えるだけで破産を考えるほどになり、次の時代を生き抜くために3年くらい前からApple製品を売却してApple製品以外のものに置き換えを進めてきました。(それでもiPad大好きマンはやめられないが。)

しかし副産物として、ハードの置き換えをしていく中で、クラウド化を強いられたことで生活が簡素化され、ハードに支配されない生活になりました。さながらデジタルミニマリストで御座います。

この記事では決してMacが使いにくいって言いたいのではなくて、もしお金が無限にあるなら私は全身Appleに染め上げたいと今でも思ってます(Macである必要性がないって話をしています。)今回はストレス発散がてら、私の自己満足に付き合ってくだされ。

Macユーザーの頃はローカルマン

f:id:setouchinatsu:20190326140330p:plain

Macbookの頃はMacの中に開発ファイルとか書類とか写真とか全部入っていて、それをクラウド(Dropbox、iCloud Drive、Google Driveなど)に同期するって形。まずハードにデータがあって、クラウドはそれらをバックアップしたり他の端末でも見れるようにするという存在。Appleとしてもそんな方向性で開発してるんじゃないかと思います。Macbookでしていた作業を、iMacで行う時はまずローカルのデータの同期を取ってという感じです。

Macはとても高価なので用途に合わせてハードを用意すると破産する。したがって、ちょっと外出する時も最強のメインMacbook Proを持ち運んでいました。せっかく学校卒業してランドセル背負わなくて良くなったのに、今度はとても重いりんごを背負わなきゃいけないなんて。。

(Macでもクラウドのみで完結させることはできる。例えばicloud.comでしたっけ、あそこでブラウザで動作しますよね。でもその使い方だったら別にLinuxでもいいと思います。Macの強みはmacOSにインストールされているアプリケーションの強力なデータ連携なのでそれを使わないのはもったいない。)

Linuxユーザーになってからはクラウドマン

f:id:setouchinatsu:20190326135335p:plain

Macで動いていたようなアプリケーションはほとんど動きません。似たようなアプリ入っていますけどMacに最初から入っているアプリケーションには及びません。

したがって私は、強引な例えをするとLinuxノートパソコンを、ターミナル付きChromebookとして使っています。

開発系以外の事をする時はChromebookみたいに使う

f:id:setouchinatsu:20190326140020p:plain

カレンダー、メモ、TODOリスト、LINE、Slack、ビデオ通話、音楽鑑賞など、全部ブラウザのアプリが提供されているならそれで頑張ってやるようにしました。

するとこれが結構いけるんですね。Googleカレンダーとか、macOSに入っているカレンダーと同じくらい便利だし、LINEのChromeアプリもおしゃんです。

Macの時は環境設定が大変だった

f:id:setouchinatsu:20190326144251p:plain

Macを使ってた頃はいろんなアプリケーションをOSにインストールしてそれを使っていましたので、Macbookでしていた作業をiMacでしようと思うと、同じアプリケーションをまた入れて、同じようにデータを同期(例えばカレンダーなら.ical形式のカレンダーをインポートしていたなら、iMacのカレンダーでもインポートが必要かもしれない。Macbookの特定のパスにファイルを保存して使うものだったら、同じデータをiMacの任意のパスに設置したあとiMacのアプリケーションの設定でその階層を指定しなければいけないなど)しなければ同等の作業はできません。

Linuxだとブラウザで完結しているので環境設定がほぼなし

f:id:setouchinatsu:20190326144333p:plain

しかし、Linuxにしてからはブラウザで全部完結させている(せざるを得ない)ので、(結果的に)ブラウザさえインストールしてGoogleなどにログインしてしまえば、他のLinuxマシンからも同様の作業が即継続できます。もしノートパソコンが壊れても、その辺りにあるノートパソコンにLinuxを入れてブラウザをインストールしたら終了です。

(もちろんMacでもブラウザさえあれば問題ないが、上でも書きましたがMacのアプリケーション系を使わないならMacである必要性はないと思います。多分本当にMacである必要がないのに使ってる私みたいな人って結構いると思います。Adobe製品やそれに準じるMacじゃないと動かない製品にどっぷり使ってる人はMacである必要があると思うが、Photoshopをちょっと使うくらいならクロスプラットフォームで動くKritaで十分だし、ちょっと趣味でやる動画編集ならShotcutで問題ない。)

開発をする時はアプリケーションを入れるがローカルにあるものは最小限にする

LinuxではGoogle Driveのようなファイル同期アプリが動かないです(Dropboxなら動くんですけど、脱Appleなんで安いAndoridを買うためGoogle Driveを契約しているので重複して契約するのはもったない)ので、ローカルのファイルをクラウドに同期するってのがうまいこといかない(Google DriveのCLIプロジェクトあるけど削除が動かないのよね)ので、そもそもローカルにファイルを置かないで、Google Driveなどでファイルを管理するようにします。すると結果的に、開発用のファイルくらいしかローカルには常時置くことはないですが、それも結局Gitで管理しているので、間接的にはクラウド(リモートリポジトリのこと)と繋がっているみたいなもんで御座いやす。

結果的に今ローカルで動かしているブラウザ以外のGUIアプリケーションは下記くらい

  • IntelliJ
  • Shotcut
  • Krita

動画ファイルとかは作ったらGoogle Driveに入れちゃいます。ローカル上でファイル整理とかしないっす。

まとめ

良かったこと

  • Macbookじゃなきゃいけないという縛りから脱した
    • Macには依存性があり、独特の使い心地で慣れてしまうと大変便利だけど、慣れてしまうとMacしか使えなくなります。
    • その縛りは結果的に生活を不便にし、お金持ちじゃないなら常に重い最強MacbookProを背負って歩くという苦行を強いられます。
      • お金が無限にあったら、家ではMacbook Proを使って、会社ではiMacを使って、出先には軽いMacbookを持っていくってことができます。
  • クラウドマンになったことでPCなんて何でもよくなった
    • どのPCでもブラウザが動いた時点で同じクオリティで作業できる。
    • ちょっと外出するくらいなら小さいChromebookがあれば結構な作業ができる。
    • ちょっとマシンパワーが必要なら自作PCでハイパフォーマンス、低価格ライフもできるようになった。
      • 無理して余裕を持った30万超えMacbookを買う必要はありません。
  • Linuxをメンテすることで技術に詳しくなった(ここは技術嫌いな人は苦行になる)
  • LinuxはUIのデザインをカスタマイズできるのおしゃれ大好きマンだったら気持ちよくなれる

悪かったこと

  • Macの強力なアプリケーションのデータ連携とOSとの癒着レベルは最強でそれには及ばない点もある(と私は思わないが客観的にはそう思われることもあるだろうと思う。)
  • Linuxにしてから適当に良いキーボード買ったら、そのキーボードにドハマりしてキーボード信者になってしまった。俺はそのうちキーボードを自作しはじめて、無駄に出費を増やすだろう。
  • Macから開放されてPC自作してたら楽しすぎて使わないパソコン作りまくった
  • 毎日自作PCを作りたい欲求を抑えて暮らしてる
  • やっぱLinuxみたいにMacほどハードと癒着していないので、多少上手くサスペンドできないなどなんか問題がある

同志たち