Access to parent object variables from scope of child object in php

So, I studied template mechanisms and how to create my own simple template engine. From a pure training perspective, I read a couple such as this one here .

Using a small modified version of the class mentioned in the link above, I thought about testing it, but ran into a problem.

When I call instances of the same template class for internal HTML, and then assign it as a var / value pair to the parent instance, I cannot access the main parent variables in the HTML (child).

Incomprehensible?

Perhaps the following code will help.

So, if I initialize the template as such (the template class matches the one specified in the link above) -

$_page = new tplEngine(); $_page->load(TPLFILES_DIR . "/root.php"); 

and then initialize header.html as a new instance of the tplEngine class and assign it as a variable for the first instance as follows:

 $_header = new tplEngineChild(TPLFILES_DIR . "/common/header.html"); $_page->set("header", $_header->parse()); 

Where...

root.php
---------------

 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <title><?php print $this->title; ?></title> <meta name="keywords" content="<?php print $this->meta_keywords; ?>" /> <meta name="description" content="<?php print $this->meta_description; ?>" /> <?php foreach($this->styles as $stylepath) : ?> <link rel="stylesheet" type="text/css" href="<?php print $stylepath; ?>" /> <?php endforeach; ?> </head> <body> <div class="body-wrap"> <div class="header"> <?php print $this->header; ?> </div> <div class="content-wrap"> <?php var_dump($this->mid_content); ?> </div> <div class="footer"> <?php print $this->footer; ?> </div> </div> </body> </html> 

and

header.html
-----------------

 <div class="mainHeader"> <div class="logo"> webTrack.in' </div> <div class="dashboard"> <?php if($this->get(isLoggedIn) == false) : ?> <p class="greeting">Hello <span class="username"><?php echo this->username; ?></span></p> <a class="logout">logout</a> <?php else : ?> <p class="greeting">Hello <span class="username"><?php echo $this->username; ?></span></p> <p><a onclick="showLogin()">Login</a></p> <form id="loginForm" class="login form" action="" method="post"> <input type="text" name="username" value="Username" /> <input type="password" name="password" value="Password" /> </form> <?php endif; ?> </div> </div> <nav> <ul class="headerNav"> <li><a href="/">Home</a></li> <li><a href="/pricing">Plans and Pricing</a></li> <li><a href="/aboutUs">About Us</a></li> </ul> </nav> 

(In the above case, $this->get(isLoggedIn) and this->username are the variables assigned to the instance of $ _page) I ran into a problem when in the header.html file I cannot access the variables set in the instance of $ _page class tplEngine.

What would be the best approach to solve this problem?

Everything worked fine when I installed the $_page as global in header.html. But is this the right approach?

+4
source share
5 answers

About object inheritance

The class is a template for objects and defines the properties and methods of the object, and the object is an instance of the class. When you extend a class, the child class inherits properties and methods from the parent.

In your case, there is no inheritance (parent-child relationship), $_header , since a single object is only a property of $_page . To enable the "link between the two objects, $_header must have a link to the $_page object.


Template Class

This is a modified version of the Template class that you are using. When you dynamically create properties, you should use the __set() and __get() magic methods . It also uses the __toString() method, so that template objects can be treated as a string. All variables that the template file uses must be assigned to the template object. Using the class defined in this way, all templates are displayed at the same time.

 class tplEngine { private $template = ''; public function __set( $var, $content ) { $this->$var = $content; } public function __get( $var ) { return ( isset($this->$var) ? $this->$var : null ); } public function __construct( $template ) { // is_readable() - tells whether a file exists and is readable if ( !is_readable( $template ) ) throw new IOException( "Could not find or access file: $template" ); $this->template = $template; } public function __toString() { ob_start(); require ( $this->template ); $content = ob_get_clean(); return $content; } } // usage: $_page = new tplEngine( TPLFILES_DIR . "/root.php" ); $_header = new tplEngine( TPLFILES_DIR . "/common/header.html" ); $_header->isLoggedIn = true; $_header->username = 'some-username'; $_page->header = $_header; // in root.php echo $this->header; 

Access to Parent Variables

Parent property

One way to access variables in the "parent" object is to add the parent property to the template class through the constructor:

 public function __construct( $template, $parent = null ) { // is_readable() - tells whether a file exists and is readable if ( !is_readable( $template ) ) throw new IOException( "Could not find or access file: $template" ); $this->template = $template; $this->_parent = $parent; } 

Access to parent properties in templates, such as:

 $this->_parent->username; 

Make parent properties local

Another way is to make them local (a neat trick if you don't want to worry about calling $this->_parent ):

 public function __toString() { ob_start(); if ( $this->_parent ) { foreach ( get_object_vars( $this->_parent ) as $key => $value ) $$key = $value; } require ( $this->template ); $content = ob_get_clean(); return $content; } 

Additional Information

Adapter design pattern

PHP overload

Magic methods

Smarty Template Engine - area variables

+3
source

the problem is that $ _header is not a child of $ _page in the php class inheritance facilities, and you do not want them to be true php parent and child.

instead, modify the tplEngineChild constructor to take $ parent as an optional argument, in this case $ _page.

Constructor

might look like this:

 function __construct($parent = null, $template = null) { if(isset($parent)) { $this->parent = $parent; } if (isset($template)) { $this->load($template); } } 

now $ header can use $ this-> parent-> username. Be sure to include "public $ username" in the definition of the parent class. You can use the overload of the php (_get) method to automatically resolve the properties of the parent if it does not exist in the child.

You can also pass $ _header instead of $ _header-> publish (); to $ _page-> set and change the $ _page template in header-> publish ()? >. Thus, the title is published when $ _page does, and not during a call to $ _page-> set ().

+1
source

Some concepts are used in different languages ​​in a different way. And although the same words are used, they do not match. This can be quite confusing. This, in my opinion, is the source of your question. I will describe three patterns used in patterns. Each template has its own specific relationship between parents and children.

1. differentiating implementations

The template template template has a strict relationship between parents and children. Children are extensions to the parent, which is usually an abstract class. Each child represents a different implementation of the parent. An example of an abstract template class is, for example, Shape. The realization of the child can be a triangle, a square and a circle. They all use some public abstract methods such as draw () and resize (), which all have the same implementation. The goal of the abstract method is to ensure that they all have a unique, characteristic implementation of this method (for this child). A base class may also have some non-abstract methods. Examples are methods like fill () and rotate (). Each child is allowed to override these methods, but this is not required if the default implementation is sufficient. Children will be able to use public / secure data and methods from the parent, see http://en.wikipedia.org/wiki/Template_method_pattern .

2. repeating composition

The template system in html files has a similar concept, but for a different purpose. The purpose of the template system in html files is to create a flexible system for inserting independent blocks. Each block is independent of any other block, so you cannot assume that they have something in common. They may have, but this is not necessary. You can compare this with the general methods of an abstract class, because in every html file you have to implement it the same way as in other files. They are independent units to provide maximum design flexibility. The same content block can be used in different template files without any problems. And they should be able to function that way. This is a composite design template. Parent-child relationships are best described as partial-whole relationships, see http://en.wikipedia.org/wiki/Composite_pattern .

3. general data, unique presentation

Inside each html fragment, the same data is used (all data of the current request and session). They have the same data, but they should not inherit anything from each other. They also have no implementation function. You may have a content block in which you display an overview of search results using a pager. Or you may have a block with a static footer. Each html template has only one header and one body. However, there may be more menus, and a particular menu may appear in different forms in different places. Therefore, you should consider Observer or MVC. The data used is part of the model. This is the same for all kinds of data during a single query. Each block represents a different representation of the model and will use the required information. No block should know the status information or data of any other block. This, in my opinion, is the reason you asked if $ _page should be global? You need this because of the general data. Not because of the html part of the file. (This is a matter of composition.) If you, however, separate the two parts of root.php and have a common data object for all the blocks, then it can work without the $ _page being global.

Output:

If the relations between parents and children in the template design template are between classes (not objects), between html fragments between blocks of html fragments and relations between the model and general data and the required data for any particular html fragment. Parent-child relations between classes are fixed, relations between whole goals between html fragments are flexible, the model’s attitude to presentation is standardized, but not fixed.

It is most effective if the data object is created only once and remains unchanged during the request. A global can do this, but a local variable in a method can also do this, like a static class variable. I would advise you to use this implementation, which is best suited for serving your application.

+1
source

Another possible approach is to not distinguish between tplEngine and tplEngineChild. Here's a simple implementation of what I mean.

 class tmplEngine { protected $template_root = ""; // container for the template variables protected $tmpl_vars = array(); public function __construct($tmpl_dir = null){ if ($tmpl_dir) $this->setTemplateDir($dir); } // sets a template root directory public function setTemplateDir($dir){ $this->template_root = $dir; } // parses an external file from the current scope public function parse($file){ ob_start(); require($this->template_root.$file); return ob_get_clean(); } // magic getter allows access as $tmplEninge->propertyName; public function __get($property){ return array_key_exists($property, $tmpl_vars)?$this->tmpl_vars[$property]:""; } // magic setter allow access as $tmplEngine->propertyName = "myVal" public function __set($property, $value){ $this->tmpl_vars[$property] = $value; } } 

So now your challenge will be something like this.

 $t = new tmplEngine(TPLFILES_DIR); $t->header = $t->parse("/common/header.html"); $t->main = $t->parse("/common/article.html"); $t->footer = $t->parse("/common/footer.html"); echo $t->parse("/root.html"); 

Hope this helps

0
source

Just point out some interesting points about the template system. In my own experience, patterns should be ... what they mean, patterns. Not a bunch of PHP code.

All those template systems that are actually used by all known systems (call it tpl, magento, oscommerce and the list are very long) are all but templates.

Why am I saying this:

It is assumed that the template should be part (you call the language, HTML, XML, WAP, CSS, JS, etc.) of natural code with parameters that need to be replaced in them.

The template should NOT contain a programming language in it, why: - Graphic designers or HTML players, as a rule, DO NOT understand the code - you need a programmer to change the templates - The template becomes another piece of PHP code - you need (usually) a lot of knowledge programming language to be able to modify and maintain your code.

The template should be a natural language code with parameters that are easily understood by low programming skills.

This is a good template system, such as Java templates, C templates, and other language templates, since it does not mix PHP with native code:

http://www.webability.info/?P=documentacion&wiki=/DomCore/reference/Templates

Only my 2 cents for better programming

0
source

Source: https://habr.com/ru/post/1479138/


All Articles