Объединение объекта с массивом

Alien85

I like my cat
Всем привет, на текущий момент у меня в движке шаблонизатор может кушать либо объекты, либо массивы.

Пример для объекта:
PHP:
$User = User::getByID($id);
$Template->Parse($User);
Пример для массива:
PHP:
$data = array(
	'Title' => 'Заголовок',
	'Text' => 'Some text'
);
$Template->Parse($User);
Парсер выглядит так:
PHP:
function Parse($TPL)
{
	...
	ob_start();
	include $fileUse; // Файл вида, в котором конструкции: aaa <?=$TPL['Title']?> bbb
	$this->Template = ob_get_contents();
	ob_end_clean();
	...
}
Так вот вопрос, что делать если нужно передать и массив и объект одновременно?
array_merge для объектов не работает.
Неужели выходом будет только $Object->toArray() ?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
PHP:
<?php
class View {
    static public function factory($view)
    {
        return new static($view);
    }

    protected $vars     = array();
    protected $template = false;
    protected $view     = false;

    protected function __construct($view)
    {
        $this->view = $view;
        if ($file = is_file($view))
        {
            $this->template = $file;
        }
        else
        {
            throw new Exception('Unable to find view ' . $view);
        }
        return;
    }

    public function set($key, $value = null)
    {
        if (is_array($key))
        {
            $this->vars = array_merge($this->vars, $key);
        }
        else
        {
            $this->vars[$key] = $value;
        }
        
        return $this;
    }

    public function render()
    {
        if ($this->template)
        {
            extract($this->vars);
            ob_start();
            try
            {
                include $this->template;
            }
            catch (Exception $e)
            {
                ob_end_clean();
                throw $e;
            }
            return ob_get_clean();
        }
        else
        {
            throw new Exception('View not found in '.$this->view);
        }
        return false;
    }

    public function display()
    {
        echo $this->render();
        return;
    }

    public function __set($key, $value)
    {
        $this->set($key, $value);
        return true;
    }

}
?>
Выкидывал свои зависимости из кода, если что сломал - сорри, понять все равно можно.
 

Alien85

I like my cat
флоппик
Впринципе, у меня был такой же шаблонизатор, но я захотел добавить поддержку целых объектов.
Например, вот так: $View->Set($User);
Как раз вся проблема в строчке $this->vars = array_merge($this->vars, $key);
Пока вижу выход, если добавить $Object->toArray(), но это очень снизит скорость парсера для больших объектов.

// спустя минуту:
$Object->toArray() не получится, т.к. мои объекты содержат вычисляемые поля и иногда их очень много.
как пример вычисляемых полей:
PHP:
	protected function var_UserUrl()
	{
		return '/users/' . $this->ID() . '.html';
	}
	
	protected function var_ImageUrlMicro()
	{
		return ( empty($this->image) )
			? Url::getInstance()->Parse('.i/u_noimage.jpg')
			: $this->PathImage('u');
	}
	
	protected function var_ImageUrlProfile()
	{
		return ( empty($this->image) )
			? Url::getInstance()->Parse('.i/m_noimage.jpg')
			: $this->PathImage('l');
	}

	protected function var_SexRus()
	{
		return ( $this->sex == 'men' )
			? 'Мужской'
			: 'Женский';
	}

	protected function var_Friends()
	{
		if ( empty( $this->userFriends ) )
		{
			$this->userFriends = new UserFriends($this, 600);
		}
		
		return $this->userFriends;
	}
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Не вижу проблемы. Передал объект — ну и работай с объектом. Проблема то в чем? На худой конец, ArrayAccess ему приделай.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
$this->set('user', $user); вообще-то, что немаловажно.
 

Alien85

I like my cat
Вместе с объектом иногда нужно передать другие строчки.
PHP:
$data = array(
    'Title' => 'Заголовок',
    'Text' => 'Some text'
);
$Template->Parse($data);
$Template->Parse(User::getByID($id));
Т.е. помимо информации о объекте, виду необходимо передать дополнительную информацию.
 

Духовность™

Продвинутый новичок
Alien85
иМХО шаблон точно должен знать, что выводить - объект или массив. И не должно быть так, что бы тут у тебя код возвращал массив данных объекта, а тут - объект. Надо к общему знаменателю придти.

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

Alien85

I like my cat
Alien85
иМХО шаблон точно должен знать, что выводить - объект или массив. И не должно быть так, что бы тут у тебя код возвращал массив данных объекта, а тут - объект. Надо к общему знаменателю придти.
Так и получается. Просто шаблонизатор был довольно сложный. Сейчас я его усекаю и все встает на свои места, как и должно быть.

А обертки я стараюсь не использовать, так сказать, пытаюсь сделать код наиболее нативный - проще отладка, выше быстродействие. Что может быть еще нужно?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Не, смотри, если взять твой пример:
PHP:
$data = array(
    'Title' => 'Заголовок',
    'Text' => 'Some text'
);
то в моем шаблонизаторе, при помощи extract():
$this->set('info', $data) - Даст тебе внутри шаблона массив $info - $info['title'], $info['text']
$this->set($data) - Даст тебе переменные $title и $text,
$this->set('user', $user) Даст тебе ссылку на объект $user в шаблоне, и там ты можешь с ним работать либо прямо как с объектом, или приделать ему ArrayAccess и у тебя все будет выглядеть массивами — в любом случае, все вычисляемые поля будут работать, поскольку это обычный референс на обычный объект.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Можно кстати делать извращения типа $this->set('view', $this).
 

Alien85

I like my cat
флоппик
я это все уже понял. Все красиво и хорошо. Спасибо еще раз.
 
Сверху