投稿日:
- microsoft.comからWindows用のドライバを落としてきて適当な場所に展開する
- コマンドプロンプトで
php -r "phpinfo()" > phpinfoする - 上記で吐き出した結果を
Threadで検索、Thread SafeかUnSafeか調べる - 落としてきたドライバからバージョンとThreadが合うものを探して
php\extに配置 php.iniのDynamic Extensionsセクションに次のような感じで記述
# php_と.dllは勝手に補完される
extension=pdo_sqlsrv_74_ts_x64
extension=sqlsrv_74_ts_x64
php -r "phpinfo()" > phpinfoしてsqlsrvが確認できたらOK
投稿日:
TSの情報に乏しく無駄にハマったのでメモ程度に
確認環境
| Env | Ver |
|---|---|
| React | 17.0.1 |
| TypeScript | 4.1.3 |
サンプルコード
- 今回はサンプルとして
<input />をラップしたコンポーネントのフォーカスを変更するためにrefを使います
Child.tsx
import { forwardRef } from 'react';
export type ChildProps = {
type: 'text' | 'password' | 'number';
onChange(changeValue: string): void;
};
// function 記法でないと ESLint が怒るので無効化
// eslint-disable-next-line react/display-name
export const Child = forwardRef<HTMLInputElement, ChildProps>(
// このpropsに明示的な型定義がないと型エラーが出る
(props: ChildProps, ref) => {
const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
props.onChange(ev.target.value);
};
return (
<input
ref={ref}
type={props.type}
onChange={(ev) => onChange(ev)}
/>
);
}
);
Parent.tsx
- 下側の
<Child />だけフォーカスが行くようにしてます
import { useEffect, useRef } from 'react';
import { Child } from './Child';
export const Parent = () => {
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
ref?.current?.focus();
}, []);
return (
<ul>
<li>
<Child
type={'text'}
onChange={(ev) => console.log('top input', ev)}
/>
</li>
<li>
<Child
ref={ref}
type={'text'}
onChange={(ev) => console.log('bottom input', ev)}
/>
</li>
</ul>
);
};
投稿日:
ふとした気づき
今時CGIなんて言わない?知らない?そんなこたぁいいんですよ。
ふと思ったんですよ、CGIとCLIアプリって本質的に同じものなんじゃないかなって。
だってPHPってこんなふうに書いてブラウザでアクセスしたらいろはにほへとって出るじゃないですか?
そしてこれをphp index.phpみたいにして叩いてもいろはにほへとって出ますよね?
<?php
echo 'いろはにほへと';
そう、気付いてしまったのです。
実はCGIって本質的にはCLIアプリなのではないかと…。
むしろ何が違うんでしょう?
仕組みを調べてみることに
気になったのでどういう仕組で動いてるのか軽く調べるために、敢えてC言語でCGIを作ってみることに。
今までC言語でCGIとか狂人のやることって印象があったのですが、意外とやってみると大したことはないというか、まぁ大したものを作ってないから当たり前なんですが…。
これが何をしているかというと、環境変数を取ってきて標準出力に吐いてるだけなので、どっからどう見てもCLIアプリです。
#include <stdio.h>
// getenv
#include <stdlib.h>
// strcmp
#include <string.h>
/*
get path for after hostname
*/
char* getPath(void) {
char *path = getenv("REQUEST_URI");
return path;
}
int main(void) {
// put http header
printf("Content-type: text/plain\n\n");
char *path = getPath();
// show current path
printf("Current path: %s\n", path);
// routing, required .htaccess to serve on apache
if (strcmp(path, "/foo") == 0) {
printf("hoge");
} else if (strcmp(path, "/bar") == 0) {
printf("piyo");
} else {
printf("fuga");
}
return 0;
}
実際に動かしてみたところ
CGIとして
CLI として
辿り着いた結論
恐らくこれは動作環境が重要なのであって、多分CGIとCLIアプリの作りとしては大きな違いはないのではないか?というのが辿り着いた結論です。
いやまぁ引数をargvから取るか環境変数から取るかは結構違う気もしますが、基本的に表示したいものを標準出力に吐く点は同じですし、別にCGIでTCPソケットを触るわけでもないので、同じようなものでは?と思った次第。
これは多分、 HTTPサーバーを通すことで標準出力がHTTPレスポンスに出力され、 Xサーバーを通すなら画面に、プリンタサーバーを通せば紙にといった具合に、どこのサーバーを通して標準出力をするかで出てくるところが変わるのでは?と感じました。(細かいことを言うともっと複雑らしい)
多分ApacheとかのHTTPサーバーはTCPソケットをいい感じにやってくれて、 HTTPヘッダを環境変数に入れてCGIスクリプトを起動といったところをしてくれているのではないかと思ったので、暇な時にTCP通信から始めるHTTPサーバーの実装でもやってみたいところですね…。
おまけ
取り敢えずPHPのCGIをCLIとして動かせるやつです。
<?php
echo $_SERVER['REQUEST_URI'];
投稿日:
画像マーカーを使ったリストタグを使った時に文字列がvertical-align: middle的になってほしい!
が結論から言うと多分無理です
なってくれないんだなこれが!
- 残念ながら現実にはなりません
- 上の画像のソースはこんなん
::beforeのcontentに画像を置くとかしても無駄です
<ul>
<li>リストの要素だよ~</li>
<li>改行のある<br>リストの要素だよ~</li>
</ul>
ul {
list-style-image: url("https://i.imgur.com/hX2OCbY.png");
}
li {
vertical-align: middle;
}
どうにか対策してみる
- 一見するとなんとかなったように見えますが、改行すると崩れます
- ぶっちゃけ無理にリストタグ使う必要もないと思うので、素直に div とかで代替するのが一番だと思います
- 何が何でもリストタグ使いたい場合はリストタグでラップしてしまうのが一番でしょうね…
- ぶっちゃけ無理にリストタグ使う必要もないと思うので、素直に div とかで代替するのが一番だと思います
- 上の画像のソースはこんなん
- リストのマーカーを使うことを放棄しているので、画像を抜けると字が落ちるのはどうしようもないですね
<ul>
<li>リストの要素だよ~</li>
<li>改行のある<br>リストの要素だよ~</li>
</ul>
.ul {
list-style: none;
}
.li::before {
padding-right: 3px;
min-height: 36px;
content: url("https://i.imgur.com/hX2OCbY.png");
vertical-align: middle;
}
投稿日:
react-routerでRouteを切る実装例
確認環境
| Env | Ver |
|---|---|
| React | 17.0.1 |
| react-router-dom | 5.2.0 |
| TypeScript | 4.1.3 |
サンプルコード
index.tsx
- ここに大元のルーティングを実装
import React from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import { BrowserRouter } from 'react-router-dom';
import { RootRoute } from './routes/RootRoute';
// ドメインルート以外にReactを設置する場合に必要
// e.g. `https://www.example.com/react/` に設置する場合 `/react` を設定
const basename = process.env.REACT_APP_BASE_NAME ?? undefined;
ReactDOM.render(
<React.StrictMode>
{/* `useHistory()` 用のDIラッパー */}
<BrowserRouter basename={basename}>
{/* ルーティング設定をまとめたコンポーネント */}
<RootRoute />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
AppRoute.ts
- ルーティングの定義、これがあると後々の管理が楽
- スプレッド演算子で
Routeに対して展開できるように記述しておく
export const AppRoute = {
// React のルート定義
root: {
path: '/',
key: '/',
exact: true, // 完全一致
component: App,
},
// 404 定義
notfound: {
component: NotFound,
},
// `/foo` 以下のルーティング定義
foo: {
// `/foo` のルート定義
root: {
path: '/foo',
key: '/foo',
component: FooRoute,
},
// 以下、 `/foo` 配下のページのルーティング定義
hoge: {
path: '/foo/hoge',
key: '/foo/hoge',
component: HogePage,
},
piyo: {
path: '/foo/piyo',
key: '/foo/piyo',
component: PiyoPage,
},
},
};
RootRoute.tsx
- 各階層の基底ルーティング管理
export const RootRoute = () => {
return (
{/* `Route` は `Switch` で囲む */}
<Switch>
{/* root */}
<Route {...AppRoute.root} />
{/* foo */}
<Route {...AppRoute.foo.root} />
{/* bar */}
<Route {...AppRoute.bar.root} />
{/* 404 */}
<Route {...AppRoute.notfound} />
</Switch>
);
};
FooRoute.tsx
/foo階層配下の管理用
export const FooRoute = () => {
return (
{/*
`Context` は `Switch` の外に出す
`Switch` の中に `Context` を書くと更に `Switch` でネストする必要がある
*/}
<FooContext.Provider value={FooContextDefault}>
<Switch>
{/* eslint-disable-next-line array-callback-return */}
{Object.entries(AppRoute.foo).map(([idx, route]) => {
if (idx !== 'root') {
/* `'root'` 以外の全ノードを展開 */
return <Route {...route} />;
}
})}
{/* 404 */}
<Route {...AppRoute.notfound} />
</Switch>
</FooContext.Provider>
);
};




