порядок определения классов в РНР файле

Фанат

oncle terrible
Команда форума
Всю жизнь считал, что порядок определения функций и классов в РНР файле неважен.
Однако,
PHP:
class userMapper extends defaultMapper{}
$userMapper = new userMapper();
class defaultMapper{}
работает
PHP:
$userMapper = new userMapper();
class userMapper extends defaultMapper{}
class defaultMapper{}
не работает

картинка-с-джеки-чаном.жпг
 
  • Like
Реакции: WMix

WMix

герр M:)ller
Партнер клуба
ну вообще понятно, не js..
PHP:
$foo = new Foo();
include("Foo.class.php");
или даже так

Код:
$ php -a
Interactive mode enabled

php > $userMapper = new userMapper();
PHP Warning:  Uncaught Error: Class 'userMapper' not found in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1
php > class userMapper extends defaultMapper{}
PHP Fatal error:  Class 'defaultMapper' not found in php shell code on line 1
php > class defaultMapper{}
php >
 

Adelf

Administrator
Команда форума
уже лет 10 спокойно работаю без этого знания. композер, PSR- не помню какой для автолоадинга классов и все.
кстати что будет на echo '10 files' + 5; тоже не знаю.
 

Фанат

oncle terrible
Команда форума
Это поведение где-то описано?
вот только ерунды не надо писать. при чем здесь интерактивный шелл?
уже лет 10 спокойно работаю без этого знания. композер, PSR- не помню какой для автолоадинга классов и все.
кстати что будет на echo '10 files' + 5; тоже не знаю.
представь себе, я тоже
если это имеет такое значение, то я спрашиваю не из практических соображений

почему '10 files' + 5 будет равно 15 мне тоже интересно, но ответ на этот вопрос я себе примерно представляю;
 

флоппик

promotor fidei
Команда форума
Партнер клуба

Фанат

oncle terrible
Команда форума
Ну ок, пойду спрашивать на Реддит.
Я ж не первый раз так делаю - сначала спрашиваю здесь, чтобы не позориться перед мировой общественностью - а то вдруг я какой-то элементарщины не знаю :)
 

fixxxer

К.О.
Партнер клуба
Ну вот даже из этого более-менее очевидно:
PHP:
fixxxer@mbp ~/tmp » cat 1.php
<?php

if (empty($_SERVER['argv'][1])) {
    class A {
        public $x = 1;
    }
} else {
    class A {
        public $x = 2;
    }
}

var_dump( (new A)->x );
fixxxer@mbp ~/tmp » php 1.php 0
/Users/fixxxer/tmp/1.php:13:
int(1)
fixxxer@mbp ~/tmp » php 1.php 1
/Users/fixxxer/tmp/1.php:13:
int(2)
 

fixxxer

К.О.
Партнер клуба
@Фанат, я просто показал, что это работает (в других языках был бы hoisting и duplicate definition).
А дальше из этого уже логично следуют ограничения на B extends A, поскольку что там в этом A, мы в общем случае узнаем только в рантайме.
Это что касается случая в одном файле.
А если в разных файлах - то тем более: zend vm компилирует файлы по отдельности и не знает ничего о структуре include-ов. Если бы было иначе, то были бы не include-ы чего попало как угодно, а всякие там заголовочные файлы, как в С++, или компиляция не по файлам, а по классам, как в Java.
Понятно, что твой конкретный случай с extends в одном файле можно было бы детектить и делать hoisting, но это слишком большое и слишком бесполезное усложнение.

Другое дело, что я вообще не понимаю, нафига было заморачиваться и делать early binding для тривиального случая. Скорее всего, так вышло исторически из-за особенностей устройства какого-нибудь php4.0 без какого-либо умысла, а дальше уже BC is the king.
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
как говорят, в специальных олимпиадах PHP всегда впереди
 
Сверху