How to mention a property in PHPDoc? - php

I am trying to mention a property of my class somewhere else in other comments of my class, ie. in a method of that class.
For example if we have this code:
(please search for: property $mention -- #property Village::mention does not work)
class Village {
/**
* #var array Data container.
*/
public $data = [];
/**
*
*/
public $mention = 'Me';
/**
* Village constructor which injects data.
*
* #param $data
*/
public function __construct($data) {
$this->data = $data;
}
/**
* A factory for our Villages.
*
* #return Village
*/
public static function hillbilly() {
return new Village;
}
/**
* Name tells the story...
*
* Now somewhere at this exact point I want to mention the
* $mention property -- #property Village::mention does not work
* nor does #property $mention either...
*
* #return array Rednecks unset.
*/
public function redneck() {
if(sizeof($data)) {
unset($data);
}
return $data;
}
}
$countryside = [
'important' => 'data',
'axe' => 'knifes',
'shovel' => 'hoe',
'trowel' => 'mixer',
];
$village = Village::hillbilly($countryside);
How do I make a mention of a property in PHPDoc?

If you need to have the $mention in the docblock text, one would usually use the inline see {#see element description}:
/**
* Name tells the story...
*
* Now somewhere at this exact point I want to mention the
* {#see Village::$mention} property.
*
* #return array Rednecks unset.
* #see Village::$mention
* #uses Village::$mention
*/
public function redneck() {
if(sizeof($data)) {
unset($data);
}
return $data;
}
The #see or #uses standalone tags are also available, but not for embedding the link into the docblock narrative text.
Note that older phpDocumentor only allowed the inlink link tag {#link url|element description}.

Related

PHPIDS on php 8.1 Deprecated Errors [duplicate]

This question already has answers here:
Reference: Return type of ... should either be compatible with ..., or the #[\ReturnTypeWillChange] attribute should be used
(2 answers)
Closed last year.
i got a problem with PHPIDS on a PHP 8.1 Server.
Here the Errors:
PHP Deprecated: Return type of IDS\Report::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phpids\ib\IDS\Report.php on line 205
PHP Deprecated: Return type of IDS\Report::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in phpids\lib\IDS\Report.php on line 218
I know Deprecated Errors are not that bad, but i want that everything works Perfect.
I Searched in Google several things but no solution found.
Hopefully you find the problem.
i use the actual PHPIDS version from Github (https://github.com/PHPIDS/PHPIDS)
i know this version is not the newest but i didn't found a newer one.
thx for the help
and here the Script Report.php
<?php
/**
* PHPIDS
*
* Requirements: PHP5, SimpleXML
*
* Copyright (c) 2008 PHPIDS group (https://phpids.org)
*
* PHPIDS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* PHPIDS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
*
* PHP version 5.1.6+
*
* #category Security
* #package PHPIDS
* #author Mario Heiderich <mario.heiderich#gmail.com>
* #author Christian Matthies <ch0012#gmail.com>
* #author Lars Strojny <lars#strojny.net>
* #license http://www.gnu.org/licenses/lgpl.html LGPL
* #link http://php-ids.org/
*/
namespace IDS;
/**
* PHPIDS report object
*
* The report objects collects a number of events and thereby presents the
* detected results. It provides a convenient API to work with the results.
*
* Note that this class implements Countable, IteratorAggregate and
* a __toString() method
*
* #category Security
* #package PHPIDS
* #author Christian Matthies <ch0012#gmail.com>
* #author Mario Heiderich <mario.heiderich#gmail.com>
* #author Lars Strojny <lars#strojny.net>
* #copyright 2007-2009 The PHPIDS Group
* #license http://www.gnu.org/licenses/lgpl.html LGPL
* #link http://php-ids.org/
*/
class Report implements \Countable, \IteratorAggregate
{
/**
* Event container
*
* #var Event[]|array
*/
protected $events = array();
/**
* List of affected tags
*
* This list of tags is collected from the collected event objects on
* demand when IDS_Report->getTags() is called
*
* #var string[]|array
*/
protected $tags = array();
/**
* Impact level
*
* The impact level is calculated on demand by adding the results of the
* event objects on IDS\Report->getImpact()
*
* #var integer
*/
protected $impact = 0;
/**
* Centrifuge data
*
* This variable - initiated as an empty array - carries all information
* about the centrifuge data if available
*
* #var array
*/
protected $centrifuge = array();
/**
* Constructor
*
* #param array $events the events the report should include
*
* #return Report
*/
public function __construct(array $events = null)
{
foreach ((array) $events as $event) {
$this->addEvent($event);
}
}
/**
* Adds an IDS_Event object to the report
*
* #param Event $event IDS_Event
*
* #return self $this
*/
public function addEvent(Event $event)
{
$this->clear();
$this->events[$event->getName()] = $event;
return $this;
}
/**
* Get event by name
*
* In most cases an event is identified by the key of the variable that
* contained maliciously appearing content
*
* #param string|integer $name the event name
*
* #throws \InvalidArgumentException if argument is invalid
* #return Event|null IDS_Event object or false if the event does not exist
*/
public function getEvent($name)
{
if (!is_scalar($name)) {
throw new \InvalidArgumentException('Invalid argument type given');
}
return $this->hasEvent($name) ? $this->events[$name] : null;
}
/**
* Returns list of affected tags
*
* #return string[]|array
*/
public function getTags()
{
if (!$this->tags) {
$this->tags = array();
foreach ($this->events as $event) {
$this->tags = array_merge($this->tags, $event->getTags());
}
$this->tags = array_values(array_unique($this->tags));
}
return $this->tags;
}
/**
* Returns total impact
*
* Each stored IDS_Event object and its IDS_Filter sub-object are called
* to calculate the overall impact level of this request
*
* #return integer
*/
public function getImpact()
{
if (!$this->impact) {
$this->impact = 0;
foreach ($this->events as $event) {
$this->impact += $event->getImpact();
}
}
return $this->impact;
}
/**
* Checks if a specific event with given name exists
*
* #param string|integer $name the event name
*
* #throws \InvalidArgumentException if argument is illegal
* #return boolean
*/
public function hasEvent($name)
{
if (!is_scalar($name)) {
throw new \InvalidArgumentException('Invalid argument given');
}
return isset($this->events[$name]);
}
/**
* Returns total amount of events
*
* #return integer
*/
public function count()
{
return #count($this->events);
}
/**
* Return iterator object
*
* In order to provide the possibility to directly iterate over the
* IDS_Event object the IteratorAggregate is implemented. One can easily
* use foreach() to iterate through all stored IDS_Event objects.
*
* #return \Iterator the event collection
*/
public function getIterator()
{
return new \ArrayIterator($this->events);
}
/**
* Checks if any events are registered
*
* #return boolean
*/
public function isEmpty()
{
return empty($this->events);
}
/**
* Clears calculated/collected values
*
* #return void
*/
protected function clear()
{
$this->impact = 0;
$this->tags = array();
}
/**
* This method returns the centrifuge property or null if not
* filled with data
*
* #return array
*/
public function getCentrifuge()
{
return $this->centrifuge;
}
/**
* This method sets the centrifuge property
*
* #param array $centrifuge the centrifuge data
*
* #throws \InvalidArgumentException if argument is illegal
* #return void
*/
public function setCentrifuge(array $centrifuge = array())
{
if (!$centrifuge) {
throw new \InvalidArgumentException('Empty centrifuge given');
}
$this->centrifuge = $centrifuge;
}
/**
* Directly outputs all available information
*
* #return string
*/
public function __toString()
{
$output = '';
if (!$this->isEmpty()) {
$output .= vsprintf(
"Total impact: %d<br/>\nAffected tags: %s<br/>\n",
array(
$this->getImpact(),
implode(', ', $this->getTags())
)
);
foreach ($this->events as $event) {
$output .= vsprintf(
"<br/>\nVariable: %s | Value: %s<br/>\nImpact: %d | Tags: %s<br/>\n",
array(
htmlspecialchars($event->getName()),
htmlspecialchars($event->getValue()),
$event->getImpact(),
implode(', ', $event->getTags())
)
);
foreach ($event as $filter) {
$output .= vsprintf(
"Description: %s | Tags: %s | ID %s<br/>\n",
array(
$filter->getDescription(),
implode(', ', $filter->getTags()),
$filter->getId()
)
);
}
}
$output .= '<br/>';
if ($centrifuge = $this->getCentrifuge()) {
$output .= vsprintf(
"Centrifuge detection data<br/> Threshold: %s<br/> Ratio: %s",
array(
isset($centrifuge['threshold']) && $centrifuge['threshold'] ? $centrifuge['threshold'] : '---',
isset($centrifuge['ratio']) && $centrifuge['ratio'] ? $centrifuge['ratio'] : '---'
)
);
if (isset($centrifuge['converted'])) {
$output .= '<br/> Converted: ' . $centrifuge['converted'];
}
$output .= "<br/><br/>\n";
}
}
return $output;
}
}
As of PHP 8.1, you have to fix the return type of the functions count() and getIterator() to match with interfaces.
public count(): int (see Countable)
public getIterator(): Traversable (see IteratorAggregate)
class Report implements \Countable, \IteratorAggregate
{
protected array $events;
public function count(): int
{
return count($this->events);
}
public function getIterator(): \Traversable
{
return new \ArrayIterator($this->events);
}
}

API-Platform: Filtering Custom Data Provider

I'm currently experiencing issues when trying to filter my results when using an external API source (Stripe) in API-Platform.
What I need to be able to do, is return a list of subscriptions for a specified customer. So going to http://localhost/api/subscriptions?customer=123foo would return all records matched to this customer.
Now, the code below is throwing an error because of the ORM\Filter and would be functional without it, as the actual filtering is performed on Stripes API, not by me, BUT, I really want the Swagger-API GUI to have the filter box.
In short, how do I get the Annotations in my Entity to display, searchable fields within the Swagger UI when using an external data source.
What I have is an Entity as below (simplified for example purposes):
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use Symfony\Component\Serializer\Annotation\Groups;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Core\Annotation\ApiFilter;
/**
* Subscriptions allow you to charge a customer on a recurring basis. A subscription ties a customer to a particular plan you've created.
* #ApiResource()
* #ApiFilter(SearchFilter::class, properties={"customer": "exact"})
* #package App\Entity
*/
class Subscription
{
/**
* Unique identifier for the object.
* #ApiProperty(identifier=true)
* #var string | null
*/
protected $id;
/**
* ID of the customer who owns the subscription.
* #var string | null
*/
protected $customer;
// Plus a bunch more properties and their Getters & Setters
}
And the SubscriptionCollectionDataProvider:
<?php
namespace App\DataProvider;
use App\Entity\Subscription;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Controller\BaseController;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Class SubscriptionCollectionDataProvider
* #package App\DataProvider
* #author dhayward
*/
final class SubscriptionCollectionDataProvider extends BaseController implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{
protected $requestStack;
/**
* SubscriptionCollectionDataProvider constructor.
* #param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack)
{
$this->request = $requestStack->getCurrentRequest();
}
/**
* #param string $resourceClass
* #param string|null $operationName
* #param array $context
* #return bool
*/
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return Subscription::class === $resourceClass;
}
/**
* #param string $resourceClass
* #param string|null $operationName
* #return \Generator
* #throws \Stripe\Error\Api
*/
public function getCollection(string $resourceClass, string $operationName = null): \Generator
{
$customer = $this->request->get("customer");
$data = \Stripe\Subscription::all(["customer" => $customer]);
foreach($data['data'] as $subscriptionObject){
$this->serializer()->deserialize(json_encode($subscriptionObject), Subscription::class, 'json', array('object_to_populate' => $subscription = new Subscription()));
yield $subscription;
}
}
}
Error result, which is presumably because I'm using an ORM/Filter without any ORM setup:
Call to a member function getClassMetadata() on null
Any pointers would be greatly appreciated.
So I finally managed to work it out. It was as simple as creating my own version of the SearchFilter, implementing ApiPlatform\Core\Api\FilterInterface.
<?php
namespace App\Filter;
use ApiPlatform\Core\Api\FilterInterface;
/**
* Class SearchFilter
* #package App\Filter
*/
class SearchFilter implements FilterInterface
{
/**
* #var string Exact matching
*/
const STRATEGY_EXACT = 'exact';
/**
* #var string The value must be contained in the field
*/
const STRATEGY_PARTIAL = 'partial';
/**
* #var string Finds fields that are starting with the value
*/
const STRATEGY_START = 'start';
/**
* #var string Finds fields that are ending with the value
*/
const STRATEGY_END = 'end';
/**
* #var string Finds fields that are starting with the word
*/
const STRATEGY_WORD_START = 'word_start';
protected $properties;
/**
* SearchFilter constructor.
* #param array|null $properties
*/
public function __construct(array $properties = null)
{
$this->properties = $properties;
}
/**
* {#inheritdoc}
*/
public function getDescription(string $resourceClass): array
{
$description = [];
$properties = $this->properties;
foreach ($properties as $property => $strategy) {
$filterParameterNames = [
$property,
$property.'[]',
];
foreach ($filterParameterNames as $filterParameterName) {
$description[$filterParameterName] = [
'property' => $property,
'type' => 'string',
'required' => false,
'strategy' => self::STRATEGY_EXACT,
'is_collection' => '[]' === substr($filterParameterName, -2),
];
}
}
return $description;
}
}

How to document settings method with phpdoc

I have a class with the methods getSetting($name) and setSetting($name,$value). These methods are used to set multiple settings throughout the class.
My question is what is the best way in phpDoc to document the available settings. I cannot do it above these methods i think, because the methods are defined only in the parent class and the children might have their own settings.
My first guess was to document it above each class in the description, so like this:
<?php
/**
* A tomato class. Needed for pizza
*
* Settings:
* color string default: red
* size integer
*/
class tomato extends fruit{
function __construct(){
$this->setSetting('color','red');
}
}
/**
* A fruit class
*
* Settings:
* price integer
*/
class fruit{
var $settings = array();
/**
* Sets setting
* #param string $name
* #param mixed $value
*/
function setSetting($name,$value = NULL){
$this->settings[$name] = $value;
}
/**
* Returns setting
* #param string $name
* #return mixed
*/
function getSetting($name){
if(isset($this->settings[$name])){
return $this->settings[$name];
}else{
return NULL;
}
}
}
?>
I was wondering if this was correct, or if there might be tags available for this, or maybe an other better solution.

PHPdoc - defining object properties for an object of stdClass

I am trying to figure out if it is possible to use PHPdoc to define the object properties being returned by a function or a object method.
Say I have the following class:
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
Now, it is easy enough to define input parameters.
/**
* Get Staff Member Details
*
* #param string $id staff id number
*
* #return object
*/
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
The question is is there a similar thing for defining properties of the output object (of a stdClass) returned by the method in question. So that another programmer does not have to open this class and manually look into the method to see what the return object is returning?
Here it is 4 years later, and there still does not appear to be a way to annotate the properties of a stdClass object as originally described in your question.
Collections had been proposed in PSR-5, but that appears to have been shot down: https://github.com/php-fig/fig-standards/blob/211063eed7f4d9b4514b728d7b1810d9b3379dd1/proposed/phpdoc.md#collections
It seems there are only two options available:
Option 1:
Create a normal class representing your data object and annotate the properties.
class MyData
{
/**
* This is the name attribute.
* #var string
*/
public $name;
/**
* This is the age attribute.
* #var integer
*/
public $age;
}
Option 2:
Create a generic Struct type class as suggested by Gordon and extend it as your data object, using the #property annotation to define what generic values are possible to access with __get and __set.
class Struct
{
/**
* Private internal struct attributes
* #var array
*/
private $attributes = [];
/**
* Set a value
* #param string $key
* #param mixed $value
*/
public function __set($key, $value)
{
$this->attributes[$key] = $value;
}
/**
* Get a value
* #param string $key
* #return mixed
*/
public function __get($key)
{
return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
}
/**
* Check if a key is set
* #param string $key
* #return boolean
*/
public function __isset($key)
{
return isset($this->attributes[$key]) ? true : false;
}
}
/**
* #property string $name
* #property integer $age
*/
class MyData extends Struct
{
// Can optionally add data mutators or utility methods here
}
You have only two way to document the structure of the result class.
1.One can describe the structure in a comment text. For example:
class SomeClass
{
/**
* Getting staff detail.
* Result object has following structure:
* <code>
* $type - person type
* $name - person name
* $age - person age
* </code>
* #param string $id staff id number
*
* #return stdClass
*
*/
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
2.One can create a data type that will inheritance stdClass and it will have an annotation of a result object. For example:
/**
* #property string $type Person type
* #property string $name Person name
* #property integer $age Person age
*/
class DTO extends stdClass
{}
And use it in your other classes
class SomeClass {
/**
* Getting staff detail.
*
* #param string $id staff id number
*
* #return DTO
*
*/
public function staffDetails($id){
$object = new DTO();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
In my opinion, this way is better than a description in the text comment because it makes the code more obvious
If you are using PHP 7, you can define anonymous class.
class SomeClass {
public function staffDetails($id){
$object = (new class() extends stdClass {
public /** #var string */ $type;
public /** #var string */ $name;
public /** #var int */ $age;
});
$object->type = "person";
$object->name = "dave";
$object->age = 46;
return $object;
}
}
It is working for my IDE (tested in NetBeans)
With for example json_decode it's harder to use own classes instead of stdClass, but in my case I just created dummy file with class definitions, which really isn't loaded and I'm adding own classes as #return (works for intelephense on vscode).
PHPdocObjects.php
/**
* class only for PHPdoc (do not include)
*/
class Member {
/** #var string */
public $type;
/** #var string */
public $name;
/** #var string */
public $age;
}
/**
* Other format
*
* #property string $type;
* #property string $name;
* #property string $age;
*/
class MemberAlt {}
SomeClass.php
/**
* Get Staff Member Details
*
* #param string $id staff id number
*
* #return Member I'm in fact stdClass
*/
class SomeClass {
public function staffDetails($id){
$object = json_decode('{"type":"person","name":"dave","age":"46"}');
return $object;
}
}
The hack I use for autocomplete in PhpStorm:
Create some meta file which will contain some classes to describe your structures. The file is never included and structures have their own name rules in order not to mess them with real existing classes:
<?php
/*
meta.php
never included
*/
/**
* #property string $type
* #property string $name
* #property string $age
*/
class StaffDetails_meta {}
Use the meta class as a return value in your real code PHPDoc:
<?php
/*
SomeClass.php
eventually included
*/
class SomeClass
{
/**
* Get Staff Member Details
*
* #param string $id staff id number
*
* #return StaffDetails_meta
*/
public function staffDetails($id)
{
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
Congratulations, this will make your IDE autocomplete your code when you'd typing something like (new SomeClass)->staffDetails('staff_id')->
P.S.: I know, almost 10 years passed but still actual

Zend and Smarty 3 integration using

I am trying to change the layout content in my controller, which only seems to overwrite it, only append.
I have built a CMS using Zend and Smarty. I have one main layout with, which displays the content for each page:
{$this->layout()->content}
Although when I try to overwrite the 'content' in the controller with a new content area this causes both the index/index.tpl and contact/contact.tpl to be displayed:
$this->view->content = $this->view->display('contact/contact.tpl');
I know I could manually assign the content to a view smarty variable, although I would like to reduce the assigns in smarty and use Zend.
In my application.ini
smarty.caching = 1
smarty.cache_lifetime = 14400
smarty.template_dir = PATH "/templates/default/"
smarty.compile_dir = PATH "/tmp/smarty_compile/"
smarty.plugins_dir = APPLICATION_PATH "/plugins/smarty/"
smarty.config_dir = ""
smarty.cache_dir = PATH "/tmp/smarty_cache/"
smarty.left_delimiter = "{"
smarty.right_delimiter = "}"
In my bootstrap.php
protected function _initView()
{
$view = new Web_View_Smarty($this->getOption('smarty'));
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$viewRenderer->setViewSuffix('tpl');
$viewRenderer->setView($view);
$this->bootstrap('layout');
$layout = Zend_Layout::getMvcInstance();
$layout->setViewSuffix('tpl');
return $view;
}
In my Smarty.php
<?php
/**
* Smarty template engine integration into Zend Framework
*/
class Web_View_Smarty extends Zend_View_Abstract
{
/**
* Instance of Smarty
* #var Smarty
*/
protected $_smarty = null;
/**
* Template explicitly set to render in this view
* #var string
*/
protected $_customTemplate = '';
/**
* Smarty config
* #var array
*/
private $_config = null;
/**
* Class definition and constructor
*
* Let's start with the class definition and the constructor part. My class Travello_View_Smarty is extending the Zend_View_Abstract class. In the constructor the parent constructor from Zend_View_Abstract is called first. After that a Smarty object is instantiated, configured and stored in a private attribute.
* Please note that I use a configuration object from the object store to get the configuration data for Smarty.
*
* #param array $smartyConfig
* #param array $config
*/
public function __construct($smartyConfig, $config = array())
{
$this->_config = $smartyConfig;
parent::__construct($config);
$this->_loadSmarty();
}
/**
* Return the template engine object
*
* #return Smarty
*/
public function getEngine()
{
return $this->_smarty;
}
/**
* Implement _run() method
*
* The method _run() is the only method that needs to be implemented in any subclass of Zend_View_Abstract. It is called automatically within the render() method. My implementation just uses the display() method from Smarty to generate and output the template.
*
* #param string $template
*/
protected function _run()
{
$file = func_num_args() > 0 && file_exists(func_get_arg(0)) ? func_get_arg(0) : '';
if ($this->_customTemplate || $file) {
$template = $this->_customTemplate;
if (!$template) {
$template = $file;
}
$this->_smarty->display($template);
} else {
throw new Zend_View_Exception('Cannot render view without any template being assigned or file does not exist');
}
}
/**
* Overwrite assign() method
*
* The next part is an overwrite of the assign() method from Zend_View_Abstract, which works in a similar way. The big difference is that the values are assigned to the Smarty object and not to the $this->_vars variables array of Zend_View_Abstract.
*
* #param string|array $var
* #return Ext_View_Smarty
*/
public function assign($var, $value = null)
{
if (is_string($var)) {
$this->_smarty->assign($var, $value);
} elseif (is_array($var)) {
foreach ($var as $key => $value) {
$this->assign($key, $value);
}
} else {
throw new Zend_View_Exception('assign() expects a string or array, got '.gettype($var));
}
return $this;
}
public function display($template){
$this->clearVars();
$this->_smarty->display($template);
return $this;
}
/**
* Overwrite escape() method
*
* The next part is an overwrite of the escape() method from Zend_View_Abstract. It works both for string and array values and also uses the escape() method from the Zend_View_Abstract. The advantage of this is that I don't have to care about each value of an array to get properly escaped.
*
* #param mixed $var
* #return mixed
*/
public function escape($var)
{
if (is_string($var)) {
return parent::escape($var);
} elseif (is_array($var)) {
foreach ($var as $key => $val) {
$var[$key] = $this->escape($val);
}
}
return $var;
}
/**
* Print the output
*
* The next method output() is a wrapper on the render() method from Zend_View_Abstract. It just sets some headers before printing the output.
*
* #param <type> $name
*/
public function output($name)
{
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header("Cache-Control: post-check=0, pre-check=0", false);
print parent::render($name);
}
/**
* Use Smarty caching
*
* The last two methods were created to simply integrate the Smarty caching mechanism in the View class. With the first one you can check for cached template and with the second one you can set the caching on or of.
*
* #param string $template
* #return bool
*/
public function isCached($template)
{
return $this->_smarty->is_cached($template);
}
/**
* Enable/disable caching
*
* #param bool $caching
* #return Ext_View_Smarty
*/
public function setCaching($caching)
{
$this->_smarty->caching = $caching;
return $this;
}
/**
* Template getter (return file path)
* #return string
*/
public function getTemplate()
{
return $this->_customTemplate;
}
/**
* Template filename setter
* #param string
* #return Ext_View_Smarty
*/
public function setTemplate($tpl)
{
$this->_customTemplate = $tpl;
return $this;
}
/**
* Magic setter for Zend_View compatibility. Performs assign()
*
* #param string $key
* #param mixed $val
*/
public function __set($key, $val)
{
$this->assign($key, $val);
}
/**
* Magic getter for Zend_View compatibility. Retrieves template var
*
* #param string $key
* #return mixed
*/
public function __get($key)
{
return $this->_smarty->getTemplateVars($key);
}
/**
* Magic getter for Zend_View compatibility. Removes template var
*
* #see View/Zend_View_Abstract::__unset()
* #param string $key
*/
public function __unset($key)
{
$this->_smarty->clearAssign($key);
}
/**
* Allows testing with empty() and isset() to work
* Zend_View compatibility. Checks template var for existance
*
* #param string $key
* #return boolean
*/
public function __isset($key)
{
return (null !== $this->_smarty->getTemplateVars($key));
}
/**
* Zend_View compatibility. Retrieves all template vars
*
* #see Zend_View_Abstract::getVars()
* #return array
*/
public function getVars()
{
return $this->_smarty->getTemplateVars();
}
/**
* Updates Smarty's template_dir field with new value
*
* #param string $dir
* #return Ext_View_Smarty
*/
public function setTemplateDir($dir)
{
$this->_smarty->setTemplateDir($dir);
return $this;
}
/**
* Adds another Smarty template_dir to scan for templates
*
* #param string $dir
* #return Ext_View_Smarty
*/
public function addTemplateDir($dir)
{
$this->_smarty->addTemplateDir($dir);
return $this;
}
/**
* Adds another Smarty plugin directory to scan for plugins
*
* #param string $dir
* #return Ext_View_Smarty
*/
public function addPluginDir($dir)
{
$this->_smarty->addPluginsDir($dir);
return $this;
}
/**
* Zend_View compatibility. Removes all template vars
*
* #see View/Zend_View_Abstract::clearVars()
* #return Ext_View_Smarty
*/
public function clearVars()
{
$this->_smarty->clearAllAssign();
$this->assign('this', $this);
return $this;
}
/**
* Zend_View compatibility. Add the templates dir
*
* #see View/Zend_View_Abstract::addBasePath()
* #return Ext_View_Smarty
*/
public function addBasePath($path, $classPrefix = 'Zend_View')
{
parent::addBasePath($path, $classPrefix);
$this->addScriptPath(PATH . '/templates/default');
$this->addTemplateDir(PATH . '/templates/shared');
return $this;
}
/**
* Zend_View compatibility. Set the templates dir instead of scripts
*
* #see View/Zend_View_Abstract::setBasePath()
* #return Ext_View_Smarty
*/
public function setBasePath($path, $classPrefix = 'Zend_View')
{
parent::setBasePath($path, $classPrefix);
$this->setScriptPath(PATH . '/templates/default');
$this->addTemplateDir(PATH . '/templates/shared');
return $this;
}
/**
* Magic clone method, on clone create diferent smarty object
*/
public function __clone() {
$this->_loadSmarty();
}
/**
* Initializes the smarty and populates config params
*
* #throws Zend_View_Exception
* #return void
*/
private function _loadSmarty()
{
if (!class_exists('Smarty', true)) {
require_once 'Smarty/Smarty.class.php';
}
$this->_smarty = new Smarty();
if ($this->_config === null) {
throw new Zend_View_Exception("Could not locate Smarty config - node 'smarty' not found");
}
$this->_smarty->caching = $this->_config['caching'];
$this->_smarty->cache_lifetime = $this->_config['cache_lifetime'];
$this->_smarty->template_dir = $this->_config['template_dir'];
$this->_smarty->compile_dir = $this->_config['compile_dir'];
$this->_smarty->config_dir = $this->_config['config_dir'];
$this->_smarty->plugins_dir = $this->_config['plugins_dir'];
$this->_smarty->cache_dir = $this->_config['cache_dir'];
$this->_smarty->left_delimiter = $this->_config['left_delimiter'];
$this->_smarty->right_delimiter = $this->_config['right_delimiter'];
$this->assign('this', $this);
}
}
There is Smarty implementation in Zend Documentation.
Smarty is bad, any template engine is bad and slowing down your application.
Use zend native views.
And remember that PHP is was invented to be a template engine.
http://framework.zend.com/manual/1.11/en/zend.view.scripts.html
When in your template, you write
{$this->layout()->content}
This is the content of the layout helper, that will render the view associated to each action.
When, in you controller, you write
$this->view->content = $this->view->display('contact/contact.tpl');
You assign a variable to your view, that can be display, using
{$content}
in your smarty template.
I think you have some confusion in your way of sorting this out. Have a look at
http://framework.zend.com/manual/1.12/en/zend.layout.quickstart.html
Anyway, your question is old and you already have selected an answer as correct, which was not really an answer by the way, but I couldn't pass by and say nothing. Using Smarty with Zend is great, Smarty is faster and compiling/caching have better fine tuning than Zend and the integration between both is neat (thanks to dependency injection). You can have the power of both libraries in one application, so go for it.

Categories