Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> привести объект родительского класса к потомковому 
V
    Опции темы
flashaa
Дата 6.2.2008, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Я написал свой класс, который наследует DOMDocument.

Код

class My extends DOMDocument {

    public function __construct() {
        parent::__construct('1.0', 'utf-8');
    }
    ..
    ..
    public function createNode($name) {
        $node = $this->createElement($name);
        $this->appendChild($node);

         return $node;
    }
}


Класс содержит несколько методов, чтобы упростить работу с DOM, сделать синтаксис короче.
так же я привел  пример одного метода  (createNode), чтобы показать суть работы класса. А она такова: при добавлении новых узлов, эти узлы возвращаются, чтобы можно было с ними дальше работать, т.е. составить цепочку вызовов, примерно так:
Код

$my = new My();
$my->createNode('root')->addAttribs(array(0 => 'a', 1 => 'b', 2 => 'c'))->createNode('child');

Методы моего класса возвращают объекты типа DOMElement, а надо сделать, чтобы они возвращали объекты моего класса, который я напишу, наследуя DOMElement
Код

class MyElement extends DOMElement {
}

В MyElement я соотвественно напишу метод addAttribs и другие, которые будут дополнять функционал DOMElement, чтобы цепочка вызовов работала.

Но вот проблема: когда я пытаюсь вернуть узел из объекта My (строка return $node;) возвращаемый элемент, как я ни пытался, всегда возвращает объект DOMElement, а не мой.
Код

public createNode($name) {
        $node = $this->createElement($name);
        $this->appendChild($node);

         return (MyElement)$node; // ошибка синтаксиса
    }

Код

public createNode($name) {
        $node = $this->createElement($name);
        $this->appendChild($node);
        $myNode = new MyElement();
        $myNode = $node;

        return $myNode; // возвращает объект DOMElement;
   }

Пробовал делать конструктор MyElement таким: 
Код

public function __construct($el)  {
    return $el; // или clone($el);
}

И возвращать так:
Код

return new MyElement($node);

Так при работе createNode действительно возвращает объект MyElement, но почему-то при любой последствующей работе, например
Код

$node->setAttribute(1,1);

выдает ошибку
 Warning: DOMElement::setAttribute() [function.DOMElement-setAttribute]: Couldn't fetch MyElement

Как реализовать то, что я хочу?

Это сообщение отредактировал(а) flashaa - 6.2.2008, 15:23
PM MAIL   Вверх
flashaa
Дата 6.2.2008, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Если сказать проще, вопрос будет такой:
Как сделать объект-потомок, имея родительский?
Есть object-DOMElement,  надо получить object-MyElement при том, что 
Код

class MyElement extends DOMElement { ...}

PM MAIL   Вверх
Glip
Дата 6.2.2008, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 473
Регистрация: 30.12.2006

Репутация: 7
Всего: 18



может быть не всё правильно понял, если в My переопределить метод createElement чтобы он возвращал MyElement. или что там .... происходит при 
Код
 $this->createElement()
 ?

Код

public createNode($name) {
        $node = new MyElement($name);
        $this->appendChild($node);

        return $node; // возвращает объект DOMElement;
   }




--------------------
user posted image
PM MAIL   Вверх
flashaa
Дата 6.2.2008, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Glip, + 100! Предложенный вариант отлично работает!

Добавлено через 9 минут и 51 секунду
Но теперь у меня другая проблема,
член parentNode..
$myElement->parentNode уже существует, т.е. его нельзя создать самому, но его тип опять DOMElement..
PM MAIL   Вверх
Glip
Дата 6.2.2008, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 473
Регистрация: 30.12.2006

Репутация: 7
Всего: 18



вероятно надо смотреть и переопределять, если необходимо, appendChild()

а при наличии полного кода, можно наверное найти оптимальное решение


--------------------
user posted image
PM MAIL   Вверх
sTa1kEr
Дата 6.2.2008, 21:07 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



flashaa, я вижу тут только один реальный способ. Отказаться от наследования от классов DOM, а написать свои wrapper-ы. Т.е. все классы MyDocument, MyElement и прочие будут повторять методы DOM, просто будут дергать соответствующие методы классов DOM через __call(), а те что нужно доработать или не достаточно логики __call() создать самому. А поля либо заполнять вручную, либо аналогично дергать их через __get(); Пример:
Код

class MyDocument extends MyNode
{
    public function __construct($version, $encoding)
    {
        parent::__construct(new DOMDocument($version, $encoding));
        // либо использовать фабрику
    }

    public function createElement($name, $value = null)
    {
        $element = parent::nodeFactory($this->node->createElement($name, $value));
        // что-то делаем свое с ним
        return $element;
    }

    // etc

}

class MyElement extends MyNode
{
    public function __construct($name, $value, $namespaceURI)
    {
        parent::__construct(new DOMElement($name, $value, $namespaceURI));
        // аналогично
    }

    public function prependChild($myNode)
    {
        // свой метод
        return $this->insertBefore($myNode, $this->firstChild);
    }
    
    // ...
}

class MyNode
{
    protected $node;

    protected function __construct($domNode)
    {
        $this->node = $domNode;
        // если надо, то еще то-то делаем
    }

    public function __get($name)
    {
        // если это нода, то обертываем, иначе возращаем as is
        $value = $this->node->$name;
        if ($value instanceof DOMNode)
        {
            return self::nodeFactory($value);
        }

        return $value;
    }

    public function __call($name, $args)
    {
        $value = call_user_func_array(array($this->node, $name), $args);
        if ($value instanceof DOMNode)
        {
            return self::nodeFactory($value);
        }

        return $value;
    }

    // ...

    static protected function nodeFactory($domNode)
    {
        // по типу ноды обертываем в соответствующий класс и если надо что-то еще сделаем
    }
}


Это сообщение отредактировал(а) sTa1kEr - 6.2.2008, 21:14
PM MAIL   Вверх
flashaa
Дата 6.2.2008, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Цитата(Glip @  6.2.2008,  19:12 Найти цитируемый пост)
вероятно надо смотреть и переопределять, если необходимо, appendChild()

Как его можно переопределить, если это встроенный класс. Его код мне недоступен. Да, задача геморрой, поэтому, если будут альтернативные предложения похожей функциональности,то постите здесь. Кстати есть уже готовые инструменты для DOMDocument ?

Добавлено через 9 минут и 54 секунды
sTa1kEr, спасибо, ваш вариант представляется мне очень неплохим. __call(), __get() очень подходит сюда, завтра опробую в коде. А сейчас большое спасибо!
PM MAIL   Вверх
flashaa
Дата 8.2.2008, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



sTa1kEr, я не очень понял, как это мне поможет в том смысле, что нету собственно решения моей проблемы, а именно все завязано на методе, который должен вернуть
Код

static protected function nodeFactory($domNode)
    {
        // по типу ноды обертываем в соответствующий класс и если надо что-то еще сделаем
    }

Код

if ($value instanceof DOMNode)
        {
            return self::nodeFactory($value);
        }

Т.е. если возвращаемый объект является объектом DOMNode, то необходимо его преобразовать, получить из него MyNode с помощью nodeFactory - если я правильно понял, хотя не уверен. В таком случае меня как раз и интересовало преобразование из DOMNode в MyNode.
Допустим я получаю какую-то ноду DOMNode и условие ( if ($value instanceof DOMNode) ) сработало, то что тогда nodeFactory делает с полученной нодой ? Т.е. поясните вот эту строку:
Цитата

// по типу ноды обертываем в соответствующий класс и если надо что-то еще сделаем


Это сообщение отредактировал(а) flashaa - 8.2.2008, 10:46
PM MAIL   Вверх
sTa1kEr
Дата 11.2.2008, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


9/10 программиста
***


Профиль
Группа: Завсегдатай
Сообщений: 1553
Регистрация: 21.2.2007

Репутация: 56
Всего: 146



Цитата(flashaa @  8.2.2008,  11:45 Найти цитируемый пост)
В таком случае меня как раз и интересовало преобразование из DOMNode в MyNode.

Вобщем-то не преобразование, а обертка. Весь смысл заключается в заполнении свойства $node... и все.

Цитата(flashaa @  8.2.2008,  11:45 Найти цитируемый пост)
Допустим я получаю какую-то ноду DOMNode и условие ( if ($value instanceof DOMNode) ) сработало, то что тогда nodeFactory делает с полученной нодой ? Т.е. поясните вот эту строку:

Все что необходимо - это создать экземпляр своего класса и присвоить свойству $node оригинальный объект $domnode. В итоге - это простейший свитч... 
Код

switch (strtolower(get_class($domnode)))
{
    case "domnode":
        $obj =  new MyNode();
        break;
    case "domelement":
        $obj =  new MyElement();
        break;
// ...
}
$obj->node = $domnode;
return $obj;

И не забыть в конструкторах сделать аргументы не обязательными
PM MAIL   Вверх
flashaa
Дата 11.2.2008, 17:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



sTa1kEr, да, теперь кажется врубился.
PM MAIL   Вверх
flashaa
Дата 12.2.2008, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Stalker, спасибо! Задача решена
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0986 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.