


結論 

以下の順番で検索する
- 絶対パスが書いてある時は、そのファイル
- include_pathを前から検索
- カレントディレクトリ基準で検索
- requireが書いてあるphpファイル基準で検索
注意 

- requireを
.
または..
で開始すると、カレントディレクトリしか検索しない - include_pathに
.
とか..
を入れてしまうとカレントディレクトリを移動すると検索場所が変化するので結構危険 - require先でさらにrequireするときは、あらためて最初からルール適用となる。

ファイルのインクルードは、指定されたパスから行います。パスを指定しない場合は、 include_path の設定を利用します。 ファイルが include_path に見つからないときは、include は呼び出し元スクリプトのディレクトリと現在の作業ディレクトリも探します。



検証 

PHP8.1.2を使用
前提
/home/ranzoに次のようにディレクトリとphpファイルを配置する。
以下、treeコマンドの出力
.
├── Main.php
├── Same.php
├── a
│ ├── Same.php
│ ├── Sub.php
│ └── a
│ └── Same.php
├── b
│ ├── Same.php
│ ├── Sub.php
│ └── a
│ └── Same.php
├── c
│ ├── Same.php
│ └── a
│ └── Same.php
└── d
Same.phpの中身は全て同じ(symlinkだと挙動が違うので実ファイル)
<?php
echo __FILE__ . "\n";
ケース1 

Main.phpを↓のようにして
<?php
set_include_path('/home/ranzo/b');
require_once '/home/ranzo/c/Same.php';
これを/home/ranzo
から実行すると結果は
% cd /home/ranzo
% php ./Main.php
/home/ranzo/c/Same.php
となる。絶対パスなので迷いなくそのファイルを実行
ケース2 

Main.phpを↓のようにして
<?php
set_include_path('/home/ranzo/b:/home/ranzo/c');
require_once 'Same.php';
これを/home/ranzo
から実行すると結果は
% cd /home/ranzo
% php ./Main.php
/home/ranzo/b/Same.php
となるので、include_pathを最優先で前から検索していることがわかる。
なお、b/Same.phpを削除すると結果は
/home/ranzo/c/Same.php
となるので、まずは他を探す前にinclude_pathを前から順に探している。
ケース2のおまけ
include_pathに.
が含まれていた場合、どこ基準の.
なのかを検証する。
Main.phpを↓のようにして
<?php
set_include_path('.:/home/ranzo/b');
require_once 'Same.php';
実行すると
% cd /home/ranzo/a # 一段深いa
% php ../Main.php # 親dirのscriptを実行
/home/ranzo/a/Same.php
となるので、include内の.
はscriptファイルのある場所ではなく、phpコマンドを実行したときにいるカレントディレクトリであることがわかる。


ケース3 

Main.phpを↓のようにして
<?php
require_once 'Same.php';
実行すると
% cd /home/ranzo/a # 一段深いa
% php ../Main.php # 親dirのscriptを実行
/home/ranzo/a/Same.php
となるので、scriptファイルのある場所よりも、カレントディレクトリ優先がわかる。
ケース4 

Main.phpを↓のようにして
<?php
require_once 'Same.php';
phpファイルのないディレクトリから実行すると
% cd /home/ranzo/d # 空っぽのフォルダ
% php ../Main.php # 親dirのscriptを実行
/home/ranzo/Same.php
ようやく、scriptファイルのあるディレクトリを探しに行く。
ここまでで
絶対パス指定 > include_path > カレントディレクトリ > scriptパス
の順とわかった。
ケース5

次はrequireした先で、サブフォルダをrequireしてみる
Main.phpを↓のようにして
<?php
// あえてcを前に書いてある
set_include_path('/home/ranzo/c:/home/ranzo/b');
require_once 'Sub.php';
Sub.phpをこのようにして、aとbディレクトリに置く。cには置かない。
<?php
echo __FILE__ . " from Sub.php\n";
require 'a/Same.php';
aから実行すると
% cd /home/ranzo/a # 一段深いa
% php ../Main.php # 親dirのscriptを実行
/home/ranzo/b/Sub.php from Sub.php
/home/ranzo/c/a/Same.php


ケース5の派生
ケース5とMain.phpは変えずに、Sub.phpのrequireに./
を追加すると
<?php
echo __FILE__ . " from Sub.php\n";
require './a/Same.php'; # ./を追加
なんと結果は
% cd /home/ranzo/a # 一段深いa
% php ../Main.php # 親dirのscriptを実行
/home/ranzo/b/Sub.php from Sub.php
/home/ranzo/a/a/Same.php
Same.phpはa/aのものが呼ばれている。
./
をつけてしまうと問答無用でカレントディレクトリ基準で呼ばれてしまうようだ。
ケース6 

Main.phpを↓のようにして
<?php
require_once './Same.php';
phpファイルのないディレクトリから実行すると
% cd /home/ranzo/d # 空っぽのフォルダ
% php ../Main.php # 親dirのscriptを実行
PHP Fatal error: Uncaught Error: Failed opening required './Same.php' (include_path='/home/ranzo/c:/home/ranzo/b') in /home/ranzo/Main.php:4
エラーになる。
この場合、カレントディレクトリしか探していないことがわかる。
PHPマニュアルには
パスを指定した場合 — 絶対パス (Windows ならドライブレターあるいは \ で始まるパス、Unix/Linux 系なら / で始まるパス) あるいはカレントディレクトリからの相対パス (. あるいは .. で始まるパス) のどちらでも — は include_path は無視されます。
とありますが、include_pathだけでなくscriptフォルダも無視されています。