エンジニアのひよこ_level10

【毎日更新!】新卒3年目エンジニアブログです! プログラムだけじゃなく、マネジメントとかも書いていきたい!

【PHP】関数宣言とif文を組み合わせるとどうなる?【594日目】

if文の中で関数宣言したら?

phpって、こんなコードが書けるのです。

if (false) {
    function xxx()
    {
        return true;
    }
}

これ、どうなるでしょう?

(その前に、こんなコード書く機会あるのかな?)

実行結果

1.通常実行

uirou:~$ php -a
Interactive shell

php > function test() { return 1; }
php > echo test();
1

2.falseで呼び出せないif文の中で関数を宣言したあとに、関数を呼び出す

php > $bool = false;
php > if ($bool) { function test2() { return 2; } }
php > echo test2();

Warning: Uncaught Error: Call to undefined function test2() in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1

3.if文の判定の変数を変えてから関数を呼び出す

php > $bool = true;
php > echo test2();

Warning: Uncaught Error: Call to undefined function test2() in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1

4.trueで呼び出せるif文の中で関数を宣言したあとに、関数を呼び出す

php > if ($bool) { function test2() { return 2; } }
php > echo test2();
2

考察

PHPに限らず、プログラムは基本的に上から実行される。

if文が実行されたときに、$boolがfalseなので、if文の中は実行されない。(2.)

その後に$boolが変わったとしても、プログラムの実行が巻き戻るわけではないので、
test2の宣言が起こらず、test2を実行しようとしても動かない。(3.)

公式ドキュメント

https://www.php.net/manual/ja/functions.user-defined.php

【PHP】継承した親クラスのメソッドの前後に追加処理を増やす対応【546日目】

メソッドに追加処理をしたい

class Parent
{
    public function hoge()
    {
        return 'fuga';
    }
}
class Child extends Parent
{

}

この時、コードをコピペせず、 Child::hoge()側に、追加の処理をしたい。

オーバーライド

class Child extends Parent
{
    public function hoge()
    {

        // 前に処理するならここ

        $temp = parent::hoge();

        // 後に処理するならここ

        return $temp;
    }
}

これで前後に処理を加える事ができた。

テンプレートパターンとか、beforeHogeクラスとかあったら特に必要のない技術

【カンファレンス行こう!】phperkaigiに行くべき5つの理由【531日目】

読者対象

  1. カンファレンス楽しいとか言ってる人が理解出来ない
  2. そもそもカンファレンス行ったことない

カンファレンスに行ってますかー?

みなさん!技術系イベント行ってますか!

カンファレンスとか行ってますか!

私はまだ2回しか行ってません(‘ω‘ )←←←

なんでこんな話するの?

『カンファレンスジャンキー』の皆さんは、カンファレンス行くべきだ!
って言うと思いますよね!

逆に、数回しか行ってないような、読者の皆さんと近い立場であるからこそ、
言えることがあると思います。

たった2回の参加でも、もっと行きたいと思わせるカンファレンス。
さあどうしてかを説明してみましょう!

題材

明日・明後日・明々後日の3日間だよ!
4000円で、3日間全部参加できるよ!

phperkaigi.jp

目次

以下の内容読んで、2つ興味を持ったら、上でチケットを買おう!

  1. 友達ができる!
  2. 新しい技術の『キーワード』を知る
  3. 新しい技術を知る
  4. 真面目じゃない技術話も聞ける
  5. 美味しい!面白い!楽しい!

1. 友達ができる!

『お前、技術関係ない話やんけ!』
そのとおりです!それについてはあとで説明します!

なぜこの話をするのかというと、
カンファレンスは、 『ただ話を聞きに行くだけ』の場ではないからです。

そこにいるのは、殆どPHPを使っている人です。
『あなたと共通の趣味・話題を持った人』が見渡す限りいるんですよ!?

twitterで『駆け出しエンジニアと繋がりたい』と呟いて、
山のようなユーザーから探すのではないのです。
眼の前にいる人は、全員友達になりえる人達ですよ!

私は、ここで出来た友達とは、今でも『困ったことを共有・相談』したり、『切磋琢磨する仲間』になりました。
友達を作るって良いですよ!

2. 新しい技術の『キーワード』を知る

『知らないことは調べるし、行かなくていいや』

そのとおりです!知らないことは調べればわかるんです。

でも、そもそも存在を知らないものを知るのって、難しくないですか?
ニュースサイトとかで、流行りのキーワードを探す?

『BEAR.Sunday』『Swoole』『cakephp/chronos』

聞いたことのない単語がある?
『知らないを知る』のに、カンファレンスは便利です。
そこで、『なんだこれ?』って思ったら、その後調べれば良いのです。

そこにいる人達は、既に経験者。
しかも便利だから紹介してるわけなのです!これは知らないままではいられない!

3. 新しい技術を知る

『新しい技術勉強するのしんどい』

わかるぅ!

でも、ニュースサイトとかで、情報収集する必要なんてないのです。
そう、カンファレンスに行けばね!

『テストコード』『抽象化』『CI』

これら全て理解してますか?あるいは興味ある?

さあ、行ってみましょう。
面倒な勉強も、その場に行って席に座れば、気づいたら知識が手に入る!

4. 真面目じゃない技術話も聞ける

『真面目じゃない話になんの意味が?』

違うんですよ。プロが全力でおふざけした話って面白くないですか?
しかも、さり気ないテクニックから、学べることありませんか?

真面目じゃない話を調べるって難しい、そんな貴重な話も聞ける。
懇親会とかで聞く話は、真面目で面白い話から『なんでそこ全力尽くした』みたいな話まで、
普段聞けない幅広い面白い話が聞けますよ・・・!

5. 美味しい!面白い!楽しい!

『何言ってるのこいつ』

待って、帰らないで、これだけ聞いて!

今までの話は『技術・交友関係』とか、役に立つというお話だったじゃないですか。

カンファレンスは『これらを楽しんで手に入れる』ことができるんですよ。

だって、これいわゆる『お祭り』みたいなものですよ?
たくさんの人が全力で楽しく学びのある会にしようと用意してるんですよ?

面白くないわけないです!

あなたは、カンファレンスに行くことで、学びながら最高の楽しい時間を過ごすのです。
あと懇親会でめっちゃ美味い飯食えるんです。新たにできた仲間たちと共に。

ほら、楽しんで学べる。一石二鳥ですよ!

『良さわからん』

それは失礼いたしました!!!
ただ、これだけ伝われば良いです。

『カンファレンスは、勉強しにいくためだけ、じゃなくてもいい』

得られるものも大きく、満足感もあると思います。
もし『お前が何言ってるかわからん』でも、『お前はとりあえず楽しかったんだな』がわかればいいです。

そして、『よくわからないが、行ってみるか』でも良いです。

絶対楽しいです。保証します。
違うなと思ったら私も会場にいますので、twitterで呼び出してくださいお友達になりましょう。反省します。

【PHP】returnを返さなかったときはどうなる?voidじゃない?【512日目】

こんなプログラムがあったとき

public function foo($key, $array)
{
    if($key != null) {
        return $array[$key];
    }
}

このプログラム、もし$keyがnullだったとき、returnを通らないです。どうなるでしょう。

return nullされる

http://php.net/manual/ja/functions.returning-values.php

return を省略した場合は NULL を返します。

ということで、return nullされます。
すると、きっと2つ程疑問が出ると思います。

voidじゃないの?

PHP: 新機能 - Manual

返り値の型として void が導入されました。返り値の型を void と宣言した関数は、関数内での return 文を省略するか、あるいは空の return を使う必要があります。 void 関数から NULL を返すことはできません。

void 関数の返り値を使おうとした場合はその値は NULL と評価されます。 警告は発生しません。警告を発生させると、一般的な高階関数の利用にも影響するからです。

ざっくりいうと、

『voidという値は存在しなくて、voidとは意味のない値を指す』
『意味のない値なので、returnがvoidのときは、そのreturn値を使うことはできない』

return nullは明記しなきゃいけないの?

public function foo($key, $array)
{
    if($key != null) {
        return $array[$key];
    }
    return null;
}

こう書かなければいけないというのは、PSRなどで決められていません。
但し、極力明記するべきだと思います。

可読性も上がりますし、そもそもコードで検討忘れだったりするかもしれません。
明記することで、関数に対する意味などと正しく定義しやすくなります。

あるいは、以下のように書き換えることもできます。

public function foo($key, $array)
{
    if($key == null) {
        return null;
    }
    return $array[$key];
}

極力、他の人のためにも、明記するほうが良いでしょう。

【PHP】newでインスタンス作成時、メソッドチェーンできないとき【510日目】

メソッドチェーンできない!?

new Collection()->push(3);

これは動かない。

インスタンス化に()をつける

(new Collection())->push(3);

これでOK!

これに15分詰まった・・・

【php】イミュータブルなクラスのフィードバック対応をしてみる【498日目】

昨日こんな記事書きました

www.nyamucoro.com

これで、イミュータブルっぽいクラスを作りました。

で、最初にフィードバックをもらった方に、あの記事を見てもらったら、こんな記事をおすすめしていただきました。

参考記事

qiita.com

qiita.com

あれー?昨日の記事よりわかりやすくて、内容が入ってるよー\(^o^)/

さすがsuinさんですね……!

実装書き換えてみる

class User {
    private $name;
    private $status;

    public function __construct(string $name, Status $status) {
        $this->name = $name;
        $this->status = clone $status;
    }

    public function setStatus(Status $status) {
        $new_instance = clone $this;
        $new_instance->status = clone $status;
        return $new_instance;
    }

    public function setName(string $name) {
        $new_instance = clone $this;
        $new_instance->name = $name;
        return $new_instance;
    }
}

疑問

privateなフィールドなのに、なんでcloneで別インスタンス作ったのに、フィールド値が書き換えられるの……?

PHP: オブジェクトのクローン作成 - Manual

PHP 7.0.0 以降では、新しくクローンしたオブジェクトのメンバーに、作成したその式の中でもアクセスできるようになりました。

し、しらなかったー!!!

ってことで、無事にいい感じのイミュータブルっぽいクラスが出来上がりましたねたぶん!やったー!

【PHP】イミュータブルなクラスを作ってみる【497日目】

始まりは突然に。

昨日のブログにツッコミが入りました(‘ω‘ )

なるほどたしかに!
changeStatusというフィールド値をUserに持たせたほうが、Userのフィールド値とか状態に触れる知識を外部に持たせないって出来ますね。
状態に対する関心も、あちこちに分散しない……!

ってことで、頂いたアドバイスを自分なりに解釈して実装してみる。
(で、出来たらちょっとレビューをお願いしてみる・・・!)

頂いたアドバイス

実装

class User {
    private $name;
    private $status;

    public function __construct(string $name, int $status) {
        $this->name = $name;
        $this->status = $status;
    }

    public function __set($name, $value) {
        throw new Exception('This object can't be set field value.');
    }

    public function setStatus(int $status) {
        return new User($this->name, $status);
    }

    public function setName(string $name) {
        return new User($name, $this->status);
    }
}

応用

フィールド値にインスタンスを持つ場合。
前に勉強したやつ実装してみる。

【デザパタ自作】イミュータブルパターン(インスタンス内包対応)【266日目】 - エンジニアのひよこ_level10

class User {
    private $name;
    private $status;

    public function __construct(string $name, Status $status) {
        $this->name = $name;
        $this->status = clone $status;
    }

    public function __set($name, $value) {
        throw new Exception('This object can't be set field value.');
    }

    public function setStatus(Status $status) {
        return new User($this->name, clone $status);
    }

    public function setName(string $name) {
        return new User($name, clone $this->status);
    }
}

感想?

こんな感じ・・・?
これで、たぶん値の変更は不可能になって、データは新しいオブジェクトを返すようになっているはず・・・?

使用感としても、ユーザーは内部に何を持ってるかを意識せず、関数だけ意識できる気がする。

// 全部違うインスタンスになる。たぶん変更出来ないはず
$user = new User('youkan', new Status(false));
$user = $user->setName('Uiro');
$user = $user->setStatus(new Status(true));

Tell Don't Askの観点とか知らない言葉が出てきてるので、いつか勉強したいというか、
早くぺちおぶ行きたいのに、Laravel JP Conferenceとかイベントに被るから行けなかった・・・(登壇者だからどうあがいても行けなかった)

また今度こそ、行きたいね・・・!