読者です 読者をやめる 読者になる 読者になる

Endo Tech Blog

Techブログと言う名のただのブログです。

さりげなくJavaScriptとDOMの働きを学ぶ

JavaScript

f:id:kikuchi1201:20160811130148p:plain

JavaScriptを学んでいる。
本来ならばもう少しPHPの文法を使った、オブジェクト指向とか、クラス設計をがっつりやろーかなぁと思っていたんだが、今取り組んでいるアルバイトで今後JSのコードと嫌でも向きあわないといけない時期がくるので、今の内に基礎の基礎を学んでいる....訳です。

ほんでこれが人間に優しくない文章で書かれた成果物になります。

github.com

今みたらMarkdownが適応されていない箇所もあって、非常になので、後で修正しときます。

で、本題です。

JavaScripって何?

よく言われている説明としては

  • ブラウザ上で実装されるスクリプト言語
  • 動きのあるウェブサイトを作れる。

と言われていますが、厳密にはWEB上でインタラクティブな表現をする為に開発されたオブジェクト指向スクリプト言語(簡易プログラミング 言語)とか言われています。なんかかっこいいですけど、要はいい感じにイケイケなwebサイト作ってくれるプログラミング言語ですね。もっと知りたかったらここをクリックすれば基本的な概要は理解できます。

で、僕はこの説明がいまいちピンとこなくて、インタラクティブって何? 動きのあるウェブサイト作れる具体的に何さ?となって、色々と自分の中で消化しながら一つの解釈を立てました。

こんな事をかくと、まさかりが振ってきそうですが、何故この考えに至ったか図を使って説明しましょう。

DOMの働き

f:id:kikuchi1201:20160810200401j:plain
(このドムじゃない)

DOMとは「Document Object Model」の略で、HTMLドキュメントやHTML要素とJavaScriptなどの外部世界とのインターフェースをオブジェクトで表現したものです。
また、難しい単語が出てきましたが、何を言ってるかというと、以下の簡単なHTMLコード(ドキュメント)があるとします。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JabaScript</title>
</head>
<body>
    <h1>Hello Enod!</h1>
</body>

</html>

これをブラウザで見ると実行結果は以下の様に出力されます。

f:id:kikuchi1201:20160810201850p:plain

いいですね。
では、次にこのHello Endo!はどのように出力されているのか?を考えてみます。 通常よくある、HTMLコードを書くと「<h1></h1>で囲む→大見出しになると」と考えますが、このこそがDOMの働きになります。 f:id:kikuchi1201:20160811112947p:plain

つまり、DOMとはHTMLコードを解析した結果を元にブラウザに出力する仕組みを提供していると考えられます。では次にその仕組みについてもう少し詳しく見ていきましょう。

HTMLパーサーとDOMの関係

f:id:kikuchi1201:20160810214220p:plain

ブラウザの仕組み: 最新ウェブブラウザの内部構造より  

オレンジで囲まれ部分に注目して下さい。先ほどの説明でHTMLを解析してとありましたが、これを行っているのがHTMLパーサです。ここではHTMLパーサの詳細な説明は省きますがやっている事は以下の2つです。

DOMはこの解析ツリーを元にDOMツリーを生成します。このDOMツリーこそが、DOMの仕組みになります。例を見ていきましょう。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JabaScript</title>
</head>
<body>
    <div>
        <h1>Hello Wold!</h1>
        <b>My Name is Endo!</b>
        <p>Have a Nice day!</p>
    </div>
</body>
</html>

このHTMLコードをDOMツリーに変換すると以下のような図になります。

f:id:kikuchi1201:20160811095803p:plain

DOMツリーを調べると、こんな感じの図が沢山出てきて、色んな人の見方がありますのでどれが正解とも言えないですが概要的にはどれも同じだと思います。こんな感じにHTMLパーサで処理した結果を元に階層構造のDOMツリーを生成すると理解しておいて下さい。

ノードとは

DOMは階層構造を取ると同時にまた、もう一つ重要な働きがあります。それがノードです。ノードとは各要素(エレメントやタグ)を表す用語です。先ほどの図を使って説明しましょう。

f:id:kikuchi1201:20160811101752p:plain

ノードにはこの様にエレメントやHTMLタグ自体を表しています。先程のコードをこんな感じにJavaScriptを入れて変えてみます。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JabaScript</title>
</head>
<body>
    <div id="d1">
        <h1 id="h1">Hello Wold!</h1>
        <b>My Name is Endo!</b>
        <p>Have a Nice day!</p>
    </div>
    <script>
        var div1 = document.getElementById("d1");
        var h1 = document.getElementById('h1')

        console.log(div1.nodeName);
        console.log(h1.nodeName);
    </script>
</body>
</html>

nodeNameとはノードの名前を文字列で返すメソッドです。

実行結果はこの様になります。

f:id:kikuchi1201:20160811103715p:plain

この様にJavaScriptはDOMで生成されるノードを用いる事でHTMLを動的に操作する事が事が理解できたと思います。

このノードには親子関係がおり、あるノードを基準Nodeとした時に上の階層にあるノードを親ノード、下の階層にあるノードを子ノードとも呼びます。

f:id:kikuchi1201:20160811105704p:plain

以下に子ノードを調べるコードがあります。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>JabaScript</title>
</head>

<body>
    <div id="node">
        <h1>Hello Wold!</h1>
        <b>My Name is Endo!</b>
        <p>Have a Nice day!</p>
    </div>
    <form>
        <input type="button" id="myButton" value="Click" onClick="check()">
    </form>
    <script>
        function check() {
            var obj = document.getElementById("node");
            var child = obj.childNodes;
            console.log(child);
        }
    </script>
</body>

</html>

これを実行すると以下の結果が返ってきます。

f:id:kikuchi1201:20160811112356p:plain

子ノードの中に<p>,<h1>,<b>がちゃんと入っているのがわかると思います。そんな訳でHTMLタグをノードという形で操作できるようにDOMがその仕組を提供している事が理解できたと思います。最後にもっと重要(?)というかDOMの働きによる恩恵を見ていきましょう。

window.documentの正体

さっきから、なんとなくスルーしていましたが、document.getElementByIdで、先頭についているdocumentwindow.documentを省略した形です。
widow.documentとは今開いているブラウザをオブジェクトで表したものです。と、まぁJavaScripを普段から触ってる方からしたら、「そんなの当たり前やん」ってなるかと思うんですけど、この説明をサラっと聞いた時の衝撃というか...

「えっ?ブラウザがオブジェクトになるの??」

「なるなる」

「なにそれ怖い。って事はオブジェクトだから、色々操作できちゃうメソッドとかプロパティあるん?」

「あるある。console.dir(window)

f:id:kikuchi1201:20160811115957p:plain

ほんまやぁぁぁぁ沢山メソッド持ってたぁぁぁすげぇぇぇ

「それで、このwindow.documentJavaScriptで操作する事で動きのあるwebページ作れちゃう」

「なるほど。」

「さらにwindow.documentにアクセスするための色々な命令を document object modelとも言って、DOM をいじる、DOM を操作するとも言われています。」

「DOMすげぇー!」

f:id:kikuchi1201:20160811124054p:plain

みたいな感じで勝手に一人で感動して自己完結したのですが、ここまで理解できればDOMがどんな働きをして、JavaScriptが何であるのか?を全部とはいえないですが、さりげなく理解できたと思います。特にDOMについては学習しながら何度も躓いて理解したので、以下に資料をのせるのでこちらも見て理解を深めて行って下さい。

ブラウザの仕組み: 最新ウェブブラウザの内部構造
JavaScript初心者でもすぐわかる!DOMとは何か?
正しいHTMLとドキュメントツリーを理解しよう
JavaScript初級者から中級者になろう
DOMとは

【読書】不格好経営―チームDeNAの挑戦  南場智子

読書

booklog.jp

南場さんと最初にあったのは、大学に入ってすぐの時で、なんのイベントか忘れてしまったのですが、その時に南場さんが、僕を含めた60人ぐらいの学生に向けて

「今の日本が好きなレベルを5段階で表したら私は1です」

と、堂々と話していて、会場を驚かせていたのを思い出しました。君たちはこの先、こんな沈み行く船に乗らないで、世界から必要とされる人材になりなさいと。

この時点で僕は当時、かなり心を掴まれたのですが、その後の放った「これからは変態と呼ばれる人が重要な人材になる」と言った言葉が頭の片隅に残っていて、変態というのは、この本で出てくる多くの南場さんを支えた方なんだなと読みながら納得しました。

スーツを来た人間よりも、最後はヨレヨレなジャージを来た人間が救う。 なんて事は世の中にそうそうはないと思いますけど、南場さんの周りには変態を呼びつかせる磁場でも働いているんでしょうか?

いずれにせよ、経営者としても、ひとりの女性としても、大変素晴らしい人間だなと思いました。

"やっぱり世の中、一番よれよれな人が一番頼りになるのである。"

部屋のエアコンがオシャカになって4年過ぎだ。

日記 RaspberryPi

 

f:id:kikuchi1201:20160721022246p:plain

 

 

かれこれ自分の部屋でエアコンを使わない生活を送って、今年で四年目になる。

f:id:kikuchi1201:20160721090033j:plain

(加工したら笑えないぐらいに、カビが生えたエアコンになってしまった図)

 

いつ壊れたのかすら覚えていない。少なくとも大学に入ってから一度も電源を入れた事がないので、最低四年は経過している。

 

続きを読む

【翻訳】PHPアプリケーションの安全化in2016:ポケットガイド

翻訳 PHP セキュリティ

f:id:kikuchi1201:20160712114109j:plain

Securing a PHP Application in 2016: The Pocket Guide

原文

この文章は機械翻訳を通した後になるべく文法が通るように筆者が意訳した為見ずらい文章が多々あります。また意味が曖昧な言葉はすべて()で括っています。もし間違い、指摘がございましたらコメント欄にてお伝え下さい

It was the year 2016. A business owner just had a great idea to expand their reach in the marketplace, and they needed to build a web application to pull it off. After a bit of market research, they decide the best course of action is to hire PHP programmers to build their vision.

2016年の事でした。事業主はちょうど市場を広げる素晴らしい考えがありましたし、同時にそれはwebアプリケーションでやる必要がありました。市場調査の後、目標を実現するための最良の行動計画はまずPHPプログラマを雇うことであると決めました。

pull it off:〔漠然と〕うまくやる
best course of action:最善の方策

Let's say you're a PHP programmer. A few days later, you find yourself employed at the company to make this vision happen. As you're sitting at the desk reviewing the wireframes that were agreed upon, the news on TV says something that catches your ear. You turn the volume up and learn that another company got hacked, all their customers' data was compromised, and it's just a mess all around.You look back at your wireframes and wonder, "If it were to happen to this project, how would it fare?" How would you even begin to answer this question?

1人のPHPプログラマが言いました。数日後にあなたは自分自身がこの会社の目標の為に雇われている事に気付くでしょう。あなたは机で座りながら規定済みのワイヤ・フレームを見直しをしている時、TVのニュースで何か耳に引っかかる事を聞きます。TVのボリュームを上げると、別の会社がハッキングされ顧客情報が危険に晒され、全てめちゃくちゃになってしまった事をあなたは理解します。 あなたは、ふり返ってワイヤー・フレームを見ながら、「万一、同じ事がこのプロジェクトに起こったらどうすればいいのか?」と思います。

さぁこんな場面に出くわしたら、なんて答え始めるでしょうか。

agreed upon :規定済みの,制定されている。
catches your ear :(曖昧)耳に引っかかる。
turn the volume up :ボリュームを上げる
just a mess all around :すべてがめちゃくちゃになる。

セキュリティの本質を理解しましょう。

Please set aside most of what you've heard over the years; chances are, most of it just muddies the water. Security is not a product.Security is not a checklist.Security is not an absolute.

この数年にわたって聞いたほとんどの情報を一旦別にしておいてください。ほとんどは逆に混乱させる可能性があります。
セキュリティーとは製品ではないです。
セキュリティーとはチェックリストでもありません。
セキュリティーとは絶対的なものではないのです。

chances are:可能性は
it just muddies the water:〔事態などを〕混乱させる,波紋を投じる

Security is a process. Security is an emergent property of a mature mindset in the face of risk.

セキュリティとはプロセスです。セキュリティーは危険に直面した際の熟慮した考えで生まれる創発特性なのです。

mature mindset: 成熟した考え

Perfect security is not possible, but attackers do have budgets.

完全なセキュリティは可能ではありません。しかし攻撃者は予算を持っています。

budgets:予算

If you raise the cost of attacking a system (your application or the networking infrastructure it depends on) so high that the entities that would be interested in defeating your security are incredibly unlikely to succeed, you'll be incredibly unlikely to be compromised.

もしシステム(アプリケーションまたはそれが依存するネットワークインフラストラクチャ)の攻撃にかかるコストを高く引き上げる事が出来ればセキュリティーを破る事に興味がある者達は破ろうとしませんし、その結果危険に晒されることも無いでしょう。

Even better, the most effective ways to raise the cost of attack against your system don't significantly increase the cost of using the system legitimately.

さらに良い事に、システムに対する攻撃のコストを最も上げる効果的な方法は、システムにかける運用コストを増やさない事です。

significantly:広げる、上回る
legitimately:正当な

This is no accident; as Avi Douglen says, "Security at the expense of usability, comes at the expense of security."

これは事故ではありません。Avi Douglenは言います。
ユーザビリティを犠牲にしたセキュリティはセキュリティを犠牲にする。」

Avi Douglen:https

With that in mind, let's look at some easy security wins you can implement in your PHP applications that significantly raise the cost of attack without making your software unusable.

この言葉を念頭において、ここでは簡単なソフトウェアが使用不能にすることなく攻撃のコストを上げる事が出来るPHPアプリケーションで実装できるセキュリティを見ていきましょう。

4ステップでPHPセキュリティを改善します

Step1 すべての新しい開発でPHP7を使用する。

PHP 7 does three important things that significantly improve the security of software written in it:

PHP 7はソフトウェアのセキュリティを著しく改善する3つの重要な事が書かれています。

1.PHP 7 dropped support for the old mysql_* functions, which a lot of outdated and insecure PHP tutorials used.
2.PHP 7 allows you to add scalar type declarations to your code.
3.PHP 7 ships with a secure random number generator.

1.多くの時代遅れで不安定なPHP教本が使用してきた、古いmysql関数の支援をやめました。
2.スカラ型宣言をコードに加えられています。
3.安全な乱数生成器がPHP7では備えられています。

Let's look at an example of the first two items in that list.

それでは最初の例として、2つのリスト項目を見てましょう。

<?php

/** PHP 5 snippet */
class Foo {
    public function get_products($name, $start = 0, $end = 30)
    {
        $name = mysql_real_escape_string($name);
        $query = mysql_query("SELECT * FROM products WHERE name LIKE '%{$name}%' LIMIT {$start}, {$end}");
        $products = [];
        while ($row = mysql_fetch_assoc($query)) {
            $products []= $row;
        }
        return $products;
    }
}

$foo = new Foo;
$products = $foo->get_products($_GET['search']);

This appears secure (we're escaping strings), but what if you accidentally passed a GET parameter as the second and third arguments to$foo->get_products()? Chances are, SQL injection would be the result.

これはセキュア(文字列をエスケープしている)として表せられますが、$foo->get_products()の二番目と三番目の引き数としてGETパラメータで渡された場合どうなるでしょう?恐らく、SQLインジェクションが結果としておきるでしょう。

what if:~だったらどうする?
Chances are:多分,おそらく

Now let's look at the PHP 7 approach:

ではPHP7での振る舞いを見てみましょう。

<?php
declare(strict_types=1);

/** PHP 7 snippet */
class Foo {
    protected $pdo;
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
        $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public function get_products(string $name, int $start = 0, int $end = 30): array
    {
        $stmt = $this->pdo->prepare(
            "SELECT * FROM products WHERE name LIKE :name LIMIT {$start}, {$end}"
        );
        $stmt->execute([
            'name' =>
                '%' . $name . '%'
        ]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

$foo = new Foo(new PDO(/* ... */));
$products = $foo->get_products($_GET['search'] ?? '');

Is this more secure than the PHP 5 snippet? Certainly. If a developer accidentally passes a GET parameter to the second or third arguments, this will throw a TypeError unless they cast the user's input to an integer first. If the script doesn't catch the TypeError, then the script aborts execution. Type safety is useful for stopping unintended consequences.

このコードはPHP5より安全でしょうか?もちろんです。もし開発者が誤って第一引数,第二引数へのGETパラメータを渡す場合でも最初の整数にユーザ入力をキャストしない限り、例外処理としてType Errorを投げます。スクリプトTypeError例外をキャッチしない場合、実行が中止されます。従って型の安全性は意図しない結果を停止するのに便利なのです。

There are no known integer inputs that can result in SQL injection, given the code above. However, it's still highly recommended to avoid string concatenation in SQL queries at all.

上記のコードで既知のSQLインジェクションをもたらすことができる整数入力はないです。しかし今まで通りにSQLクエリでの文字列連結を回避することを強くお勧めします。

Furthermore, both the MySQLi and PDO extensions support a feature called prepared statements.The old MySQL extension did not.

さらに、MySQLiとPDO拡張機能両方が準備された機能をサポートします。古いMySQLはもう拡張はしません。

PHP 7 marked an inflection point in the PHP language (and the ecosystem surrounding it) to make it easier to do the secure thing than the insecure thing

PHP 7は不安定な言語から、より簡単に安全なことをするPHP言語(またそれを囲む生態系)としての変曲点を迎えました。

marked an inflection point :(曖昧)変曲点にマークする

Step2 どこでもHTTPSを使おう。

A website that uses HTTPS properly almost never has to worry about session hijacking attacks (for example, Firesheep); and thanks to Let's Encrypt and open source projects like Caddy - a webserver that offers automatic free HTTPS, it's never been easier to adopt HTTPS.

HTTPSを適切に使用しないほとんどのウェブサイトはセッションハイジャック攻撃(例:Firesheep)を心配する必要があります。 暗号技術やCaddy -オープンソースHTTPSを提供するWebサーバ-のおかげで、HTTPSの導入は簡単になりました。

セッションハイジャック攻撃:cookieでセッション管理を行うPHPの場合はcookieにセッションIDを保存します。このセッションIDを他のユーザーのものに書き換えてなりすましてしまうのがセッションハイジャック攻撃です。

Compare, for instance, this Caddyfile for our project, CMS Airship with its congruent Apache or nginx configurations.

例えば我々のプロジェクトであるCaddyfile,CMS AirshpsにおいてApacheもしくはnginxの構成で比較してみましょう。

Even though modern HTTPS (the TLS 1.2 variety) adds a layer of authenticated encryption to your network traffic, its CPU and memory usage overhead has been proven negligible. With HTTP/2, it's often faster for your users to connect over HTTPS than it is over HTTP.

現代のHTTPS(TLS1.2)はネットワークトラフィックに認証された暗号化の層を追加していても、そのCPUとメモリ使用量のオーバーヘッドが無視できることが証明されています。HTTP/2を使用する事でユーザがHTTPを介しするよりもりも、HTTPS経由で接続する方が速いことが多いのです。

For marketing incentive, HTTPS is also a boon for search engine optimization.

マーケティングの要点からもHTTPSは検索エンジ最適化のために役立つでしょう。

incentive:要因,動機 boon:恩恵,ありがたい

Step3 セキュリティ・ヘッダーを使用する。

Security expert Scott Helme has put together a website that allows you to assess your usage of HTTP response headers that enable and/or configure security features, at SecurityHeaders.io. (You can see our scan results here.)

セキュリティの専門家であるスコット・ヘルメ氏はSecurityHeaders.ioでセキュリティ機能を有効にするか、または構成するHTTP応答ヘッダーの使用状況を評価することを可能にするウェブサイトを一緒に入れています。 (ここに私達のスキャン結果を見ることができます。

Some security headers are trivial to implement (header("X-Frame-Options: SAMEORIGIN"); makes clickjacking nigh-impossible while allowing the use of HTML frames if your website was designed to use them).

一部のセキュリティヘッダを実装するのは簡単です。例えば(header("X-Frame-Options: SAMEORIGIN");を実装するようにデザインされているHTMLフレームであれば、使用しながらもクリックジャッキングを不可能にする事ができます。

※クリックジャッキングとはCSRFと同じように「Webアプリケーションのサーバー側機能」を利用者(被害者)に実行させる手法です。詳細はここのリンクにあります。

For the more complicated security headers, Paragon Initiative Enterprises has developed open source software to make their implementation easier.Consider, for example, CSP Builder (which assembles Content-Security-Policy headers for you).

より複雑なセキュリティ・ヘッダーの場合、 Paragon Initiative企業(著者の企業)はこれらの実装を容易にするために、オープンソースソフトウェアを開発しました。例えば、CSP Builder(Content-Security-Policyの組み立て)で考えてみましょう。

<?php
use ParagonIE\CSPBuilder\CSPBuilder;

(new CSPBuilder())
    ->addSource('image', 'https://ytimg.com')
    ->addSource('frame', 'https://youtube.com')
    ->addSource('script', 'https://www.google.com')
    ->addDirective('upgrade-insecure-requests', true)
    ->sendCSPHeader();


At bare minimum, you should send these headers:

最低でも、以下のヘッダを送信する必要があります。

  • Strict-Transport-Security
  • X-Frame-Options
  • X-XSS-Protection

Step4 信頼できる参考資料を使いましょう。

Although adopting PHP 7 means you'll miss out on most of the ways PHP developers shoot themselves in the foot while building software, there are still tutorials being written in 2016 that contain ill-advised (or outright vulnerable) practices. A great way to avoid accidentally trusting an unreliable tutorial is to proactively learn the best practices.

PHP7を採用する機会から逃げている事は、PHP開発者がソトウェアを構築しなが自ら墓穴を掘っている事を意味しますし、また(あからさまな脆弱)が含まれている2016年に書かれたチュートリアルが未だ残っています。信頼できないチュートリアルを回避するのに最適な方法は、積極的にベストプラクティスを学ぶことです。

miss out on most of the ways:方法のほとんどを逃します。
shoot themselves in the foot:自ら墓穴を掘る。

Start with our Gentle Introduction to Application Security, then check out our application security reading list. Most of the concepts we emphasize in our blog posts are also widely applicable outside PHP security.

PHPセキュリティの次のレベルへ

If you follow the four easy steps above, you'll be in much better shape when it comes to defending against computer criminals.

上記の4つの簡単な手順を実践する事でコンピュータ犯罪者に対する防御を考える際にもはるかに良い形になるでしょう。

Earlier we had said, "If you raise the cost of attacking a system (your application or the networking infrastructure it depends on) so high that the entities that would be interested in defeating your security are incredibly unlikely to succeed, you'll be incredibly unlikely to be compromised." There's a corollary that must be stated here.

先に我々が述べた"もし貴方がシステム(アプリケーションまたはそれが依存するネットワークインフラストラクチャ)の攻撃にかかるコストを高く引き上げる事が出来れば、セキュリティーを破る事に興味が攻撃者達は破ろうとしませんし、その結果危険に晒されることも無いでしょう"という事をここに、もう一度記載しなければなりません。

You cannot know everyone that is interested in attacking your system. You similarly cannot know why every possible attacker in the universe may want to attack your system.

システムを攻撃する事に興味を持ってる人を誰も知り得る事はできません。また同様に、全ての(in the universe)攻撃者がセキュリティーを破れるシステムの中であなたのシステムを攻撃するかもしれない事を、知る事もできないのです。

There are a lot of companies that try to fill in this gap. They emphasize attribution, threat intelligence, and real-time attack monitoring. You can, for the most part, safely ignore all of these things they are selling.

このギャップを埋めるために挑戦する多くの企業があります。彼らは攻撃の特性、脅威インテリジェンス、およびリアルタイムの攻撃の監視を強調しています。ほとんどの部分は、彼らが販売している物で安全に無視することができます。

attribution :帰属,著者,属性特性

Consider this: Even if you were to succeed in knowing who is attacking your network and what they hope to gain, the most you can glean from this is psychological comfort in knowing your enemy and maybe retributive prosecution (if they're in another country, the odds become much slimmer).

ここで考えてみましょう:貴方がネットワークを攻撃した人物を特定し、攻撃者が望んでいる情報を引き出す事に成功したとしても、ほとんどは攻撃者を特定する事による心理的快感と恐らく報復起訴を苦労して得る事ができます。(もし、攻撃者が別の国にいる場合、オッズはかなり小さいですが。)

glean:探り出す,〈落ち穂などを〉拾う,(苦労して少しずつ)収集する
retributive prosecution:(曖昧)報復起訴

If your goal is to write secure PHP applications:
・You generally don't need to know who the attacker is.
・You generally don't need to know why they want to break in.
Conversely:
・You should know what attacks are possible.
・You should know where attacks should come from.
・If an incident does occur, you should know when and how it happened, so you can prevent it (and similar attacks) from happening again.

セキュアなPHPアプリケーションの目標を記述する場合:

・「誰」が攻撃者があるかを知る必要はありません。
・「なぜ」彼らは壊したいのかを知る必要はありません。

では逆に

・「なに」で攻撃が可能であるかを知っている必要があります。
・「どこ」から攻撃がくるのかを知っている必要があります。
・もし事故が発生した場合は、「いつ」、どのようにそれが起こったあなたが知っている必要がありますので、再び起きてからそれ(と同様の攻撃)を防ぐことができます。

If you find yourself asking, "Who would want to attack us? It's not worth it for them to target such small fry," consider the current trend of computer crime: ransomware and watering-hole attacks on ad networks are quickly becoming the biggest threats to the security of most peoples' computers.

あなたはこんな感じに自問自答するかもしれません。"だれが我々を攻撃したがるんだ?彼らにとって我々なんて小さな稚魚を捕まえるような事じゃないか",と考えながら現在のコンピュータ犯罪の傾向を考えます。広告ネットワークへのランサムウェアおよびWatering Hole型攻撃はすぐに人々のコンピュータセキュリティ最大の脅威となってくるでしょう。

ランサムウェア:感染したPCをロックしたり、ファイルを暗号化したりすることによって使用不能にしたのち、元に戻すことと引き換えに「身代金」を要求する不正プログラムです。 身代金要求型不正プログラムとも呼ばれます。詳細はここで見れます

※Watering Hole型攻撃:企業や組織を狙った攻撃手法の1つを表す言葉として使用されています。この場合、攻撃者は、慎重に考慮した上で特定のWebサイトを選定し、そのWebサイトに脆弱性利用のマルウェア(エクスプロイト)を組み込むことで改ざんを行い、最終的にマルウェアの感染被害が発生することになります。詳細はここで見れます

Your system might not be the end-game, especially if the attacker is sophisticated. Always look to improve. Security is a process. It's not a destination.

攻撃者が高度な技術を持っている場合は特に、システムにエンドゲームはないかもしれません。常に改善する所があります。繰り返し言いますが、セキュリティはプロセスです。目的地ではないのです。

sophisticated:(都会的・知的に)洗練された、(高度の)教養のある、インテリ向きの、世慣れた、純真でない、如才ない,精巧な、高性能の

If you run out of ideas to improve, consider hiring a security company to perform a comprehensive penetration test and/or audit your source code. Specialists will generally have deeper insight into the more advanced attacks that are possible as well as the best defense against them.

もしも改善するアイデアが不足した場合は総合的な侵入テストを実行するために警備会社を雇うことを検討するか/またはあなたのソースコードを監査をつけましょう。専門家は、一般的に可能なだけでなくそれらにに対する最善の防御策であり、より高度な攻撃に深く洞察力を持っています。

(Full disclosure: Our company specializes in developing secure PHP software; penetration testing and source code auditing are both services we provide our clients.)

(情報開示:私たちの会社は安全なPHPのソフトウェアの開発に特化しており、侵入テストとソースコード監査の両方のサービスをクライアントに提供しております)

July 10, 2016 4:55 pm by P.I.E. Staff

原文

後日談

数日前に友人に誘われてベンチャー投資家とスタートアップのミーティング会議に参加させてもらったことがあったんですよ。といってもデッカイ会場とかではなく横浜にあるタワーマンションのワンルーム(?)みたいな所で10~12人ぐらいが入る規模ぐらいかな?。このミーティングに参加している一人が僕の友人にこのミーティングに誘ってくれて、その友人から僕に連絡がきて「美味しい食べ物とお酒、ノメルヨ」と来てノココと付いて行った訳です。でまぁ、このミーティングが結構熱くて、中には黒人の学生の子もいて、母国(アフリカ諸国)に戻ってICT教育を普及させたいだ!つって全部英語で喋って(勿論投資家側も英語で返す)、僕みたいミーハな奴でも熱が伝わる素晴らしいプレゼンだったんだけど、プレゼンが終わった飲み会でその黒人の人とは違う、外国人の人から「PHPwebサービスを作るのは危険なんだよね」みたいな事を聞かれれ、ボクなんか英語で返そうにも最近Rapにはまってるせいで「Hy!Yo!Year! wackなMC~!」しか言えないんだけど、頑張って「いやPHP7にすれば大丈夫だよ」とかなんかそれっぽい事を言ったら「hmmmmmm」ってすごい怪訝な顔をされた訳ですよ。 「hmmmmm」って、それ日本人でしう「う~~~ん」みたいな?なんか違うぜ、みたいな?そしたら彼がやっぱりセキュリティの事でPHPは危険さぁ~って、手にもった赤ワインを飲みながら陽気に受け流していたんだけど。まぁ確かに7に上げた所でそこまで売り上げ変わるかってわかんないし、そもそも情報がまだまだ少ないし、しかもカツカツなベンチャーなら、顧客情報流失なんて謝罪で済む話じゃない訳で、一歩間違えりゃ倒産じゃないですか。さっき頑張ってプレゼンしてた黒人のナイスガイナな彼も困り顔で「hmmmmm」とか言いそうだなって!って、意識が朦朧としながらトイレで引きこもりがら考えてたんですよ。

でこの文章に書いてある通りに確かにセキュリティを考えなきゃならん、しかし運用も考えなきゃならんと。結局はバランスとか言っていい感じに〆たい所なんですけ少なくとも今後新しいサービスは7に切り替えるべきだなって考えています。まぁそんなわけでここに書いてある通り良いコードを身につけるべく、今は独習PHPにいじめられています。

時間あったら型付関数とタイプビンディングの違いの記事をあげます。

教祖本

散々いじめられた。お世話になりました。

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

今読んでます。

独習PHP 第3版

独習PHP 第3版

教祖本を買いた同じ人が書いてますが、やっぱり難しいが良本。
MVCフレームワークを使った最近のwebアプリケーション開発の事例を知りたかったら
この本でも十分通用します。

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

効率的なWebアプリケーションの作り方 ~PHPによるモダン開発入門

工事中画面のページ

現在このページはまだ作られておりません。

以下、本人による心からの謝罪文をお読みください。

f:id:kikuchi1201:20160704151924p:plain

【翻訳】Pythonを使ったInstagramにおけるWebサービスの効率化

翻訳

f:id:kikuchi1201:20160622104353p:plain

原文:Web Service Efficiency at Instagram with Python

この文章は機械翻訳を通した後になるべく文法が通るように筆者が意訳した為見ずらい文章が多々あります。また意味が曖昧な言葉はすべて()で括っています。もし間違い、指摘がございましたらコメント欄にお伝え下さい

意味が曖昧な単語

  • CPUの回帰(CPU regression)
  • 信頼区間(confidence intervals)
  • 振り返り(battle regression.)

Pythonを使ったInstagramWebサービスの効率化

Instagram currently features the world’s largest deployment of the Django web framework, which is written entirely in Python.

Instagramは現在Djangoウェブ・フレームワークの世界で最大の配備を特色としており全てPythonで書かれています。

We initially chose to use Python because of its reputation for simplicity and practicality, which aligns well with our philosophy of “do the simple thing first.” But simplicity can come with a tradeoff: efficiency.

私たちは"シンプル"さと"実用性"の評判のためにPythonを使用することを最初に決めました。それは私たちの哲学である「単純なことを最初にする」とよく結びつけます。
しかし、単純性は"効率"とトレードオフです。

Instagram has doubled in size over the last two years and recently crossed 500 million users, so there is a strong need to maximize web service efficiency so that our platform can continue to scale smoothly.

Instagramのは過去2年間で2倍の大きさと最近5億人ユーザーが利用しており私たちのプラットフォームはスムーズに拡大縮小し続けることができるようなWebサービスの効率を最大化する強い必要性がありました。

In the past year we’ve made our efficiency program a priority, and over the last six months we’ve been able to maintain our user growth without adding new capacity to our Django tiers.

そこで去年私たちは効率を優先事項にプログラムさせ、過去6か月に渡り新しいキャパシティーDjango層に加えずにユーザ成長を維持することができました。

In this post, we’ll share some of the tools we built and how we use them to optimize our daily deployment flow.

この記事は、私たちの日常の開発の流れを最適化するために我々がビルドしたツールと、それをどのよう使用するのか、いくつかを共有しましょう。

なぜ効率を?(Why Efficiency?)

Instagram, like all software, is limited by physical constraints like servers and datacenter power.

すべてのソフトウェアがそうであるように、Instagramはサーバーおよびデータセンターのような物理的な制約によって制限されています。

With these constraints in mind, there are two main goals we want to achieve with our efficiency program:

これらの制約を念頭において私たちが効率プログラムで達成したい主な2つのゴールがあります。

1.Instagram should be able to serve traffic normally with continuous code rollouts in the case of lost capacity in one data center region, due to natural disaster, regional network issues, etc.

1.Instagramは自然災害、地域ネットワークの問題などで1つのデータセンターの地域で容量が失われた場合でも連続的なコードロールアウト(運用展開)で、通常のトラフィックにサービスを提供することができる必要があります。

2.Instagram should be able to freely roll out new products and features without being blocked by capacity.

2.Instagramは自由に容量に遮られることなく新製品と機能をロールアウトすることができる必要があります。

To meet these goals, we realized we needed to persistently monitor our system and battle regression.

これらの目標を達成するため、私たちは持続的にシステム監視する事とその振り返り(battle regression.)が必要である事に気付きました。

効率の定義(Defining Efficiency)

Web services are usually bottlenecked by available CPU time on each server.

Webサービスは通常は各サーバ上の利用可能なCPU時間がボトルネックとされます。

Efficiency in this context means using the same amount of CPU resources to do more work, a.k.a, processing more user requests per second (RPS).

このコンテキスト中の効率は毎秒(RPS)より多くのユーザ・リクエストを処理してより多くの仕事(a.k.a)をするために同じ量のCPU資源を使用することを意味します。

As we look for ways to optimize, our first challenge is trying to quantify our current efficiency.

最適化する方法を探していくにつれて私たちの最初の課題は効率化の定量化でした。

Up to this point, we were approximating efficiency using ‘Average CPU time per requests,’ but there were two inherent limitations to using this metric:

このポイントまで私たちは「1つのリクエスト当たりの平均のCPU時間」を使用して効率化に接近していました。しかし、このメトリック(測定基準)の使用に、2つの固有の制限がありました。

Diversity of devices. Using CPU time for measuring CPU resources is not ideal because it is affected by both CPU models and CPU loads.

1つにデバイスの多様性です。CPUモデルとCPU負荷の両方に影響されるため、CPUリソースを測定するためのCPU時間を使用することは理想的ではありません。

Request impacts data. Measuring CPU resource per request is not ideal because adding and removing light or heavy requests would also impact the efficiency metric using the per-requests measurement.

2つめに要求が影響を与えるデータです。データの追加や軽い削除、重いリクエストなどこれらはそれぞれの要求測定を使用して効率メトリックに影響を与えるため、リクエスごとにCPUリソースを測定することは理想的ではありません。

Compared to CPU time, CPU instruction is a better metric, as it reports the same numbers regardless of CPU models and CPU loads for the same request.

同じリクエストのCPUモデルとCPU負荷に関係なく同じ番号を報告するように、CPU時間と比較してCPUの命令で測定する事は良好なメトリックだと私たちは考えました。

Instead of linking all our data to each user request, we chose to use a ‘per active user’ metric.

従って私たちはデータをすべて各ユーザ・リクエストにリンクする代わりに1つの"アクティブユーザあたりのリクエスト"を使用することに決めました。

We eventually landed on measuring efficiency by using ‘CPU instruction per active user during peak minute.’ With our new metric established, our next step was to learn more about our regressions by profiling Django.

私たちは最終的に「ピーク分中のアクティブユーザにおけるCPU命令」の使用により効率を測定することを決めました。以上の新しいメトリックを確立した状態で次のステップであるDjangoをプロファイリングすることにより当社の振り返りについてご紹介したいと思います。

Djangoサービスのプロファイリング(Profiling the Django Service)

There are two major questions we want to answer by profiling our Django web service:

私たちはDjangoWebサービスをプロファイリングすることでお答えしたい二つの主要な質問があります。

Does a CPU regression happen? What causes the CPU regression and how do we fix it?

CPUの回帰が発生しますか?
何がCPUの回帰を引き起こしそれをどのように解決するのですか?

To answer the first question, we need to track the CPU-instruction-per-active-user metric.

最初の質問に答えるために、我々はCPU命令あたりのアクティブユーザーメトリックを追跡する必要があります。

If this metric increases, we know a CPU regression has occurred.

このメトリックが増加した場合我々はCPUの回帰が発生している事を知っています。

The tool we built for this purpose is called Dynostats.

私たちがこの目的のために作成したツールはDynostatsと呼ばれます。

Dynostats utilizes Django middleware to sample user requests by a certain rate, recording key efficiency and performance metrics such as the total CPU instructions, end to end requests latency, time spent on accessing memcache and database services, etc.

Dynostatsはmemcache(汎用の分散型メモリキャッシュシステム)や終了要求の待ち時間の合計CPU命令としてキー効率と性能指標を記録し、一定の割合でユーザーの要求をサンプリングするためにDjangoミドルウェアを利用します。

On the other hand, each request has multiple metadata that we can use for aggregation, such as the endpoint name, the HTTP return code of the request, the server name that serves this request, and the latest commit hash on the request.

一方で各リクエストにはそれぞれ終了点名、リクエストのHTTPリターン・コード、このリクエストに役立つサーバー名およびリクエストに応じた最新のコミットハッシュとして集計に使用できる多数のメタデータがあります。

Having two aspects for a single request record is especially powerful because we can slice and dice on various dimensions that help us narrow down the cause of any CPU regression.

我々は任意のCPU回帰の原因を絞り込むため為に様々な寸法上で切り分ける事ができるので、単一の要求レコードに対して二つの側面を見ることができ、これは特に強力です。

For example, we can aggregate all requests by their endpoint names as shown in the time series chart below, where it is very obvious to spot if any regression happens on a specific endpoint.

任意の回帰は、特定のエンドポイント上で発生した場合にスポットすることは非常に明白であります。以下の時系列グラフに示すように、例えばエンドポイント名ですべての要求を集約することができます。

f:id:kikuchi1201:20160622094755p:plain

CPU instructions matter for measuring efficiency — and they’re also the hardest to get.

CPUの命令は効率を測定するために重要です - また、取得することが最も難しいです。

Python does not have common libraries that support direct access to the CPU hardware counters (CPU hardware counters are the CPU registers that can be programmed to measure performance metrics, such as CPU instructions).

PythonにはCPUハードウェア・カウンター(CPUハードウェア・カウンターは、CPU命令のようなパフォーマンス・メトリクスを測定するようにプログラムすることができるCPU命令)へのダイレクトアクセスをサポートする共通のライブラリーがありません。

Linux kernel, on the other hand, provides theperf_event_open system call.

一方でLinuxカーネルはperf_event_openシステムコールを提供します。

Bridging through Python ctypes enables us to call the syscall function in standard C library, which also provides C compatible data types for programming the hardware counters and reading data from them.

従ってPythonctypesを介して橋渡しすることでハードウェアカウンタをプログラミングし、そこからデータを読み出すためのCと互換性のあるデータを標準Cライブラリ内のシステムコール関数として呼び出すことを可能にしています。

With Dynostats, we can already find CPU regressions and dig into the cause of the CPU regression, such as which endpoint gets impacted most, who committed the changes that actually cause the CPU regression, etc.

Dynostatsで我々はすでにCPUの回帰を見つけることができますし、実際にCPU回帰などを引き起こす変更をコミットし、エンドポイントが最も影響を受けるかなど、CPUの回帰原因を掘り下げます。

However, when a developer is notified that their certain changes cause CPU regression, they usually has a hard time finding the problem.

しかしながらある変更がCPU回帰を引き起こすと開発者に通知された場合でもその原因を見つける事は通常困難です。

If it was obvious, the regression probably wouldn’t have been committed in the first place!

それはもし明白だった場合は、回帰はおそらく最初の場所でコミットされていなかった事にしましょう!(ジョーク?)

That’s why we needed a Python profiler that the developer can use to find the root cause of the regression (once Dynostats identifies it).

ですから、私達は開発者が(Dynostatsが識別した後)回帰の根本的な原因を見つけるために使用できるPythonのプロファイラが必要でした。

Instead of starting from scratch, we decided to make slight alterations to cProfile, a readily available Python profiler.

ゼロからスタートする代わりに、私たちはcProfileを容易に利用可能なパイソン・プロフィーラーへの少しの変更を行うことに決めました。

The cProfile module normally provides a set of statistics describing how long and how often various parts of a program were executed.

cProfileモジュールは、プログラムの様々な部分がどれくらいの時間でどれくらい頻繁に実行されたかを説明する1セットの統計を通常提供します。

Instead of measuring in time, we took cProfile and replaced the timer with a CPU instruction counter that reads from hardware counters.

測定する代わりに、私たちはcProfileを使いハードウェア・カウンターから読むCPU命令カウンタにタイマーを取り替えました。

The data is created at the end of the sampled requests and sent to some data pipelines.

データはサンプリングされたリクエストの終わりに作成されいくつかのデータ・パイプラインに送られます。

We also send metadata similar to what we have in Dynostats, such as server name, cluster, region, endpoint name, etc.

さらにサーバー名、クラスタ、地域、終了点名などのような、私たちが持っているメタデータをDynostatsに送ります。

On the other side of the data pipeline, we created a tailer to consume the data.

データ・パイプラインの反対側には私たちがデータを消費するためのテーラーを作成しました。

The main functionality of the tailer is to parse the cProfile stats data and create entities that represent Python function-level CPU instructions.

テーラーの主な機能性はcProfile統計データを解析しパイソン機能レベルでCPU命令を表わす実体を作成することです。

By doing so, we can aggregate CPU instructions by Python functions, making it easier to tell which functions contribute to CPU regression.

そうすることによって、私たちはどの機能がCPUの回帰に依存するのかを伝えることをより簡単にしてパイソン機能によるCPU命令を集めることができます。

モニタリングおよび警報メカニズム(Monitoring and Alerting Mechanism)

At Instagram, we deploy our backend 30–50 times a day.

Instagramではバックエンドに1日に30-50回展開します。

Any one of these deployments can contain troublesome CPU regressions.

これらの展開はいずれも面倒なCPUの回帰を含んでいます。

Since each rollout usually includes at least one diff, it is easy to identify the cause of any regression.

それぞれのロールアウトは、通常少なくとも一つの差分を含むので、任意の回帰の原因を特定することは容易です。

Our efficiency monitoring mechanism includes scanning the CPU instruction in Dynostats before and after each rollout, and sending out alerts when the change exceeds a certain threshold.

私たちの効率監視メカニズムはそれぞれのロールアウトの前後でDynostatsにおけるCPUの命令をスキャンし、変化がある閾値を超えたときに警告を送信します。

For the CPU regressions happening over longer periods of time, we also have a detector to scan daily and weekly changes for the most heavily loaded endpoints.

より長い期間にわたって起こっているCPUの回帰の為に私たちも毎日スキャンする検出器と、最も負荷の高いエンドポイントの毎週変化の情報を保持します。

Deploying new changes is not the only thing that can trigger a CPU regression.

また新しい変更のDeployはCPU回帰を引き起こすことができるただ一つのトリガーではありません。

In many cases, the new features or new code paths are controlled by global environment variables (GEV).

多くの場合、新機能や新しいコードパスはグローバル環境変数(GEV)によって制御されます。

There are very common practices for rolling out new features to a subset of users on a planned schedule.

これらは計画されたスケジュールに基づいてユーザーのサブセットに新しい機能を展開するための非常に一般的な慣行があります。

We added this information as extra metadata fields for each request in Dynostats and cProfile stats data.

私たちは、DynostatsとcProfileの統計データ中の各リクエストの余分なメタデータ・フィールドとしてこの情報を加えました。

Grouping requests by those fields reveal possible CPU regressions caused by turning the GEVs。

これらのフィールドによってグループ化の要求がGEVsを回すことによって引き起こされるCPUの回帰の可能性を明らかにしました。

This enables us to catch CPU regressions before they can impact performance.

これらはパフォーマンスに影響が出る前にCPUの回帰をキャッチすることを可能にします。

次は?(What’s Next?)

Dynostats and our customized cProfile, along with the monitoring and alerting mechanism we’ve built to support them, can effectively identify the culprit for most CPU regressions.

Dynostatsおよび私たちのカスタマイズされたcProfileはこれらをサポートするために、構築したモニタリングおよび警報するメカニズムに加えてほとんどのCPU再起の原因を有効に識別することができます。

These developments have helped us recover more than 50% of unnecessary CPU regressions, which would have otherwise gone unnoticed.

これらの開発したツールのおかけで見過ごされてきたであろう不要なCPU回帰の50%以上を回復する助けています。

There are still areas where we can improve and make it easier to embed into Instagram’s daily deployment flow:

私たちがそれを改善しInstagramの毎日の配備フローへ埋め込むことがより簡単にできるエリアがまだあります。

The CPU instruction metric is supposed to be more stable than other metrics like CPU time, but we still observe variances that make our alerting noisy.

CPUの命令メトリックは、CPU時間などの他の指標よりも安定であると考えられるが、まだ私達はノイズの多い差異を検出できる騒々しいアラート作る為に監視します。

Keeping signal:noise ratio reasonably low is important so that developers can focus on the real regressions.

信号維持の為に:開発者は実際の回帰に焦点を当てることができるように雑音比が適度に低いことが重要です。

This could be improved by introducing the concept of confidence intervals and only alarm when it is high.

この雑音比が高いとき信頼区間( confidence intervals )のみ導入することによって改善することができます。

For different endpoints, the threshold of variation could also be set differently.

異なるエンドポイントの場合、変動のしきい値も異なって設定することができました。

One limitation for detecting CPU regressions by GEV change is that we have to manually enable the logging of those comparisons in Dynostats.

GEV変更によってCPU再起を検知するための1つの制限は、私たちがDynostatsの中のそれらの比較のロギングを手動で有効にする必要があるということです。

As the number of GEVs increases and more features are developed, this wont scale well.

GEVs増加およびより多くの特徴の数が開発されているとともに、上手く比例しなくなります。

Instead, we could leverage an automatic framework that schedules the logging of these comparisons and iterates through all GEVs, and send alerts when regressions are detected.

その代わりに私たちはすべてのGEVsを通じてフレームワークを活用しスケジュールにこれらの比較および反復処理のログを自動的にリグレッションを行い、検出された場合にアラートを送信することを可能とします。

cProfile needs some enhancement to handle wrapper functions and their children functions better.

cProfileは、ラッパー関数やその子関数を処理するためのいくつかの機能拡張を必要としします。

With the work we’ve put into building the efficiency framework for Instagram’s web service, we are confident that we will keep scaling our service infrastructure using Python.

私たちのInstagramウェブサービス効率フレームワークを構築する仕事は、Pythonを使ってサービス・インフラストラクチャーを計り続けるである事を確信しています。

We’ve also started to also invest more into the Python language itself, and are beginning to explore moving our Python from version 2 to 3.

さらに私たちはPython言語自体にもっと投資し始めており、バージョン2〜3への移行調査も始めています。

We will continue to explore this and more experiments to keep improving both infrastructure and developer efficiency, and look forward to sharing more soon.

私たちは、インフラストラクチャおよび開発者の効率の両方を維持向上するためにこれ以上の実験を探求し続け、よりすぐに共有することを楽しみにしてます。

Min Ni is a software engineer at Instagram.

Min NiはInstagramのソフトウェア・エンジニアです。

後日談

CPUの回帰と信頼区間って何だよ!英語もっと勉強しときゃよかったぁ…と非常に嘆いている。嘆いているが、この文章が言ってる効率化の話はだいたいわかった。Instagramを使ったことがないので感触が余りわからないが5億人ユーザ(やばい)からのアクセスを処理する為にCPUが回帰する原因を探る為のCPUからの命令を読みとれるPython整のツール(Dynostats)を開発した話と、それを導入する事で50パーセント以上のCPUの回帰を回復する話なのだが、CPU自体も効率化に考慮しないと考えるとなるといよいよ、ソフトウェアなのかハードウェアなのか、知識の境界線が曖昧になってきているなと頭が痛くなる。今後安全で確立した大規模のサービスを提供するにあたっては、以前のHTTP/2のプロトコルを弄ってページの読み込み速度を上げる話にあった様にに、もっともっと下の層を弄るのが今後の流れになるのか…そうなると、エンジニア一人当たりの知識ってどんどん増えていくのかと感じた。でも今日本でCPUまで効効率化に考慮した大規模なサービスってあるのかな…?

俺はPHPで改行したかった、だけ

PHP

[PHP 改行]ってGoogle先生に聞くと

f:id:kikuchi1201:20160609122727p:plain

PHPスクリプト講座:改行処理 | そふぃのphp入門
改行文字の前に HTML の改行タグを挿入する
PHPの基本的な文法
\nで改行できない!【はずがない!】

なるほど。 どれも言ってる事は正しいが、なんだろう。
僕はドアを開ける為のカギが欲しい!と言ったにアーミナイフを渡された感は。 f:id:kikuchi1201:20160609124605j:plain

それで結論nl2br関数を使えばええんやなぁとわかったわけです。

nl2br
string nl2br(string string) 
引数に指定した文字列に含まれるすべての改行文字の前に '<br />' を挿入
して返します。

引数:
  string  対象の文字列
返り値:
  <br />挿入後の文字列

そんな事を考えていたら、遠くから「アウトプット...アウトプットせなあかんよ...?」と聞こえたのでヤケクソでQiitaに投稿した。 qiita.com

こんなショボイ内容でも見てくれる人がいるからQiita先生好き。

そしたらその日にコメントが付いてきて「まじか、改行ぞ?、ただの改行とかで悩んでいるだけのヘッポコにそんなアドバイスとか頂いていいんですか?」って、尊い気持ちになりました。
本当にありがとうございます。
きっとコメントをくれた人は僕がechoでデバックなんかで、出力された文字が見えづらいと思って気を遣ってアドバイスして頂いたと思うんですが、違います。マジで改行だけで悩んでいただけです。

そんなデバックなんて...恐れ多い...ひぇ..。

まとめ

もっとコードを書けるように頑張ります。

今読んでいる本

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)