Çiftleşmiş sistem kapsam sorunu

4 Cevap php

PHP bir iskelet Görüntüle sistemi kamçılamak için çalışıyorum, ama ebeveynlerinin değişkenleri almak için görüşlerini gömülü almak için nasıl anlamaya olamaz. Örneğin:

View Class

class View
{
    private $_vars=array();
    private $_file;

    public function __construct($file)
    {
        $this->_file='views/'.$file.'.php';
    }

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

        return $this;
    }

    public function output()
    {
        if (count($this->_vars))
            extract($this->_vars,  EXTR_REFS);
        require($this->_file);
        exit;
    }

    public static function factory($file)
    {
        return new self($file);
    }
}

test.php (top level view)

<html>
    <body>
        Hey <?=$name?>! This is <?=$adj?>!
        <?=View::factory('embed')->output()?>
    </body>
</html>

embed.php (embedded in test.php

<html>
    <body>
        Hey <?=$name?>! This is an embedded view file!!
    </body>
</html>

Code:

$vars=array(
    'name' => 'ryan',
    'adj' => 'cool'
);
View::factory('test')->set($vars)->output();

Output:

Hey ryan! This is cool! Hey [error for $name not being defined] 
this is an embedded view file!!

Sorun üst düzey görünümünde ayarlamak değişkenler gömülü görünümüne geçmiş olsun kalmamasıdır. Bunu nasıl yapacaksın?

4 Cevap

Yani, tam olarak soruya cevap değilim, ama burada benim süper basit el-yetiştirilen şablon sistemi bulunuyor. Arayüzü farklı olmasına rağmen, yapmaya çalıştığınız şeyi destekler.

// Usage
$main = new SimpleTemplate("templating/html.php");
$main->extract($someObject);
$main->extract($someArray);
$main->name = "my name";
$subTemplate = new SimpleTemplate("templating/another.php");
$subTemplate->parent($main);
$main->placeholderForAnotherTemplate = $subTemplate->run();
echo $main; // or $main->run(); 

// html.php
<html><body><h1>Title <?= $name ?></h1><p><?= $placeHolderForAnotherTemplate ?></p></body></html>

    <?php
// SimpleTemplate.php
function object_to_array($object)
{
	$array = array();
	foreach($object as $property => $value)
	{
		$array[$property] = $value;
	}

	return $array;
}

class SimpleTemplate
{
	public $source;
	public $path;
	public $result;
	public $parent;

	public function SimpleTemplate($path=false, $source=false)
	{
		$this->source = array();
		$this->extract($source);
		$this->path($path);
	}

	public function __toString()
	{
		return $this->run();
	}

	public function extract($source)
	{
		if ($source)
		{
			foreach ($source as $property => $value)
			{
				$this->source[$property] = $value;
			}
		}
	}

	public function parent($parent)
	{
		$this->parent = $parent;
	}

	public function path($path)
	{
		$this->path = $path;
	}

	public function __set($name, $value)
	{
		$this->source[$name] = $value;
	}

	public function __get($name)
	{
		return isset($this->source[$name]) ? $this->source[$name] : "";
	}

	public function mergeSource()
	{
		if (isset($this->parent))
			return array_merge($this->parent->mergeSource(), $this->source);
		else
			return $this->source;
	}

	public function run()
	{
		ob_start();
		extract ($this->mergeSource());
        include $this->path;
        $this->result = ob_get_contents();
        ob_end_clean();
        return $this->result;
	}
}

iyi, sınıfın yeni bir örneğini oluşturmak, böylece gömülü şablonda tanımlanan herhangi bir değişken vardır. Bunun yerine bir yenisini oluşturmak yerine, nesneyi kopyalamak için çalışmalısınız.

edit: Ben fabrika yöntemi bahsediyorum

Ana sorun, görüşler birbirlerinin doğrudan bilgiye sahip olmasıdır. Bu arayarak:

<?=View::factory('embed')->output()?>

Lütfen "ebeveyn" görünümünde, bunu başka bir şablon içinde olduğu gerçeği hiçbir bilgiye sahip bir şablon oluşturmak ve çıkış.

Burada tavsiye verebilecek iki yaklaşım vardır.

#1 - Associate your templates.

Gömülü şablonlar bir ana şablon "çocuklar" yaparak, onları output() anda ebeveynin değişkenlere erişim için izin verebilir. Ben inşa Görünüm sisteminde bu yaklaşımı kullanmaktadır. Böyle bir şey gider:

$pView = new View_Parent_Class();
$cView = new View_Child_Class();
$pView->addView($cView);

$pview->render() anda, çocuk görünümünde kolayca ebeveynin değişkenlere erişim verilir.

Bu yöntem sizin için üstlenmeden çok gerektirebilir, bu yüzden kirli ayrıntıları bırakın ve ikinci yaklaşım içine gidersiniz.

#2 - Pass the parent variables

Bu muhtemelen şimdiye kadar aldım yaklaşım verilen uygulamak için en kolay yöntem olacaktır. Çıkış yöntemi isteğe bağlı bir parametre ekleyin ve bu gibi, biraz onu yeniden:

public function output($extra_vars = null)
{
    if (count($this->_vars))
        extract($this->_vars,  EXTR_REFS);
    if (is_array($extra_vars)) extract($extra_vars, EXTR_REFS);
    require($this->_file);
    exit;
}

Basit bir alıcı yöntem eklemek yanı ise:

public function get_vars()
{
    return $this->_vars;
}

Sonra ebeveynin değişkenler etkili ne salt erişim ile dosyalarınızı gömebilirsiniz:

<?=View::factory('embed')->output($this->get_vars())?>

$this Geçerli şablonla, yani bir referans olacaktır. ana. Çünkü iki extract çağrıları bu yöntemle değişken adı çarpışmalar olabileceğini unutmayın.

Eğer özellikle zarif, senin $ _VARS özelliği statik değil yapabilir, ama size ulaşmak için çalışıyoruz ne için çalışmak istiyorum.

Bir yan not ... seti içinde array_merge () () işlevi yanlış, etrafında 2 değişkenleri takas.