- 投稿日:
Markdownを使って快適にブログを書きたくない?書きたいですよね?そう、書きたい!
ではどうすればいいか?というのをこれから書いていきます。
JAMStackを使ってGitHub PagesとNext.js SSGでMarkdownブログを作ろう!みたいな人はブラウザバックをオススメします。
技術選定
- JAMStack
- はてなブログ
- WordPress
JAMStack
まずJAMStackは真っ先に除外します。ブログを書きたいのであってブログを作りたいわけではないからです。
またSSGだとクライアントサイドのレンダリングコストが重く、リッチなブログにしようとすると負荷がしんどい気がしています。恐らくSEO対策的にもCSRを妥協して極限までSSGしていないと厳しいのではないでしょうか?
はてなブログ
カスタマイズがすんごくだるい上に、真面目にやろうとするとクライアントサイドでHTMLをゴリゴリ書き換えたり、order
などのハックに近いCSSを多用して擬似的に要素を移動させたりする必要があり、レイアウトを組むのが非常に面倒です。
エディタもしょぼいしカテゴリはないし(はてブロのカテゴリは実質的にタグなので)年会費が高い割に出来ることの制限が強い…。あんまSEOも強くなかったし、試しに使ってみたものの流入が激減…正直個人的にこれはですね。
WordPress
多分こいつが一番現実的な選択肢です。WP Githuber MDを使うことで不自由なくMarkdownを扱うことが出来ると思います。但し内蔵のPrism.jsはなんかいい感じに動いてくれないケースがあり、その場合はカスタマイズが必要です。
カスタマイズについてもプラグインやテーマが豊富にあり、改造も容易なのでローコストでリッチなものが実現しやすいと思います。またセルフホストなのでデータの取り回しの自由が効きやすいのも大きなポイントですね。
CMSは色々使ってきましたが、なんだかんだブログはWordPressが一番だなって思います。SEO対策もGoogle謹製のやつがあるし、特に何もしなくてもある程度なんとかなるのは強みだと思います。
カスタマイズ法
CSS
使っているテーマと整合性が取れるようにいい感じにします。私は Dracula for Prism.js を改造して使いました。
JS
私の場合は次のコードをヘッダタグの中に足して対処しました。特に内容の説明はしませんが、行番号とコピーボタンが出るようにしています。
<script src="https://unpkg.com/prismjs@1.28.0/components/prism-core.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://unpkg.com/prismjs@1.28.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('pre > code').forEach((codeEl) => {
codeEl.className = codeEl.className === '' ? 'language-none' : codeEl.className;
codeEl.className = codeEl.className.replace(/^sh$/, 'shell');
codeEl.parentNode.className = 'line-numbers';
});
window.Prism.highlightAll();
});
</script>
- 投稿日:
VSCodeでは出来たことがPhpStormだと上手く出来なかったので、その解消法です
Remote Developmentに慣れてるとハマりやすいと思います
PhpStormに類似の機能は多分ないです
PhpStorm編
確認環境
一応Apacheの上に乗っかったLaravelで確認してますがそこらへんの環境情報は端折ってます
Env | Ver |
---|---|
Windows | 11 Pro |
PhpStorm | 2021.3.2 |
Docker | 20.10.11 |
docker-compose | 1.29.2 |
PHP | 8.1.1 |
Xdebug | 3.1.3 |
Dockerfile
PHPが入ってるDockerfileに以下を追記
出来ることならヒアドキュメントで書きたい
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
Dockerの設定
適当にDockerを追加してコンテナとローカルのパスをマッピング
PHPインタプリタの設定
CLIインタプリタをDockerに向けて設定します
パスマッピングは勝手にやってくれた気がする
デバッグ
HTTPリクエスト
受話器みたいなところを押してcurlなりPOSTMANなりブラウザなりにXDEBUG_TRIGGER=StartProfileForMe
というCookieを刺してリクエストするとブレークにかかります
初回だけパスマッピングを構成するダイアログが出てくるのでよしなに処理します
PHPUnit
デバッグ構成を作ってデバッグするだけ
おまけのVSCode編
VSCodeだとネイティブに動くのでDockerの存在を考えなくて済むのは楽ですが、IDEとしての性能はPHP Intelephenseに課金してもPhpStormには劣るので微妙なところ(静的解析に問題がある
確認環境
PhpStormと被る部分は端折ってます
Env | Ver |
---|---|
VSCode | 1.64.2 |
ms-vscode-remote.remote-containers | 0.217.4 |
robberphex.php-debug | 1.14.0 |
Dockerfile
PHPが入ってるDockerfileに以下を追記
PhpStormとの違いはxdebug.client_host
が不要なところです
(PhpStormでもCLI Debugだとなくていけるっぽいのでややこしい)
RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
launch.json
- Listen for Xdebug
- HTTPリクエスト用
- PHPUnit
- PHPUnit用
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "PHPUnit",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/vendor/phpunit/phpunit/phpunit",
"args": ["${file}"],
"env": {
"XDEBUG_TRIGGER": "StartProfileForMe"
},
"port": 9003
}
]
}
デバッグ
PHPのいるコンテナにAttach Visual Studio CodeしてF5押せばデバッグできます
あとがき
個人的に操作感はVSCodeの方が好みなので使えるならVSCodeでいきたいのですが、今の所PhpStormには敵わないという感じなのが悲しい
まぁJS/TS用のエディタみたいなもんだし仕方がないですね…
ただGitのGUI周りはVSCodeが圧倒的に好みなので、Git操作するときだけVSCode使ってたりはします
しかしPhpStormとVSCodeを共存させるのはxdebug.client_host
の向きの関係で微妙な感じですね…
- 投稿日:
TypeScriptをぼちぼちやってきた中で、型推論が素直に決まらないみたいな所が出てきたので書き置きとして残しておきます
具体的には何かしらの関数を通して処理を隠蔽すると上手くいかなくなるケースがあります
型が推論されないケース
検査関数的なものを通した場合に、後続処理で期待通り型が推論されなくなるケースです
その1
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
};
const required = (val: string) => {
return val === '';
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
};
if (required(input.value)) {
input.error = 'ERR';
console.error(input.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(input.value);
}
その 2
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true };
} else {
return { value: obj.value, error: '', hasError: false };
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(result.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(result.value);
}
export {};
型を推論されるようにしたケース
オブジェクトに型判定用のプロパティを生やしas
で型を明示することでクリアしています
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true } as {
value: '';
error: string;
hasError: true;
};
} else {
return { value: obj.value, error: '', hasError: false } as {
value: ValueT;
error: string;
hasError: false;
};
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(input.error);
} else {
registerHogePiyo(result.value);
}
export {};
あとがき
- Assertion Functionsを使う方法もあると思いますが、何も考えずAssertion Functionsを書くと次のような弊害があり、積極的に採用しづらいと考えています
- 何もしていなければ基本的にバンドル後のソースコードに出てくる
- 要するにバンドルサイズが大きくなります
throw
を書く必要性があり、バンドル後に残っている以上、このthrow
をcatch
する必要性がある- 無意味な実装工数が生まれる
- そもそも論としてAssertion Functionsを書く工数が生まれる
- Assertion Functionsの振る舞いを見ている限り、
as
に限りなく近く、ぶっちゃけas
で書いたほうが楽
- 何もしていなければ基本的にバンドル後のソースコードに出てくる
- 絶対に
as
を使わず現実的な工数で開発するというのは、割と非現実ではないかという感触があります- 個人的に型推論はIDEが勝手にやってくれるおかげで楽ができるシステムだと考えているので、型推論の補佐をする仕組みに工数をかけるというのは本末転倒な気がしています
- 品質は大切なことですが、反面で少なくないビジネスには期限もあります
- 品質に寄せすぎた過剰に冗長なコードも、納期に寄せすぎた脆弱性不具合山盛りスパゲティコードもどちらも考えものであり、その辺のバランスが上手くとれるやり方がなんかないかなーと考えることはしばしばあります
- 投稿日:
環境
Windows 10
Env | Ver |
---|---|
PHP | 8.0.2 |
Xdebug | 3.0.2 |
php.ini
zend_extension="xdebug-3.0.2-8.0-vs16-nts-x86_64"
xdebug.start_with_request=yes
xdebug.mode=debug
settings.json
別になくてもデバッグは出来る
"php.validate.executablePath": "C:/path/to/php.exe",
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
}
]
}
- 投稿日:
$arr = ['a', 'b', 'c'];
$test1 = '';
$test2 = '';
$test3 = '';
for($idx = 0; count($arr) > $idx; $idx++) {
${'test' . ($idx + 1)} = $arr[$idx];
// $this->{'test' . ($idx + 1)} = $arr[$idx];とするとクラスのプロパティも行ける
}
// $test1 = 'a'
// $test2 = 'b'
// $test3 = 'c'