PHP復習

環境

mfham@mac ~/w/php_study> php -v
PHP 7.4.5 (cli) (built: Apr 23 2020 23:35:46) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

インスタンス化する・しないでの挙動

<?php

class Human
{
    const COUNTRY = ‘jp’;

    public static $hobby = 'sleeping';
    public        $job   = 'developer';
    private       $name  = 'mfham';

    public function public_hello()
    {
        echo 'public_hello';
    }

    private function private_hello()
    {
        echo 'private_hello';
    }

    public static function public_static_hobby()
    {
        return self::$hobby;
    }

    public static function public_job()
    {
        return self::$job;
    }
}

// インスタンス化する
$human = new Human();

echo $human->job;  // => ‘developer'
echo $human->name; // Fatal error: Uncaught Error: Cannot access private property Human::$name

$human->public_hello();  // => ‘public_hello'
$human->private_hello(); // PHP Fatal error:  Uncaught Error: Call to private method Human::private_hello() from context ‘'

// インスタンス化しない
echo Human::COUNTRY; // ‘jp'
echo Human::$hobby;  // ’sleeping'
echo Human::$job;    // Fatal error: Uncaught Error: Access to undeclared static property: Human::$job 

echo Human::public_static_hobby(); // ’sleeping’
echo Human::public_job();          // PHP Fatal error:  Uncaught Error: Access to undeclared static property: Human::$job

オーバーライド

<?php

class ParentClass
{
    public function func1($v)
    {
        echo ‘hello parent';
    }
}

class ChildClass extends ParentClass
{
    public function func1($vv)
    {
        echo $vv;
    }
}

// オーバーライド
$child = new ChildClass();
$child->func1('foo’); // ‘foo’;
<?php

class ParentClass
{
    public function func1($v)
    {
        echo ‘hello parent';
    }
}

class ChildClass extends ParentClass
{
    public function func1()
    {
        echo ‘hello child';
    }
}

// 引数の違うオーバーライドはWARNING
$child = new ChildClass(); // PHP Warning:  Declaration of ChildClass::func1() should be compatible with ParentClass::func1($v)
$child->func1(); // ‘hello child’

finalキーワード

<?php

class ParentClass
{
    public final function func1()
    {
        echo 'hello parent';
    }
}

class ChildClass extends ParentClass
{
    public function func1()
    {
        echo 'hello child';
    }
}

$child = new ChildClass(); // PHP Fatal error:  Cannot override final method ParentClass::func1()

abstract

インスタンス化できない。

<?php

abstract class ParentAbstract
{
    abstract public function func1();

    public function func2()
    {
        echo 'parent func2';
    }
}

$parent = new ParentAbstract(); // PHP Fatal error:  Uncaught Error: Cannot instantiate abstract class ParentAbstract

abstractキーワードをつけたメソッドは実装する必要がある。

<?php

abstract class ParentAbstract
{
    abstract public function func1();

    public function func2()
    {
        echo 'parent func2';
    }
}

class ChildClass extends ParentAbstract
{
    public function func2()
    {
        echo 'child func2';
    }
}

$child = new ChildClass(); // PHP Fatal error:  Class Child contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ParentAbstract::func1)

interface

インスタンス化できない。

<?php

interface ParentInterface
{
    public function func1();
}

$parent = new ParentInterface(); // PHP Fatal error:  Uncaught Error: Cannot instantiate interface ParentInterface

メソッドを実装しなければいけない。

<?php

interface ParentInterface
{
    public function func1();
}

class ChildClass implements ParentInterface
{
}

$child = new ChildClass(); // PHP Fatal error:  Class Child contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ParentInterface::func1)

遅延静的束縛

<?php

class ParentClass
{
    public function hello1()
    {
        self::hi1();
    }

    public function hello2()
    {
        static::hi2();
    }

    public static function hi1()
    {
        echo 'parent hi1';
    }

    public static function hi2()
    {
        echo 'parent hi2';
    }
}

class ChildClass extends ParentClass
{
    public static function hi1()
    {
        echo 'child hi1';
    }

    public static function hi2()
    {
        echo 'child hi2';
    }
}

$child = new ChildClass();

$child->hello1(); // ‘parent h1'
$child->hello2(); // ‘child h2'

Flutter(準備)+Mac+fish

使うまでにやったことメモ。


# Flutter
1. download
https://flutter.dev/docs/get-started/install/macos

2.
mfham@mac ~> mkdir work/flutter_dev
mfham@mac ~> cd work/flutter_dev/

3.
# バージョン上がってもすぐに対応できるかと思ってgitのほうにした
mfham@mac ~/w/flutter_dev> git clone https://github.com/flutter/flutter.git -b stable

4.
mfham@mac ~/.c/fish> echo $PATH
/Users/mfham/.phpbrew/php/php-7.4.5/bin /Users/mfham/.rbenv/shims /Users/mfham/.embulk/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin

mfham@mac ~/w/flutter_dev> set -U fish_user_paths ~/work/flutter_dev/flutter/bin $fish_user_paths

mfham@mac ~/w/flutter_dev> echo $PATH
/Users/mfham/work/flutter_dev/flutter/bin /Users/mfham/.embulk/bin /Users/mfham/.phpbrew/php/php-7.4.5/bin /Users/mfham/.rbenv/shims /usr/local/bin /usr/bin /bin /usr/sbin /sbin

5.
mfham@mac ~/w/flutter_dev> which flutter
/Users/mfham/work/flutter_dev/flutter/bin/flutter

# iOS
6.
Xcodeはインストール済み

7.
mfham@mac ~/w/flutter_dev> sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
Password:
mfham@mac ~/w/flutter_dev> sudo xcodebuild -runFirstLaunch
Install Started
1%.........20.........40.........60.........80.........Install Succeeded

8.
mfham@mac ~/w/flutter_dev> sudo xcodebuild -license

By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel] agree

You can view the license agreements in Xcode's About Box, or at /Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf

mfham@mac ~/w/flutter_dev>

9.
起動確認
mfham@mac ~/w/flutter_dev> open -a Simulator

10.
mfham@mac ~/w/flutter_dev> rbenv versions
  system
  2.3.1
  2.5.3
  2.6.5
* 2.7.0 (set by /Users/mfham/work/flutter_dev/.ruby-version)
  jruby-9.1.15.0
mfham@mac ~/w/flutter_dev> sudo gem install cocoapods
mfham@mac ~/w/flutter_dev> pod setup
Setup completed

# Android
11.
https://developer.android.com/studio
Version3.6.3

12.
起動
Install Type:Standard
Select UI Theme:Darcula
・HAXMインストールの許可のとき拡張機能がブロックされたので、「システム環境設定->セキュリティとプライバシー」で許可した

3.6以降は古いバージョンのAndroid SDK Toolsを手動で追加する必要があるとマニュアルに書かれてあるのでその通り対応する。
Preferences->Appearance&Behavior->System Settings->Android SDK
SDK Toolsタブをクリック、Hide Obsolete Packagesのチェックを外す。
するとチェックできる項目が増え、Android SDK Tools (Obsolete)にチェックを入れる(もともと入ってた)。
OKをクリック。
カラーがDarculaじゃなくなったぞ・・・?
=> Editor->Color SchemeでDarculaに変更。Defaultになってた。

13.
Set up the Android emulator
https://developer.android.com/studio/run/emulator-acceleration#vm-mac
->OK

# Set up an editor
14.
Visual Studio Codeを使う
https://flutter.dev/docs/get-started/editor?tab=vscode
手順通り。

15.
ここまででdoctor確認。
mfham@mac ~/w/flutter_dev> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G4032, locale ja-JP)

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    ✗ Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
[!] Android Studio (version 3.6)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] VS Code (version 1.41.1)
[!] Connected device
    ! No devices available

! Doctor found issues in 3 categories.

16.
Android licenses not accepted
↓
mfham@mac ~/w/flutter_dev> flutter doctor --android-licenses
acceptする

Flutter plugin not installed;
Dart plugin not installed;
↓
https://flutter.dev/docs/get-started/editor?tab=androidstudio
Flutterプラグインをインストールする(Dartもついでにインストールされる)
その後のdoctorの結果
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G4032, locale ja-JP)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
[✓] Android Studio (version 3.6)
[✓] VS Code (version 1.41.1)
[✓] Connected device (1 available)

• No issues found!



17.
https://flutter.dev/docs/get-started/test-drive?tab=vscode
動いた

Create Android emulatorで次のエラーが出る

No suitable Android AVD system images are available. You may need to install these using sdkmanager, for example: sdkmanager "system-images;android-27;google_apis_playstore;x86"

16でAndroid StudioでFlutterプラグインをインストールしたあと、
Android Studio起動後にStart a new Flutter projectを選択してプロジェクトを作成する。
https://flutter.dev/docs/get-started/test-drive?tab=androidstudio
ナビゲーションバーのTools->AVD Manager->Create Virtual Device
Pixel 2 (適当)-> RecommendedにあるR (適当)のDownloadをクリック
(Flutterプラグインをインストールしていないと表示されなかったので混乱した)
↓
Visual Studio CodeでFlutterプロジェクトを開くと、右下からPixel2を選択できるようになった。
↓
このエラーが出た。
次のSOFにあるように、Android StudioからAVD Managerを開いて一度Stopさせて、その後Visual Studio Codeから再度Pixel2を選択するとうまくいった
https://stackoverflow.com/questions/55677874/failed-to-launch-emulator-error-emulator-didnt-connected-within-60-seconds

mac+phpbrew+Symfony+fish

前準備

# 入れておかないとphpbrew, Symfonyインストール時にエラーが起きたので
# 少なくともlibxml2 zlib bzip2 libiconvは必要だったはず
~> brew install libxml2 zlib bzip2 libiconv mhash mcrypt curl libedit gd

# git gzipも必要だと思う

fish

# fish 2.7.1だと~/.phpbrew/phpbrew.fishで次のエラーが起きたので、fishのバージョンを上げる
# Unsupported use of '&&'. In fish, please use 'COMMAND; and COMMAND'.
~> brew upgrade fish
~> fish --version
fish, version 3.1.0

GNU parallel causes "Unsupported use of '&&'. In fish, please use 'COMMAND; and COMMAND'." · Issue #5582 · fish-shell/fish-shell · GitHub

phpbrew

# https://github.com/phpbrew/phpbrew
~> curl -L -O https://github.com/phpbrew/phpbrew/releases/latest/download/phpbrew.phar
~> chmod +x phpbrew.phar
~> mv phpbrew.phar /usr/local/bin/phpbrew

~> phpbrew init

# たしかinitしたタイミングでconfig.fishに勝手にphpbrew.fishのsource記述が追加されたけど、
# 絶対パスだったので相対パスに直した
~> emacs ~/.config/fish/config.fish
source .phpbrew/phpbrew.fish

# 利用可能バージョン一覧
~> phpbrew known
# Symfony利用時にiconv拡張が必要だったのでdefaultに加えて追加する
# https://github.com/symfony/demo を利用するためにsqlite拡張も追加
~> phpbrew install 7.4.5 +default +iconv +sqlite

~> phpbrew use php-7.4.5
~> phpbrew list
* php-7.4.5
~> php -v
PHP 7.4.5 (cli) (built: Apr 18 2020 20:48:16) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
~> phpbrew system php-7.4.5 #これやらないと毎回phpbrew useで指定しないといけないかも?

その他

# valiants確認
~> phpbrew variants
# ロードされている拡張、利用可能な拡張確認
~> phpbrew extension

composer, Symfony

Installing & Setting up the Symfony Framework (Symfony Docs)

~> brew install composer

~> composer create-project symfony/skeleton symfony_study
~> cd symfony_study/
~> php bin/console --version
Symfony 5.0.7 (env: dev, debug: true)

~> curl -sS https://get.symfony.com/cli/installer | bash
~> mv /Users/mfham/.symfony/bin/symfony /usr/local/bin/symfony

# Webサーバー起動
~> symfony server:start

f:id:mfham:20200419154407p:plain
Webサーバー起動後画面

かっこいい

DNSを日常生活で例える

ストーリー

座席
社長 佐藤さん 7階711
A事業部長 市川さん 5階501
A事業部B開発グループ長 南さん 4階433
A事業部B開発グループ 星さん 4階455

根岸さん「mfhamさん、A事業部B開発グループ 星さんの座席、どこかわかりますか・・・?」
mfham「えーっと・・・探すね!」

@7階711
mfham「社長、A事業部B開発グループ 星さんの座席 を教えてください!」
佐藤さん「A事業部のことは A事業部長 市川さん に聞いてください。場所は5階501です。」
mfham「わかりました!」

@5階501
mfham「市川さん、A事業部B開発グループ 星さんの座席 を教えてください!」
市川さん「B開発グループのことは B開発グループ長 南さん に聞いてください。場所は4階433です。」
mfham「わかりました!」

@4階433
mfham「南さん、B開発グループ 星さんの座席 を教えてください!」
南さん「4階455です。」
mfham「ありがとうございます!」

mfham「星さんの座席は4階455だよー!」
根岸さん「ありがとうございます!」

~ 10分後 ~
根岸さん「あの・・・A事業部B開発グループ 星さんの座席ってどこでしたっけ・・・?」
mfham「4階455だよ!(私は記憶力がいいのである)」
根岸さん「ありがとうございます!」

解説

社長:ルートサーバー
根岸さん: スタブリゾルバー(Stub resolver)
mfham: フルリゾルバー(Full resolver)
市川さん、南さん: 権威サーバー(Authoritative server)
10分後の問い合わせにすぐ座席を返している状態: キャッシュ

合わせてチェックしたい

https://www.internic.net/domain/named.root
ヒントファイル。

RFC 7719 - DNS Terminology
DNS用語。

DNSがよくわかる教科書
読みやすい、理解しやすい、です。
読み終えて、2周目突入中です。

Basics_of_DNS_that_application_engineers_should_know - Speaker Deck
JPRSさんの本と一緒に。

DNSの仕組みの基本を理解しよう:DNSの仕組みと運用(1) - @IT
あとでしっかり目を通してみる。

DNS関連RFC一覧 - Qiita 読みたくなる願望・・・

AWS障害とdig

今のところこの半期で一番読んでためになった、楽しいという感情にもしてくれた本。

すらすら読めるし、用語の定義についても丁寧に説明してくれている。

digコマンドを使った名前解決の話、これまでいかに自分が雰囲気でdigを使っていたかというのを感じさせられた。

私と一緒に・・・ペアdigしませんか・・・?

DNSがよくわかる教科書

DNSがよくわかる教科書

AWS障害

AWS障害、大部分の復旧完了 原因は「サーバの過熱」 - ITmedia NEWS

サーバーでgit pullができなくなった。

そのときに上記の本で学んだことを使って原因が起きていそうなところを推測でき、その推測が当たっていたのが嬉しかった。

学んだことが活かせたときにセロトニンが分泌される気がする。

まとめ

幸せの名前解決をしてください(´;ェ;`)

validatorで勉強シリーズ

Vivaldiを使っておりまして、「W3Cのサービスによる検証」が手軽にできるのでこれを使っていろいろなサイトを見てみれば勉強になるんじゃないかと思ったのでやってみるシリーズ。

The W3C Markup Validation Service

題材

AbemaTV|国内最大の無料インターネットテレビ局

普段からよく見ています。
ドラ恋やオオカミくん、今ならかぐや姫についてワーキャー話したけど周りに見ている人がほぼいないので悲しいです。

結果

[Warning] Text run is not in Unicode Normalization Form C.

window.__REHYDRATE__ = ...に対してWarning。
誤認識している気がしているのでスルー。
ただ、Unicodeについて勉強するいい機会。次の2つおよび参考にされているリンクは見てみます。
ActiveSupport::Multibyte::Unicodeは仕事で使えるかもな・・・
「Text run is not in Unicode Normalization Form C.」というHTML Validation Serviceの警告について: 小粋空間 文字列の表記揺れをUnicode正規化で簡単に解決する方法 - Qiita

[Error] A meta element with an http-equiv attribute whose value is X-UA-Compatible must have a content attribute with the value IE=edge.

chrome=1がついているのがErrorの原因のよう。 あとで調べて記事更新する。
HTML 5.2: 4.2. Document metadata
html - Bad value X-UA-Compatible for attribute http-equiv on element meta - Stack Overflow

[Warning] The type attribute for the style element is not needed and should be omitted.

style要素のtype属性は必要なく省略されるべきとのこと。なるほど。
MDNにも現代では含める理由がないと書かれています。
HTML 5.2: 4.2. Document metadata

Active Supportメモ

Active Supportのn.monthn.yearの挙動が5.0系、5.1系以上で異なっていました。 バージョン上げるときにバグをうまないようメモしておきます。

https://github.com/rails/rails/blob/5-1-stable/activesupport/CHANGELOG.md

# 5.0.7.2
https://github.com/rails/rails/blob/5-0-stable/activesupport/lib/active_support/duration.rb#L14-L15
SECONDS_PER_MONTH  = 2592000  # 30 days
SECONDS_PER_YEAR   = 31557600 # length of a julian year (365.2425 days)

> 1.month.to_i
=> 2592000

> 1.year.to_i
=> 31557600

> 12.months == 1.year
=> false

> 30.days == 1.month
=> true
# 5.1.7
https://github.com/rails/rails/blob/5-1-stable/activesupport/lib/active_support/duration.rb#L111-L112
SECONDS_PER_MONTH  = 2629746  # 1/12 of a gregorian year
SECONDS_PER_YEAR   = 31556952 # length of a gregorian year (365.2425 days)

> 1.month.to_i
=> 2629746

> 1.year.to_i
=> 31556952

> 12.months == 1.year
=> true

> 30.days == 1.month
=> false

CHANGELOG.mdに次のように書いてありますね。

The value of 365.2425 days in Gregorian year is more accurate as it accounts for every 400th non-leap year.

グレゴリオ暦 - Wikipedia

ユリウス暦 - Wikipedia

面白い〜