Pull to refresh

Comments 28

А что, в пыхпыхе «наследуются» статические методы?
Незнаю, если совсем уж любое решение — можно через debug_backtrace выдирать имя, по которому метод был вызван, ну и соот-но explode('::', $имя_метода);
Как? У меня не получилось. Кстати, условие такое, что класс Product должен быть пустым, т.е. без методов и свойств.
Ну если совсем уж любое решение подойдет — тогда можно продолжить мысль, debug_backtrace не присылает имя дочернего класса, зато присылает имя файла и номер строки, где все это дело вызывается, можно вырезать имя дочернего класса оттуда :) Что-то вроде:

public static function find() {
list($aTrace) = debug_backtrace();
$aFile = file($aTrace['file']);
$sLine = $aFile[$aTrace['line'] — 1];
$iEnd = strpos($sLine, $aTrace['type'].$aTrace['function']);
echo substr($sLine, 0, $iEnd);
}

В данном конкретном примере правда обрезается только конец строки, если сначала перед вызовом будет — тоже попадет в имя, для полностью рабочего состояния нужно еще помудрить :)
Во, полная версия моего монстрообразного креатива :) Скорость работы данной конструкции будет воистину коллосальной :)

public static function find() {
list($aTrace) = debug_backtrace();
$aFile = file($aTrace['file']);
$sLine = $aFile[$aTrace['line'] — 1];
$iEnd = strpos($sLine, $aTrace['type'].$aTrace['function']);
$sLine = substr($sLine, 0, $iEnd);
$sToken = strtok($sLine, '( .=&|');
while($sToken) {
$sName = $sToken;
$sToken = strtok('( .=&|');
}
return $sName;
}
Но — зато работает). Пока и такой костыль сойдет.
Дружно ждем версию 5.3)
Тьфу, извиняюсь, даже так нельзя :)
Можно пробовать через debug_backtrace(), но лучше, наверное, подождать «static::».
Хотя, если вы вызываете не из метода потомка, то и через debug_backtrace у вас ничего не получится.
Вот, сделал грязнющий хак. Конечно, так делать нельзя, но я сделал, чисто для эксперимента.

class Model_Base {
  public static function get_sub_class_name() {
    foreach (array_reverse(get_declared_classes()) as $classname) {
      if (is_subclass_of(new $classname, get_class())) {
        return $classname;
        break;
      }
    }
  }
  
  public static function find() {
    return self::get_sub_class_name();
  }
}

class Product extends Model_Base {
  
}

echo Product::find();


* This source code was highlighted with Source Code Highlighter.


Выведет: Product
Тоже блин вариант :) Даже незнаю что будет работать быстрее, мой способ или ваш, хотя это конечно от количества классов зависит :) скорее всего всетки ваш.
Надо тест провести, глянуть какой вариант быстрее.
И если вы добавите ещё один класс, который наследуется от Model_Base, то ваш код не будет работать правильно.
Вы правы. Фигня получилась.
Во-первых, вызывая метод статически, Вы по-любому знаете имя класса, иначе Вы не сможете его вызывать.
Во-вторых, статические методы они вызываются для того класса, для которого они определены, в данном случае, сколько бы раз вы не унаследовали, при вызове find, всё одно окажетесь в классе Model_Base

Если убрать все статики, то будет как надо:
<?php

class Model_Base {
public function find() {
  return get_class($this);
}
}

class Product extends Model_Base { }

$obj = new Product();

echo $obj->find();

* This source code was highlighted with Source Code Highlighter.
Да, придется так и сделать и не выпендриваться. Единственное, что можно сделать,
так это поределить в классе Product статический метод find(__CLASS__, *args), тогда получится так, как я хотел.
Но — это некрасиво, не хочу засорять лишней логикой Product. Поэтому, обойдусь без статического find().
Если вам нужно имя класса — у вас плохая архитектура (с) Буч
Я задавал 2 недели на phpclub ЭТОТ же вопрос.
Просто решил все перепроектированием.

Вывод такой: наследование и статические методы практически несовместимы.
>>>Реально ли в PHP 5.2 получить имя подкласса (т.е. Product) в статическом методе find() класса Model_Base?

Да реально:

class Model_Base {
public static function find() {
return get_class();
}
}

class Product extends Model_Base {
public static function find() {
return get_class();
}
}

echo Product::find();

в статическом методе find() класса Model_Base?

Вы по-моему невнимательно читали условие задачи.
афтор видимо невнимательно читал мануалы по ООП для пэхэпэ, и неправильно сформулировал задачу.
афтар хочет прострелить себе ногу, а не руку. не путайте его ;-)
Совсем нет. Наоборот, пытаюсь улучшить себе процесс кодинга. Для ORM решение этой задачи было бы полезно, мне не пришлось бы каждый раз создавать новый экземпляр класса, что сэкономило бы врямя и было бы более читаемо (смотрим, как в ActiveRecord для Ruby сделано).

Но в php подобное можно будет сделать только начиная с 5.3. Поэтому — ждем.
угу, в процедурном программировании вообще не надо объектов создавать =)
покажи свой нечитаемый код, хоть.
find('Product', ...) Model_find('Product', ...) Model::find('Product', ...)
Cделать что нибуть в этом роде — религия не позволяет?

Нет веть обязательно нужен синтаксический сахар, о да… потомучто вот в другом езыке так сделано… да будем ждать когда же блять наконец разработчики соизволят добавить очень нужную фичу…
Сделал так:

$p = new Products;
$p->title = "";
Сделал так:

$p = new Product;

// Получаем объект rowset
$rowset = $p->find('all');
Sign up to leave a comment.

Articles