20201021のPHPに関する記事は7件です。

Webエンジニアになるにあたっての学習方法

【対象者】

これからWebエンジニアやってみようかなって人

【まえがき】

初めまして、Webエンジニアになって早6年目。
Qiitaは読む専門だったのですが、ありがたいことに1年半ほど前からオンラインスクールの講師をやらせてもらってます。
その中で、「自分もそうだったなぁ」と感じることが多く、自分の今の目の前の方だけではなく
今もどこかで、独学で悩んでいるエンジニアの方の助けになればと思い、記述をしてみようと思った次第です。
これはあくまで私の主観ですので、先輩エンジニアの方やスーパーエンジニアの方は、
またそこら辺のエンジニアがなんか言ってるわ、と見逃すか、暖かい心でコメントください。

【経歴と自己紹介】

本業は、SESでプログラム組んでます。
「エンジニアになりたいけど誰も未経験なんて雇ってくれないわ、よし!一人でやろう」
で、フリーランスで3年実務経験(笑)を積んだ後に、会社員として3年目、現在に至ります。
使用言語は今はPythonでApi作ったり、解析やったりしてます。
元々はPHPでWebサービスばっかり作ってました。
言語にこだわりは持たないタイプ。器用貧乏。Mr.中途半端。

【先に結論(忙しい人向け)】

全部は覚えなくていいんだよ。
正解はないよ、ルールはあるけど。

【本編】

開発は覚えることが多いです

他の方も言われてるかと思いますが、まずは暗記することをやめてください
もちろん覚えるのであれば覚えてもらっても構わないですが、効率がものすごく悪いです。

HTMLから学習をしはじめたとして、HTMLタグ109個全てを覚える必要はないということです。
ここで誤解しないで欲しいのは、知識としては「こういうタグがあるんだーへー」と何回かは目を通してください。
あとは、自分でサイト制作を数こなしていくうちによく使うタグであったり書き方を確立すべきです。

初めて作る料理をまずは、レシピ通りに作ってそれから繰り返しやっていく中で自分の味付けを確立するのと感覚は似てると思います。

ここで大事なのは、
書き方を覚える必要はないのです。やり方を覚えてください。

HTMLをかくときはまず、

1.HTML宣言が必要
2.必要に応じてmetaタグを書く
3.CSSを読み込む
4.bodyタグの中に書く
5.header main footerで大きく分けて全体を詰めていく。

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sample</title>
</head>
<body>
    <header>
        <!--ナビゲーションとかロゴとか-->
    </header>

    <main>
        <!--ここにメインの内容を持ってくる-->
        <section>
            <!--必要に応じてSectionなどで小分け-->
        </section>
    </main>

    <footer>
        <!--著作権表示のコピーライトとかサイトリンクとか-->
    </footer>

</body>
</html>

これさえ覚えてればあとは、「このタグどうやって書くんだっけ」となっても自分のやりたいことを調べれば大丈夫です。

HTMLを学習したいのであれば、おすすめはある程度タグの理解が深まった段階で、ダミーサイトもしくはコピーサイトを作成してみることです。
ただ、コピーサイトについてはサイト公開は必ずしないようにしてください。

フロントコーディングで一番難しいのは書き方に正解がないということ。
ただ正解がないからってめちゃくちゃにやっていいというわけではないので
せめてもの基礎的なコーディングルールぐらいは覚えるようにしてください。

  • idは重複NG
  • h1は1ページに一つまで
  • Class名はわかりやすく的確に
  • 鬼のdivコーディングをしない

...etc

料理で例えるなら、
ポテトサラダに玉ねぎ入れる派入れない派(私は入れる派)
焼き鳥はタレ派塩派(私は塩派)

時にはコーディングに関する暗黙のルールの当たり前をぶつけられる時だってあります。
そんなときは、よっぽど変な事じゃなければ、なるべくそれに従うようにしてもらえれば良いのかなと思っています。

そんな衝突をなくすために様々な記法なども存在するので目を通してもらえれば良いと思います。

【PHPとかバックエンド側の場合】

バックエンドプログラミング(ここではPHP)の場合も考え方は同じです。

Progateさんや、ドットインストールさんなどでとりあえず基礎は学んだけど、アプリの作り方がわからないって方多いと思います。
私もそうでしたし、めちゃくちゃ困りました。

TODOアプリを作成する例でご説明していきます。
POST(登録・更新)、GET(検索)、ログイン制御、SQLでのCRUDがあるのでこれできたら正直PHPはできたと言っても過言でh...

プログラム抜きでまずはHTMLと同様に全体を考えて固めます。

今回必要な機能(最低限)

  • 予定、開始日時、終了日時を入力・登録できる。
  • 登録したら予定が一覧で確認できる。

大枠を細分化と流れを構築する

ここは若干、経験が入ってきますが気合で慣れてください。

  • 予定、開始日時、終了日時を入力・登録できる

    • 1. 予定、開始日時、終了日時を入力できるようにHTMLを組む
    • 2. ボタンを押されたら、送信された内容を受け取る
    • 3. 受け取った値がプログラムが欲しい値か検証する
    • 4. 問題なければ、DBに登録する
    • 5. 結果を返す(成功・失敗)
  • 登録したら予定が一覧で確認できる。

    • 1. 登録された内容を表示するためのHTMLを組む
    • 2. 登録されているデータをDBから取得する
    • 3. 取得した結果を表示する
<?php


// 毎回POSTがあるか確認するのが面倒なので処理をまとめておきます。
function post($key) {
    // 指定した値を受け取れなかった時
    if (empty($_POST[$key])) {
        //NULLを返却してエラーを回避
        return NULL;
    }

    //ユーザから受け取った値をサニタイズ化して返却
    return htmlspecialchars($_POST[$key]);
}

// 毎回設定書くのはめんどくさいので接続処理はまとめときます。
function pdo() {

    // DB接続設定
    $dbh = "mysql:host=localhost;dbname=todo;charset=utf8";
    $user = "hoge";
    $pass = "hoge";

    $pdo = new PDO($dbh,$user,$pass);

    return $pdo;
}

// データ登録処理
function insert($data) {
    try {

        // 設定の呼び出し
        $pdo = pdo();

        // ダメだったらエラー
        if ( ! $pdo) {
            throw new Exception("DB接続エラー");
        }

        // SQLの処理を書く
        $sql = <<<QUERY
INSERT INTO
todo(
start_at,
end_at,
schedule,
) VALUES(
:start_at,
:end_at,
:schedule
)
QUERY;

        // SQLの準備
        $stmt = $pdo -> prepare($sql);

        // プリペアードステートメントを使用してプレースホルダーと実際の値の紐付け
        foreach($data as $key => $val) {
            $stmt -> bindValue($key,$val,PDO::PARAM_STR);
        }

        // SQL実行
        $result = $stmt -> execute();

        // データ登録失敗(ここは書いても書かなくても好みだと思います。)
        if ( ! $result) {
            throw new Exception("データ登録失敗");
        }

        // 値の返却
        return $result;

    } catch (PDOException $e) {
        exit($e -> getMessage());
    }

}

// 値のあるなし検証
function check_val($val) {
    if (empty($val)) {
        return FALSE;
    } 

    return TRUE;
}

/* ==========ここからTODOのデータ追加処理========== */

// 値の受け取り

// キーを:つきにしているのは、bindValueで紐付けを楽にするため。
$data = array(
    ":start_at" => post("start_at"),
    ":end_at"   => post("end_at"),
    ":schedule" => post("schedule")    
);

// 全部必須項目にするとして値があるかどうかは検証しておく。 
foreach ($data as $val) {
    // 値がなければ入力メッセージを作る
    if ( ! check_val($val)) {
        $error = "値を入力してください。";
        break;
    }
}

// errorがあればデータを追加せずにエラーを表示
if ( ! empty($error)) {
    echo $error;
    exit();
}


$result = insert($data);

echo "値を追加しました。";
exit;

細かいところは省きましたがおおよそこんな感じです。
あとはそれぞれの書き方を調べながら組んでいけばOKです。
MVCも使わずにユーザ定義関数だけでまとめてるので、読みやすいかと思います。

小さく作って大きく育てる

そんな意識を持ってもらえればきっと知らず知らずのうちにプログラムの流れを掴めるようになると思います。

さいごに

プログラミングの世界って明確な答えが最初はなくて難しいと思います。
たどり着きたいゴールはみんな同じでもやり方は十人十色
基礎ある程度やったよって人はまずはミニマムアプリケーションを作成してみると良いかと思います。
これからは、HTML ~ PHPまでこれやっとけみたいなやつ書くようにしていきます。

この投稿がいつか誰かの気持ちを軽くできることを願っています。
最後まで、読んでいただきありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel:バリデーションの検証ルール

【概要】

1.バリデーションの主な用意されている検証ルール

2.その他の用意されている検証ルール

3.開発環境

1.バリデーションの主な検証ルール

app/Http/Controllers/XXXXController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class XXXXController extends Controller
{
  public function post(Request $request)
    {
      $validate_rule = [
        'name' => 'required' , #---❶
        'mail' => 'email' , #---❷
        'age' => 'numeric|between:0,150' , #---❸
        ];
    }
}

❶:"required"は、必須項目であることを示します。値がnull,空文字列(NULLとは違う)、
❷:"email"は、形式チェックのみで実際に使用できるかどうかはチェックしません。
❸:"numeric"は、値が数値であるかをチェックします。"integer"は整数であるかをチェックします。"between:最小値,最大値"は、最小値〜最大値の範囲内であるかをチェックします。"|"を使用することで複数検証ルールを実装することができます。

※今回はバリデーションの説明なので、 return view('XXXX.index' , ['XXX'=>'XXXX']);等々の記載は省いています。

2.その他の検証ルール

=> 'alpha' #入力したすべてがアルファベットがチェック
=> 'alpha-num' #入力したすべてがアルファベットと数字かチェック
=> 'boolean' #true,false,0,1といった真偽値可動かをチェック
=> 'filled' #空欄でないかをチェック
=> 'present' #値が存在しているかのチェック。値はnull存在していれば問題なし。
=> 'string' #文字列かチェック
=> 'unique:テーブル名, カラム名' #データーベースにあるテーブルの該当カラムと重複していないかのチェック。emailと併用して使うことが多いです。


3.開発環境

PHP 7.4.10
Laravel 8.9

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Slim4をサブディレクトリで走らせる方法

軽量なPHPフレームワークで有名なSlim4を、ルートディレクトリより下のディレクトリで走らせる方法です。このページを元に書いてます。つまり雑な英訳≒要約です。

次のようにApacheサーバーが動いているとします。

  • Rootディレクトリが/var/www/public/
  • URLがhttps://example.com/

こんなウェブサイトがあったときに、

  • Slim4を/var/www/public/test/ディレクトリに展開して、
  • https://example.com/test/としてアクセスしたい。

そんな状況です。

Apacheの設定

/var/www/public/test/.htaccessを作成します。

# Rewrite URL
RewriteEngine on

# redirect to /index.php
RewriteBase /test
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php [L,QSA]

ポイントはRewriteBase /testを追加すること。
それとRewriteRuleのファイル名をindex.phpとすること(最初にスラッシュを書かない)。
かな。

Slim4の設定

次に、/var/www/public/test/index.phpで、Slim4を動かします。

ここでアプリに、サブディレクトリで走っていることを教えてあげます。

$app = AppFactory::create();
$app->setBasePath('/test'); // ←この一行を追加!

$app->setBasePath()関数でサブディレクトリ名を指定します。

これで、/testを書かずにルート設定などが可能になります。

自動でBasePathを取得する方法

ベースパスを自動で取得する方法が参考ページにありましたので、興味ある方はそちらを御覧ください。

最後に

ウェブサイトの一部だけをSlim4で作る・作り直すというケースがありそうかなと思って調べてみました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

全プログラミング言語の用語整理

言語自体の整理

1. 動的型付けのプログラミング言語

プログラムでは様々な「型」を扱います。例えば、文字列値と整数値と少数値は異なる型です。この他にも様々な型があり、プログラムにミスがあって異なった型を指定しまう事でエラーを発生させることがあります。

動的型付けのプログラミング言語の場合はプログラムを実行時に型検査を行います。厳格なエラーを対処しなくてもプログラムは動作するので初心者には学びやすい言語が多くなっています。しかしその反面、非常に分かりにくい不具合を作り込んでしまう可能性もあります。

言語名 F-S Initial release 起源
JavaScript FS HTML と合わせて使用して動きのある WEB ページを開発するために使用 1995
Ruby FS 日本人により開発された。可読性を重視した構文 1995
Python FS 最近ではAI やデータ解析処理の場面において利用されおり注目度の高い言語 1990
PHP S 動的な WEB サイトを実装する為の言語であるため、ライブラリを用いなくても WEB アプリケーション向けの処理が実装 1995

2. 静的型付けのプログラミング言語

動的型付けのプログラミング言語の場合、「コンパイル」を行う事でプログラミング時に型チェックを行います。静的型付けのプログラミング言語に比べて型チェックが厳格になっているので実装する処理も多くなります。

静的型付けのプログラミング言語に比べて難易度は高いと言えます。

言語名 F-S Initial release 起源
C - 高速に動作。システムの共通言語として様々なplatformで使用。garbage collection等、最近の機能は実装されてなく習得難易度はとても高い 1972
C++ - C を元にオブジェクト指向や例外処理等の概念を取り入れた言語 1993-2
C# - Microsoft が開発した .Net Framework と言うプラットフォーム上で動作させるためのプログラム 2000
Objective-C / Swift - Apple 社の MacOS や iOS 用のアプリケーションを開発するためのプログラム言語 1984/2014-6
SQL - データベースから情報の取得、追加、更新、削除と言った処理を行う為の言語 1974

各言語詳細

1. フロントエンド

JavaScript

(npmやYarn: パッケージ管理)

ーVue  Initial release: February 2014;
ーーnuxt VueのFramework  Initial release: October 26, 2016;
ーーーVuexなどのライブラリ


ーReact  Initial release: May 29, 2013;
ーーNext ReactのFramework
ーーーReduxなどのライブラリ
ーーーMaterial UI Reactのcomponents、Vuetifyみたいな感じかな

react native Initial-March 26, 2015

angular Initial release 2.0 / 14 September 2016; 

Python  First appeared: 1990

(pip:  パッケージ管理)

ーDjango Python-web-framework   Initial release: July 2005

Ruby 1995

(gem:  パッケージ管理)

ーーrails  August 2004;

2. サーバーエンド

PHP

(composer:  パッケージ管理)

ーLaravel PHPのFramework  Initial release: June 2011

JavaScript

Node Initial release: May 27, 2009;
Node express November 16, 2010;

3. その他

Rust

(cargo:  パッケージ管理)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ブルゾン風】WPの投稿記事をhtmlファイルで回してみたくない?

やりたいこと

WordPressのブログの記事情報を外部サイトにも反映・表示させたい!
だがしかし、、拡張子がhtmlのファイルにそんなことができるの??

思い悩むこと12時間............
なんとかやり口を見つけ解決まで導き出せました!

今回やりたいことをまとめると
・WordPressの投稿情報を外部サイトでも使いたい
・htmlファイルでphpを使いたい

環境

【サーバー】   Xserver
【サーバー番号】 2001(sv2001)以降

WordPressの投稿情報を外部サイトでも使う方法

ステップは2つです。
・WP管理外でも機能を使えるようにする
・投稿記事を表示する

WP管理外でも機能を使えるようにする

下記記述を対象のhtmlファイルの一番上にコピペしましょう。

include($_SERVER['DOCUMENT_ROOT']."/wp/wp-load.php");

もしくは

include($_SERVER['DOCUMENT_ROOT']."/wp/wp-blog-header.php");

どちらも同じ結果が返るので、どちらでも良いでしょう。
$_SERVER['DOCUMENT_ROOT'] とはルートのことで、それ以下のディレクトリは各々でWPファイルを記述してください。

私は上の記述でうまくいかなかったので、下の記述でやるとうまくいきました!

投稿記事を表示する

よーーし!
あとは表示だけだーー!!
WPのループを回して情報を表示させよう!

<?php if(have_posts()): while(have_posts()):the_post(); ?>

  <p><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></p>

  <time datetime="<?php the_time('Y-m-d'); ?>"><?php the_time('Y.m.d'); ?></time>

<?php endwhile;endif; ?>

これで完成だー!!ってあれれぇぇ........(コナンくんみたいな声が漏れた)
何故だかうまく情報を取得できません。

<?php
  $args = array( 'posts_per_page' => 3, 'order'=> 'DESC', 'orderby' => 'date' );
  $posts = get_posts($args);

  foreach ($posts as $post) :
?>
  <p><a href="<?php the_permalink(); ?>"><?php echo $post->post_title; ?></a></p>
  <p><?php echo mysql2date( 'Y/m/d', $post->post_date ) ?></p>

<?php endforeach; ?>

foreach文を使うとうまくいきました!!

htmlファイル内でphpを使う方法

.htaccessファイルに記述をしていきます。
サーバーによって記述方法が異なるので様々ですが、
ここでは一般的な記述方法とエックスサーバー利用時の記述方法を掲載しています。

一般的な記述

AddType application/x-httpd-php .php .phtml
AddType application/x-httpd-php .php .phtml .html

両方記述しているパターンが多いですが、どちらか1つでも行けると思います。

エックスサーバーの記述

エックスサーバーの中でも設定方法が2種類あります。
サーバー番号が2001(sv2001)以降の場合

AddHandler fcgid-script .html

私はこれで動きました。
サーバー番号が1999(sv1999)以前の場合

AddHandler x-httpd-php5.6 .php .phps .html

エックスサーバーのサーバー番号は、お知らせメールからわかるそうです。
チェックしておきましょう。

以上です!

参考記事

https://macoblog.com/wp-gaibu-kijiroop/
https://princessvision.com/html_php_work/
https://wp.turbo-w.com/wordpress_news_topics_1.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】全ボクが実務で泣いた「値渡し」と「参照渡し」を完!全!理!解

はじめに

先日、仕事(PHPでのWebアプリ開発)で連想配列の中身を加工していたのですが30分程全然うまく行かなかったので、先輩に聞いたら3分くらいで解決しました。

結論、解決方法としては「値渡しではなく"参照渡し"を使う」でした。

これまで何となく聞いたことがあったけど「絶対ムズイからイヤッ!!!:persevere:」と目を背けていた"参照渡し"について、これを機にちゃんと理解しようと思ったのでまとめます。
(てかそろそろ理解しておかないとヤバイという危機感w)

あと...
「これ、参照渡ししてあげるとオッケーですよ」
ってスマートに言えたらカッコよくないですか?

↑カッコ良いですけど、参照渡し自体はむやみに使わない方が良いので一応取り消し(笑)

というわけで書きます。

この記事でわかること

  • 値渡し
  • 参照渡し

特に僕と同じように「参照渡しから目を背けてきた方」や、「そもそも参照渡しってなーに?」って方に読んで欲しいですね。

読めば絶対に理解できます!!!

直面した問題

仕事のコードをそのまま使うことはできないので、簡単に再現してみます。

以下のコードをご覧ください。

<?php

// 配列を2つ定義
$members = [
    'Aさんの好きな果物' => [
        'りんご' => 'apple',
        'ぶどう' => 'grape',
        'バナナ' => 'banana',
    ],
    'Bさんの好きな果物' => [
        'マンゴー' => 'mango',
        'パイナップル' => 'pineapple',
        'ドラゴンフルーツ' => 'dragon fruit',
    ],
];
$fruits = [
    'ざくろ' => 'pomegranate',
    'オレンジ' => 'orange',
    'もも' => 'peach',
];

// $membersに$fruitsの要素を追加
foreach ($members as $member) {
    $member['ざくろ'] = $fruits['ざくろ'];
    $member['もも'] = $fruits['もも'];
}

// 配列を出力
var_dump($members);

AさんとBさんについてそれぞれ好きな果物を$membersに定義しています。
Bさんは多分、多分なんですけど沖縄の方な気がしてます。

そして、$fruitsという果物を3つ入れた連想配列も定義。

次に、foreachの中でAさん、Bさんの好きな果物に$fruitsから2つ追加しています。

それでは、var_dumpした時の出力結果がどうなっているのかというと

array(2) {
  ["Aさんの好きな果物"]=>
  array(3) {
    ["りんご"]=>
    string(5) "apple"
    ["ぶどう"]=>
    string(5) "grape"
    ["バナナ"]=>
    string(6) "banana"
  }
  ["Bさんの好きな果物"]=>
  array(3) {
    ["マンゴー"]=>
    string(5) "mango"
    ["パイナップル"]=>
    string(9) "pineapple"
    ["ドラゴンフルーツ"]=>
    string(12) "dragon fruit"
  }
}

あれ?
...定義した時の$membersのままなんですよね。

Bさんは相変わらず沖縄の人。(多分ですけどね)

本当はこうなって欲しい。

array(2) {
  ["Aさんの好きな果物"]=>
  array(5) {
    ["りんご"]=>
    string(5) "apple"
    ["ぶどう"]=>
    string(5) "grape"
    ["バナナ"]=>
    string(6) "banana"
    ["ざくろ"]=>
    string(11) "pomegranate"
    ["もも"]=>
    string(5) "peach"
  }
  ["Bさんの好きな果物"]=>
  array(5) {
    ["マンゴー"]=>
    string(5) "mango"
    ["パイナップル"]=>
    string(9) "pineapple"
    ["ドラゴンフルーツ"]=>
    string(12) "dragon fruit"
    ["ざくろ"]=>
    string(11) "pomegranate"
    ["もも"]=>
    string(5) "peach"
  }
}

仕事では連想配列に要素が追加できず、必須にタイポがないかめっちゃ探してました。
が、原因は全然違うところにあったのです...

どうすればいいのかというとコチラ!ドン!

<?php

// 配列を2つ定義
$members = [
    'Aさんの好きな果物' => [
        'りんご' => 'apple',
        'ぶどう' => 'grape',
        'バナナ' => 'banana',
    ],
    'Bさんの好きな果物' => [
        'マンゴー' => 'mango',
        'パイナップル' => 'pineapple',
        'ドラゴンフルーツ' => 'dragon fruit',
    ],
];
$fruits = [
    'ざくろ' => 'pomegranate',
    'オレンジ' => 'orange',
    'もも' => 'peach',
];

// $membersに$fruitsの要素を追加
// $memberの前に&をつける→参照渡しにする
foreach ($members as &$member) {
    $member['ざくろ'] = $fruits['ざくろ'];
    $member['もも'] = $fruits['もも'];
}

// 配列を出力
var_dump($members);

どこを変えたかというとコチラ!ドン!

// $membersに$fruitsの要素を追加
// $memberの前に&をつける→参照渡しにする
foreach ($members as &$member) {
    $member['ざくろ'] = $fruits['ざくろ'];
    $member['もも'] = $fruits['もも'];
}

$memberの前に&をつけて&$memberにしてあげると参照渡しになり、問題解決なのです...

ちなみに実際に出力結果はコチラ!ドン!

array(2) {
  ["Aさんの好きな果物"]=>
  array(5) {
    ["りんご"]=>
    string(5) "apple"
    ["ぶどう"]=>
    string(5) "grape"
    ["バナナ"]=>
    string(6) "banana"
    ["ざくろ"]=>
    string(11) "pomegranate"
    ["もも"]=>
    string(5) "peach"
  }
  ["Bさんの好きな果物"]=>
  &array(5) {
    ["マンゴー"]=>
    string(5) "mango"
    ["パイナップル"]=>
    string(9) "pineapple"
    ["ドラゴンフルーツ"]=>
    string(12) "dragon fruit"
    ["ざくろ"]=>
    string(11) "pomegranate"
    ["もも"]=>
    string(5) "peach"
  }
}

ちゃんとAとBさんの要素に2つの要素(ざくろ、もも)が追加されていますね。
これでBさんの沖縄感も少し薄まりましたね。

(てかざくろって英語でpomegranateなんだ。読み方わかんない)

ここまで来たけど

「というか!!何!!参照渡しって!?」って話。

ハイ、詳しく見ていきましょう。

値渡し

値渡しは関数の引数や変数を扱う上でデフォルトの考え方です。
何もしない(=参照渡しに変更しない)場合は、値渡しになります。

適当に書いてみましょう。

<?php

//変数を定義
$number = 1;

//関数を定義
function addNumber($num) {
    $num += 99;
    echo $num;
}

//関数を実行
addNumber($number);

//変数を出力
var_dump($number);

ハイ、こちらの結果はこうなります。

//addNumber()の中のechoの出力
100
//var_dumpの出力
int(1)

ですよね。
var_dumpで出力した場合はデータの型も表示されます。今回だと数字なので(int)型)

まあハイハイ、って感じですよね。

これが値渡しです。

これ、どういう流れで処理を行っているかというと

値渡し.jpg

addNumber($number)

で、addNumber関数の仮引数として設定した$num$numberを渡していますが、渡しているのは

$number = 1;

1という数字の値だけってこと。だけを渡すから値渡し。ナルホド。

(僕、今書きながら改めてナルホド!ってなってます)

なので

//関数を定義
function addNumber($num) {
    $num += 99;
    echo $num;
}

で99を足しているけど、渡しているのは1という数字だけだから、その後の

var_dump($number);

では定義した時の1がそのまま出力されるってことですね。完!全!理!解!

参照渡し

参照渡しについて公式ドキュメントを見てみましょう。

リファレンスにより関数に変数を渡すことが可能です。この場合、関数内で その引数を修正可能になります。構文は次のようになります。

引用元:リファレンス渡し

ハイ、意味不明。

じゃあさっき値渡しの説明で使ったコードで参照渡ししてみましょう。

<?php

//変数を定義
$number = 1;

//関数を定義
//仮引数$numの前に&をつける
function addNumber(&$num) {
    $num += 99;
    echo $num;
}

//関数を実行
addNumber($number);

//変数を出力
var_dump($number);

では出力結果!ドン!

//addNumber()の中のechoの出力
100
//var_dumpの出力
int(100)

つまり

var_dumpした出力結果がint(100)、つまり100になっちゃってるってことですね。

ということでここで詳しく理解していきます。

まず、どういう流れで処理を行っているかというと

参照渡し.jpg

こんな感じです。
(正式にはちょっと違うのかもしれませんがわかりやすくまとめました)

値渡しは「変数の値(文字列、数字など)を仮引数に渡す」ことでしたが、参照渡しは「変数自体を渡す」ことです。

(ググったら「変数のメモリ番地を渡す渡し方」と書いてましたが、多くの方にとってはちょっと難しい言い回しかと)

一応リンクだと貼っておきます。
値渡しと参照渡しの違いを理解する

値渡しと同じ手順ですが、

addNumber($number)

で、addNumber関数の仮引数として設定した$num$numberを渡していますが、渡しているのは

$number = 1;

$number = 1自体、つまり「numberという変数が数字の1という値を持っていますよ〜」という情報を渡しているんですね。

なので

//関数を定義
function addNumber(&$num) {
    $num += 99;
    echo $num;
}

で99を足しているのは$numberに格納されている数字です。
つまり、$numberの値が100に上書きされているっていうことになります。

というわけで

var_dump($number);

では1に99を足した100が出力されるわけですね。完!全!理!解!

以上をふまえて

値渡しと参照渡しを理解した上で最初のコードに戻ります。

// 配列を2つ定義
$members = [
    'Aさんの好きな果物' => [
        'りんご' => 'apple',
        'ぶどう' => 'grape',
        'バナナ' => 'banana',
    ],
    'Bさんの好きな果物' => [
        'マンゴー' => 'mango',
        'パイナップル' => 'pineapple',
        'ドラゴンフルーツ' => 'dragon fruit',
    ],
];
$fruits = [
    'ざくろ' => 'pomegranate',
    'オレンジ' => 'orange',
    'もも' => 'peach',
];

// $membersに$fruitsの要素を追加
// $memberの前に&をつける→参照渡しにする
foreach ($members as &$member) {
    $member['ざくろ'] = $fruits['ざくろ'];
    $member['もも'] = $fruits['もも'];
}

// 配列を出力
var_dump($members);

つまりこんなことが起こってる。(画質悪くてスミマセン)
参照渡し-2.jpg

foreach ($members as &$member) {

&$memberには$membersの各要素が入るので、

1回目は

'Aさんの好きな果物' => [
    'りんご' => 'apple',
    'ぶどう' => 'grape',
    'バナナ' => 'banana',
]

2回目は

'Bさんの好きな果物' => [
    'マンゴー' => 'mango',
    'パイナップル' => 'pineapple',
    'ドラゴンフルーツ' => 'dragon fruit',
]

になりますよね。

その各要素(連想配列)自体の情報が格納されるので好きな果物にざくろとももが追加(=上書き)されてvar_dumpで追加された状態で出力することができるってわけですね。ふむふむ。

おわり

値渡しと参照渡しのそれぞれの考え方を説明しました。
僕なりに初学者にもわかりやすくまとめることができたんじゃないかと思います。

※明らかにおかしいところあればぜひコメントをいただけると幸いですm(__)m

「内容がよかった!」と思っていただけましたらLGTMをしてくださると嬉しいです:sob:

以上です。

P.S.
この記事を書いている途中に別の先輩から参照渡しをせずに連想配列の中身を書き換えるワザを教えてもらったので、別の記事にまとめます。
投稿したらここにリンク貼ります。
(というか参照渡し使ってたらその後の処理が上手くいかず最終的に上記の方法で実装しました)

なお、コメント欄を見ていただけるとわかりますが、参照渡し自体はできれば使わない方がいいみたいです。理由についてもコメントに書いていただいているので参照くださいm(__)m

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

php.iniファイルの場所をターミナルで確認する

確認コマンド

$ php -r "echo phpinfo();" | grep "php.ini"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む