php class return class
Php class return class
Developers with a C background may expect pass by reference semantics for arrays. It may be surprising that pass by value is used for arrays just like scalars. Objects are implicitly passed by reference.
# (1) Objects are always passed by reference and returned by reference
# (2) Scalars are not passed by reference or returned as such
# (3) You have to force pass by reference and return by reference on scalars
# (4) Arrays use pass by value sematics just like scalars
$array = array();
$array [ ‘x’ ] = 1 ;
# (5) You have to force pass by reference and return by reference on arrays
$array = array();
$array [ ‘x’ ] = 1 ;
However resource is not allowed as a return type:
Be careful about using «do this thing or die()» logic in your return lines. It doesn’t work as you’d expect:
Functions which return references, may return a NULL value. This is inconsistent with the fact that function parameters passed by reference can’t be passed as NULL (or in fact anything which isnt a variable).
if ( testRet () === NULL )
<
echo «NULL» ;
>
?>
parses fine and echoes NULL
Be careful when introducing return types to your code.
Return values of a type different to that specified are silently converted with sometimes perplexing results. These can be tedious to find and will need rewriting, along with calling code.
Declare strict types using «declare(strict_types=1);» and an error will be generated, saving much head-scratching.
With 7.1, these are possible yet;
function ret_void (): void <
// do something but no return any value
// if needs to break fn exec for any reason simply write return;
if (. ) <
return; // break
// return null; // even this NO!
>
You may specify child return type if there is no parent:
PHP 7 return types if specified can not return a null.
For example:
declare( strict_types = 1 );
Output :
7
Process finished with exit code 139
Declaring a collection of objects as return type is not implemented and forbidden:
class Child <>
function getChilds (): Child []
<
return [(new Child ()), (new Child ())];
>
var_dump ( getChilds ());
// Returns: Parse error: syntax error, unexpected ‘[‘, expecting ‘ <'
?>
We have to use:
class Child <>
function getChilds (): array
<
return [(new Child ()), (new Child ())];
>
Объекты и классы в PHP
Объекты
Объекты в PHP — это просто ещё один тип данных. Объект позволяет хранить в переменной набор из свойств и их значений, а также встроенные функции. Это делает объекты похожими по своей структуре на ассоциативные массивы. Но отличие от массивов всё-таки есть, и при этом достаточно важное — объекты могут иметь внутреннее состояние.
Особенности объектов и их отличия от массивов
Давайте разберёмся, что такое PHP-объект. Как сказано выше, объекты похожи на массивы, но со своими особенностями. Объекты могут содержать отдельные значения, каждое под своим ключом. Эти значения называются свойствами объекта.
Также объекты могут иметь внутри себя функции — их называют методами объекта. Методы могут обращаться к любым свойствам объекта, читать и записывать туда данные.
Значение свойства объекта может быть любого типа: число, строка, массив, другой объект. Но, в отличие от массива, объекты не позволяют добавлять в себя новые значения. То есть объект всегда имеет конечное число своих свойств и методов. Менять значения существующих свойств можно, а удалять и заменять их — нельзя. Что в корне отличается от поведения массива, ведь там добавлять и удалять значения можно в любое время.
Но самая большая особенность объектов — это то, как они создаются. Если массив создается либо пустым, либо сразу с набором значений, то объекты устроены иначе. Дело в том, что объекты не существуют сами по себе. Чтобы создать новый объект, вам придётся вначале создать его описание — класс.
Класс — это как бы чертёж объекта. Класс описывает то, из чего состоит объект. Мы разберёмся с классами чуть позже.
Анатомия объекта
Как же устроен объект изнутри? Его содержимое можно поделить на две группы: свойства и методы.
Свойства могут быть двух видов: публичные и скрытые. К публичным свойствам можно обращаться за пределами объекта, точно так же, как вы обращаетесь к элементам массива по его ключам.
Скрытые свойства не имеют аналогов в массиве. Они доступны для чтения и изменения только внутри самого объекта — и это могут делать его методы.
Вторая группа — это методы объекта.
Набор методов также называется поведением объекта. Как и свойства, методы бывают публичными и скрытыми. Публичные методы объекта можно вызывать из внешнего кода, а скрытые только из самого объекта. Методы способны обращаться к свойствам объекта также просто, как если бы это были их внутренние переменные или аргументы.
Классы
Класс — это шаблон, по которому создаются объекты.
Напомню, что классы — это описания объектов. Мы не можем создать объект «на лету», как это происходит с массивами. Объект может быть создан только на основе своего описания — класса. Этим, кстати, реализация объектов в PHP отличается от JavaScript. В JS объектам не нужны никакие классы, и они могут быть созданы и модифицированы когда угодно и как угодно.
Класс как чертёж
Зачем же нужны классы, и почему объекты не могут существовать без них?
Здесь аналогия очень простая: класс – это чертёж, максимально подробное описание того, как должно выглядеть изделие. Сам по себе класс не является чем-то физическим и осязаемым, то есть мы не можем использовать его в коде непосредственно. Вместо этого класс является схемой, структурой, на основе которой будет создан объект.
Жизненный цикл объекта
Любая работа с объектами в PHP состоит из следующих этапов.
Начинается всё с создания класса. В классе мы фиксируем из каких свойств и методов будет состоять каждый его экземпляр. Также в классе можно задать начальные значения для каждого свойства.
Имея класс, возможно создать его экземпляр — объект.
Классы в PHP принято сохранять в отдельных файлах, поэтому вначале вы подключаете этот сценарий там, где он необходим. Затем вызываете процедуру создания нового объекта на основе этого класса.
Чтобы использовать объект в дальнейшем, его следует, как всегда, назначить переменной. Затем вы будете работать с объектом через переменную: вызывать методы и обращаться к свойствам.
Пример создания объекта на основе класса
Создание объекта на основе класса:
Разбор примера
Разберёмся с тем, что здесь происходит.
Начнём с целей создания данного класса. Его задача — хранить в объекте данные о погоде за конкретный день, а также предоставлять сводку за этот день в текстовом виде.
В классе определено четыре скрытых свойства. Это значит, что к ним не будет доступа за пределами объекта. Читать и записывать эти свойства могут только внутренние методы объекта. Сами свойства хранят температурные параметры (температуру, осадки), дату и дополнительный комментарий к записи. Некоторым свойствам задано значение по умолчанию.
Что такое конструктор объекта
Методы объекта вызываются из внешнего кода, при явном обращении к ним с указанием имени. Но если назвать один метод __construct то он будет вызываться автоматически в момент создания объекта на основе класса.
Конструкторы объектов используются для инициализации каких-либо значений и выполнении других подготовительных операций. В нашем примере конструктор устанавливает содержимое скрытых свойств.
Обращение к свойствам и методам объекта
Посмотрим, как внутри метода происходит обращение к его свойствам.
Во-первых, для этого используется специальная переменная this, которая всегда присутствует внутри объекта и ссылается на него самого.
Во-вторых, для обращения к методам и свойствам объекта нужен специальный синтаксис: «стрелочка». Такая стрелочка отделяет имя свойства или метода от имени объекта. Это аналог квадратных скобок при работе с массивами.
Метод с именем isCold() нужен, чтобы узнать было ли холодно в тот день, основываясь на показаниях температуры в градусах.
Метод setRainStatus() устанавливает логическое значение, которое показывает статус осадков в день наблюдения.
Метод getDayDescription() формирует текстовое описание погоды на заданную дату.
Создание объекта на основе класса
В коде мы передаём в конструктор почти все параметры погодных наблюдений. Затем для созданного объекта вызываются его методы: первый устанавливает значения осадков, а второй возвращает текстовое описание погоды.
get_declared_classes
(PHP 4, PHP 5, PHP 7, PHP 8)
get_declared_classes — Returns an array with the name of the defined classes
Description
Gets the declared classes.
Parameters
This function has no parameters.
Return Values
Returns an array of the names of the declared classes in the current script.
Note that depending on what extensions you have compiled or loaded into PHP, additional classes could be present. This means that you will not be able to define your own classes using these names. There is a list of predefined classes in the Predefined Classes section of the appendices.
Changelog
Version | Description |
---|---|
7.4.0 | Previously get_declared_classes() always returned parent classes before child classes. This is no longer the case. No particular order is guaranteed for the get_declared_classes() return value. |
Examples
Example #1 get_declared_classes() example
The above example will output something similar to:
See Also
User Contributed Notes 9 notes
The array returned by this function will be in the order the classes were defined / included / required and this order does not appear to change.
//define classone
class classone
//define classtwo
class classtwo
//This will show X classes (built-ins, extensions etc) with
//classone and classtwo as the last two elements
//define classthree
class classthree
//. and four
class classfour
//Shows the same result as before with class three and four appended
print_r ( get_declared_classes ());
Regarding note of 3-21:
?>
This function could also be used to determine the names of classes defined in a particular file by calling it before and after include. It’s hardly a pointless function.
get-declared-classes makes no sense at all, if u maybe, later for production, merge class files in one package file.
lets say: package.php
print_r(get_declared_classes());
class declaredHere < >
print_r(get_declared_classes());
so in this case, the declaredHerr class is defined at the first call of print_r();
because PHP-complier runs a hole file and declare Stuff before running the code.
But (Lovely PHP):
print_r(get_declared_classes());
if(true)<
class declaredHere < >
>
print_r(get_declared_classes());
Will print the declaredHere class only in the second print_r.
Its not a Bug it a.
Summary:
* in PHP 5.1 class names have case preserved
* contrary, in PHP 4.4 class names are downcased, withe exception of a few build-in ones
The get_declared_classes() funcition returns the list of names with case preserved, as of PHP 5.1 series (prolly 5.0 too, but i have no way to test it right now). Since PHP generally is caseless in regard to names of classes, this may come at a surprise. Also, this could potentially break older code asssuming downcased list.
classes can’t be unloaded. probably not very practical to implement that in a future version. I wouldn’t go out of my way to do it if I were zend. you’re better off finding a workaround. it’s better programming technique to find a way around having to do that anyway.
This function considers only classes and subclasses. Not subsubclasses.
Php class return class
I have implemented enum using late static binding.
interface IEnum <
/**
* Only concrete class should implement this function that should behave as
* an enum.
*
* This method should return the __CLASS__ constant property of that class
*
* @return string __CLASS__
*/
public static function who ();
>
abstract class Enum <
// use of late static binding to get the class.
$class = static:: who ();
class Fruits extends Enum implements IEnum <
public static function who () <
return __CLASS__ ;
>
>
// user input from dropdown menu of fruits list
$input = 3 ;
echo B :: constructor (); // B
?>
Just a quick reminder to always check your syntax. While I love LSB, I thought it wasn’t working:
static::$sKey = not set
…until I realized that I’d completely forgotten to make it a variable variable:
static::$$sKey = is set
…of course this applies anywhere in PHP, but because of the (current) newness late static bindings, I’ve seen lots of code with this particular snafu in it from others.
In the above example (#3) in order to make it work, you can change the child’s method from ‘private’ to ‘protected’ (or public) and it will be called through ‘static’.
class B extends A <
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
>
class C extends A <
protected function foo () < //note the change here
echo ‘hello world!’ ;
>
>
I discovered an interesting thing. The class name string must be accessed directly from «flat» variable. Late static binding code that get’s it’s variable from array that is passed by class instance, throws an syntax error. Bug?
public static function numbers ()
<
return 123 ;
>
$arr = array( ‘class’ => ‘A’ );
This function can be used as a workaround for late static binding in PHP >= 5.1.0. There was another similar version of this function elsewhere, but used eval.
At least as of PHP 5.3.0a2 there’s a function get_called_class(), which returns the class on which the static method is called.
class a <
static public function test () <
print get_called_class ();
>
>
a :: test (); // «a»
b :: test (); // «b»
You can pass arguments to your constructor through your getInstance method, assuming you are running php5.
This would pass the params to your constructor. Love for php.
PHP5.3 unavailable, yet in the need for ‘static’, I did the following.
Any objections? Personally I hate using the the eval() statement.
Here is a small workaround I made for the static inheritance issue. It’s not perfect, but it works.
// Init
$backTrace = debug_backtrace ();
$class = false ;
public static function staticClassName () <
// Get real name
$staticName = self :: getStatic ();
?>
There are two issues with this workaround :
— if you call a static method from global env, you need to declare the name of the class BEFORE calling the method, otherwise the workaround won’t work (see 3rd and 4th examples). But I assume good programming makes few calls to static methods from global scope, so this shouldn’t be long to fix if you use it.
— the workaround fails to access to private or protected static vars, as it uses get_class_vars(). If you find any better solution, let us know.
Php class return class
Класс может содержать собственные константы, переменные (называемые свойствами) и функции (называемые методами).
Пример #1 Простое определение класса
Результат выполнения данного примера в PHP 7:
Результат выполнения данного примера в PHP 8:
Если с директивой new используется строка ( string ), содержащая имя класса, то будет создан новый экземпляр этого класса. Если имя находится в пространстве имён, то оно должно быть задано полностью.
В случае отсутствия аргументов в конструктор класса, круглые скобки после названия класса можно опустить.
Пример #3 Создание экземпляра класса
Когда происходит присвоение уже существующего экземпляра класса новой переменной, то эта переменная будет указывать на этот же экземпляр класса. То же самое происходит и при передаче экземпляра класса в функцию. Копию уже созданного объекта можно создать через её клонирование.
Пример #4 Присваивание объекта
Результат выполнения данного примера:
Создавать экземпляры объекта можно двумя способами:
Пример #5 Создание новых объектов
class Test
<
static public function getNew ()
<
return new static;
>
>
class Child extends Test
<>
Результат выполнения данного примера:
Обратиться к свойству или методу только что созданного объекта можно с помощью одного выражения:
Пример #6 Доступ к свойствам/методам только что созданного объекта
Результатом выполнения данного примера будет что-то подобное:
Замечание: До PHP 7.1 аргументы не имели значения, если не определена функция конструктора.
Свойства и методы
Пример #7 Доступ к свойству vs. вызов метода
public function bar () <
return ‘метод’ ;
>
>
Результат выполнения данного примера:
Это означает, что вызвать анонимную функцию, присвоенную переменной, напрямую не получится. Вместо этого свойство должно быть назначено, например, переменной. Можно вызвать такое свойство напрямую, заключив его в скобки.
Пример #8 Вызов анонимной функции, содержащейся в свойстве
Результат выполнения данного примера:
extends
Класс может наследовать константы, методы и свойства другого класса используя ключевое слово extends в его объявлении. Невозможно наследовать несколько классов, один класс может наследовать только один базовый класс.
Наследуемые константы, методы и свойства могут быть переопределены (за исключением случаев, когда метод класса объявлен как final) путём объявления их с теми же именами, как и в родительском классе. Существует возможность доступа к переопределённым методам или статическим свойствам путём обращения к ним через parent::
Пример #9 Простое наследование классов
class ExtendClass extends SimpleClass
<
// Переопределение метода родителя
function displayVar ()
<
echo «Расширенный класс\n» ;
parent :: displayVar ();
>
>
Результат выполнения данного примера:
Правила совместимости сигнатуры
Пример #10 Совместимость дочерних методов
Результат выполнения данного примера:
Следующие примеры демонстрируют, что дочерний метод, который удаляет параметр или делает необязательный параметр обязательным, несовместим с родительским методом.
Пример #11 Фатальная ошибка, когда дочерний метод удаляет параметр
class Extend extends Base
<
function foo ()
<
parent :: foo ( 1 );
>
>
Результат выполнения данного примера в PHP 8 аналогичен:
Пример #12 Фатальная ошибка, когда дочерний метод делает необязательный параметр обязательным.
Результат выполнения данного примера в PHP 8 аналогичен:
Переименование параметра метода в дочернем классе не является несовместимостью сигнатуры. Однако это не рекомендуется, так как приведёт к Error во время выполнения, если используются именованные аргументы.
Пример #13 Ошибка при использовании именованных аргументов и параметров, переименованных в дочернем классе
Результатом выполнения данного примера будет что-то подобное:
::class
Пример #14 Разрешение имени класса
namespace NS <
class ClassName <
>
Результат выполнения данного примера:
Разрешение имён класса с использованием ::class происходит на этапе компиляции. Это означает, что на момент создания строки с именем класса автозагрузки класса не происходит. Как следствие, имена классов раскрываются, даже если класс не существует. Ошибка в этом случае не выдаётся.
Пример #15 Отсутствует разрешение имени класса
Результат выполнения данного примера:
Начиная с PHP 8.0.0, константа ::class также может использоваться для объектов. Это разрешение происходит во время выполнения, а не во время компиляции. То же самое, что и при вызове get_class() для объекта.
Пример #16 Разрешение имени объекта
Результат выполнения данного примера:
Методы и свойства Nullsafe
Пример #17 Оператор Nullsafe
Оператор nullsafe лучше всего использовать, когда null считается допустимым и ожидаемым значением для возвращаемого свойства или метода. Для индикации ошибки предпочтительнее выбрасывать исключение.
User Contributed Notes 11 notes
I was confused at first about object assignment, because it’s not quite the same as normal assignment or assignment by reference. But I think I’ve figured out what’s going on.
First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.
Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object’s «handle» goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.
What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.