TIL2025-02-15-プログラミング基礎

 

 

class Parent {
    Parent() {
        System.out.println("Parent のコンストラクタが実行されました");
    }
}

class Child extends Parent {
    Child() {
        // 実際には super(); が自動的に呼ばれる
        System.out.println("Child のコンストラクタが実行されました");
    }
}

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

 

  • これが普通だと思っていたけど、PHP, Ruby では違うっぽい

 

PHP と Ruby では、super の扱いが Java や JavaScript とは異なります。どちらの言語も、super() を明示的に呼び出さない限り、親クラスのコンストラクタは自動的に実行されません。 したがって、親クラスの共通処理を実行するためには super() を明示的に呼び出す必要があります。

 

<?php
class ParentClass {
    public function __construct() {
        echo "Parent のコンストラクタが実行されましたn";
    }
}

class ChildClass extends ParentClass {
    public function __construct() {
        parent::__construct(); // これを忘れると親クラスのコンストラクタは実行されない
        echo "Child のコンストラクタが実行されましたn";
    }
}

$child = new ChildClass();
?>

 

 

class ParentClass
  def initialize
    puts "Parent のコンストラクタが実行されました"
  end
end

class ChildClass < ParentClass
  def initialize
    super # これを忘れると親クラスの initialize は実行されない
    puts "Child のコンストラクタが実行されました"
  end
end

child = ChildClass.new

 

 

言語 super(または parent::__construct())の自動実行 super() を明示的に書く必要がある場合
Java ✅ デフォルトコンストラクタは自動実行 🚨 親が引数付きコンストラクタを持つ場合は必須
JavaScript 🚨 自動実行されない ✅ 子クラスのコンストラクタ内で必須
PHP 🚨 自動実行されない ✅ 親の __construct() を実行する場合は parent::__construct(); を明示的に記述する必要あり
Ruby 🚨 自動実行されない ✅ 親の initialize を実行する場合は super を明示的に記述する必要あり

 

php で 子がコンストラクタを持たないときはparent::__construct();は不要ですか。

PHP では子クラスがコンストラクタを持たない場合、親クラスのコンストラクタは自動的に実行されます。

<?php
class ParentClass {
    public function __construct() {
        echo "Parent のコンストラクタが実行されましたn";
    }
}

class ChildClass extends ParentClass {
    // コンストラクタを定義しない
}

$child = new ChildClass();
?>

 

# 出力
Parent のコンストラクタが実行されました

 

 

 

子がコンストラクタを持たないとき、明示的に呼び出さないことで、親のコンストラクタが実行されない言語はありますか。

はい、C++ は子クラスがコンストラクタを持たない場合でも、明示的に親のコンストラクタを呼び出さないと親のコンストラクタが実行されないことがあります。

 

??? 言語によって変わるから、覚えるの無理 ???

  • 使う言語だけ頑張る

package は java で namespace は php ですか?

PHP の namespace は Java の package に相当します。

 

比較項目 PHP: namespace Java: package
目的 名前空間の管理、クラスや関数の整理 クラスの整理、アクセス制御
宣言方法 namespace MyNamespace; package mypackage;
ファイル構成の強制性 フォルダ構成は自由 package のパスとフォルダ構成が一致する必要あり
クラスのインポート use MyNamespaceMyClass; import mypackage.MyClass;
アクセス制御 namespace 自体にアクセス制御はない public, protected, private でアクセス制御
  • Java では ディレクトリ一致が必須だ!!PHPは気にしなくていい

 

  • namespace Office/Word の Class Writer でも Writer.php は officeディレクトリ直下でOK
  • 人の探しやすさが優先されます

 

CSRFの攻撃の流れ

  1. 被害者がサービスにログイン(例:銀行サイト)
  2. 攻撃者が悪意のあるWebページを用意(例:偽のリンクや画像)
  3. 被害者が攻撃者のサイトを開く
  4. 被害者のブラウザが、ログイン中のサイトに不正なリクエストを送信
  5. ログイン状態が維持されているため、サイト側でリクエストが正当なものと誤認
  6. 結果として、被害者のデータが改ざんされる

 

CSRFの正しい対策

  1. CSRFトークンをフォームに含める(POST, PUT, DELETE などのリクエストで検証)
  2. JavaScriptの非同期リクエスト(Ajax, Fetch, Axiosなど)にもCSRFトークンを適用
  3. CSRFトークンがないリクエストは、攻撃の可能性があるため拒否する
  4. GETリクエストには通常CSRFトークンは不要(ただし、例外あり)

 

CORS(Cross-Origin Resource Sharing)とは?

CORS(クロスオリジンリソース共有) とは、異なるオリジン(ドメイン)間でのリソースのやり取りを制御する仕組み です。

セキュリティ上の理由から、ブラウザは異なるオリジン(クロスオリジン)へのリクエストを制限します。

 

オリジンは、プロトコル + ドメイン + ポートの組み合わせで決まります。

URL オリジン
https://example.com https://example.com
https://api.example.com https://api.example.com(異なるオリジン)
http://example.com http://example.com(異なるオリジン)
https://example.com:8080 https://example.com:8080(異なるオリジン)

 

CORSとCSRFの違い

項目 CORS CSRF
目的 異なるオリジン間のリクエストを制御 ユーザーの意図しないリクエストを防ぐ
攻撃の種類 ブラウザがリクエストを制限(セキュリティ対策) 攻撃者がユーザーの認証情報を悪用
対策方法 サーバー側で Access-Control-Allow-Origin を設定 CSRFトークンを使用
影響するリクエスト クロスオリジンのリクエスト全般 ログイン中のユーザーが意図しないリクエストを送るケース

 

🔹 CORSエラーのポイント

✅ サーバーが「Access-Control-Allow-Origin」ヘッダーを返さないと、ブラウザがエラーを出す。

✅ CORSのチェックはブラウザ側のみで発生し、サーバー側では特にエラーにならない。

✅ サーバー側でCORSを正しく設定すればエラーは解消できる。

⚠️ サーバー間の通信(バックエンド同士)ではCORSの制限はない

  • 例えば curlPostman でリクエストを送っても CORSエラーは発生しない(ブラウザが関与しないため)。
  • CORS制限は あくまで「ブラウザで実行されたリクエスト」に適用される。

 

🔹 まとめ

✅ CORSがないと DDoS攻撃やCSRF、情報漏洩 などのリスクが高まる。

✅ SOP(同一オリジンポリシー)は、Webセキュリティの基本原則 であり、これがないと多くの攻撃が成立する。

✅ ブラウザがSOPを遵守しないと、セキュリティホールが無限に広がる。

つまり、SOPがないとWebは「無法地帯」になり、安全に使えなくなってしまう ということです。💀

 

 

PHP は static を静的領域に確保する?

PHP は Java や C++ のように「静的領域(データセグメント)」を明示的に確保するわけではありません。

 

  • インスタンスのプロパティ ➝ インスタンスごとに個別のメモリが確保される
  • static プロパティ ➝ クラスごとに1つだけ確保され、全インスタンスで共有される
class Test {
    public int $a = 0; // インスタンスごとに別々
    public static int $b = 0; // クラス全体で共有
}

$obj1 = new Test();
$obj2 = new Test();

$obj1->a++;
$obj2->a++;

$obj1::$b++;
$obj2::$b++;

echo "obj1->a: {$obj1->a}, obj2->a: {$obj2->a}n"; // それぞれ 1
echo "Test::b: " . Test::$b; // 2(共有されているため)

 

 

静的プロパティは通常のメソッドでも使える

class Example {
    public static int $count = 0; // 静的プロパティ

    public function increment() { // 通常のメソッド
        self::$count++; // 静的プロパティを変更
    }

    public function showCount() {
        echo "Count: " . self::$count . "n"; // 静的プロパティを取得
    }

    public static function staticIncrement() { // 静的メソッド
        self::$count++;
    }
}

$obj1 = new Example();
$obj2 = new Example();

$obj1->increment();
$obj2->increment();

Example::staticIncrement();

$obj1->showCount(); // Count: 3

 

 

 

ラムダ式とは?

ラムダ式(Lambda Expression) とは、「名前を持たない小さな関数」 のことです。無名関数(Anonymous Function) や クロージャ(Closure) とも呼ばれることがあります。

 

function()(無名関数) fn()(アロー関数)
記述 function($x) { return $x * $x; } fn($x) => $x * $x;
複数行 ✅ 可能 ❌ 不可(1行のみ)
use の扱い コピー(値渡し) 参照(use なしで外部変数にアクセス)
  • function() を使う(無名関数)
$square = function($x) {
    return $x * $x;
};

echo $square(5); // 25

 

 

  • fn() を使う(アロー関数)
$square = fn($x) => $x * $x;

echo $square(5); // 25

 

 

ラムダ式の用途としての例

function processItems(array $items, callable $callback) {
    foreach ($items as $item) {
        echo $callback($item) . PHP_EOL;
    }
}

$data = [1, 2, 3, 4, 5];

// 2倍にする処理を渡す
processItems($data, fn($n) => $n * 2);

// 文字列として表示する処理を渡す
processItems($data, fn($n) => "Number: $n");

 

 

 

Callable(呼び出し可能)な関数でスコープが変わるとは?

 

JavaScript では、関数が “Callable”(呼び出し可能)であっても、呼び出し方によって this のスコープ(参照先)が変わる という重要な特性があります。

 

const obj = {
    name: "Alice",
    showThis: function() {
        console.log(this.name);
    }
};

obj.showThis(); // "Alice"

 

  • 関数を変数に渡す(this が変わる!)
const obj = {
    name: "Alice",
    showThis: function() {
        console.log(this.name);
    }
};

const fn = obj.showThis; 
fn(); // ❌ `undefined` またはエラー(strict mode)

 

 

具体的に this はどこで決まる?

 

class MyClass {
    constructor() {
        this.name = "MyClassInstance";
    }

    handleClick() {
        console.log(this.name);
    }
}

const obj = new MyClass();
obj.handleClick(); // ✅ this は obj

 

  • 関数の実行時に決まる

 

 

アロー関数のthisは?

 

document.getElementById("btn").addEventListener("click", () => obj.handleClick());

どう動作するか?

クリックされたとき

  • () => obj.handleClick() の アロー関数が実行される。
  • その中で obj.handleClick() が その時点の objhandleClick を呼び出す。
  • thisobj のまま維持される(アロー関数の this は定義時の this を保持するため)。

 

 

バンドルツールとは?

 

バンドルツールは、JS/CSS などを 1 つにまとめて最適化するツール

 

 

代表的なバンドルツール

ツール名 特徴
Webpack 最も有名なバンドルツール。カスタマイズ性が高い。
Vite 高速な開発環境を提供するモダンツール(ESModules ベース)。
Parcel 設定不要で簡単に使える。
esbuild 超高速なバンドルツール(Go 言語製)。
Rollup 軽量で、ESModules に特化。

 

 

scroll イベントで要素の表示を検知する実装

 

document.addEventListener("scroll", () => {
  const target = document.getElementById("triggerElement");
  const rect = target.getBoundingClientRect();
  const windowHeight = window.innerHeight;

  if (rect.top < windowHeight && rect.bottom > 0) {
    console.log("要素が表示領域に入った!");
  }
});

 

  • getBoundingClientRect() で 要素の座標を取得
    • .top → 要素の上端の Y 座標(ビューポートの上からの距離)
    • .bottom → 要素の下端の Y 座標(ビューポートの上からの距離)
  • window.innerHeight は ビューポートの高さ
  • rect.top < windowHeight で 要素の上端が画面内に入ったら発火
  • rect.bottom > 0 で 要素の下端が画面内にあるか確認(完全に消えてないか)

 

 

Enum と Struct

 

Enum(列挙型) Struct(構造体)
用途 限定された値を表す 複数のデータを1つにまとめる
データ 定数(固定値) 変数(異なる型のデータ)
メモリ 小さい(値のみ) より最適化されている
拡張性 変更不可(列挙値を追加する以外) プロパティを追加できる
PHP enum(PHP8.1〜) class で代用

 

まぁ覚えるの大変です

エンジニア 1 年生って困難です