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.
Related
I use Loggable to backup changes in Entities.
The default AbstractLogEntry does not have enough columns for my needs.
Thats why i extended the class and added extra getters and setters.
See the code below
/**
* EmployeeBackup
*
* #ORM\Table(name="employee_backup")
* #ORM\Entity(repositoryClass="Gedmo\Loggable\Entity\Repository\LogEntryRepository")
*
*/
class EmployeeBackup extends AbstractLogEntry
{
/**
* #var int
*
* #ORM\Column(name="division_id", type="integer", unique=true)
*/
private $divisionId;
/**
* #return int
*/
public function getDivisionId(): int
{
return $this->divisionId;
}
/**
* #param string $divisionId
*/
public function setDivisionId(string $divisionId): void
{
$this->divisionId = $divisionId;
}
}
The extension is using the class above. So it works.
But now i need to set the divisionId when a new version is stored.
I tried the code below
$loggable = new LoggableListener();
$loggable->setDivision($division);
$evm->addEventSubscriber($loggable);
And this is what i get:
Attempted to call an undefined method named "setDivision" of class "Gedmo\Loggable\LoggableListener".
And thats true because LoggableListener does not have a setDivision function. My question is: Do i need to override the listener and if so, how do i do that?
Thanks ;)
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}.
There has been a solution for template variants, which allowed to set a suffix for a fluid template file used by an extbase controller. It was created by Peter Niederlag and was improved by Bastian Waidelich.
The solution is not working any longer in TYPO3 8.7 because the code has been refactored and the method expandGenericPathPattern in TemplateView does not exist anymore.
How should I implement such variant view in TYPO3 8.7?
$this->view->getRenderingContext()->setControllerAction('MyAction.Variant'); should do the trick (from any initializeAction method or within action method). Note that contrary to the view override class you linked to, this approach means you must have the original action template in the path.
I created the following classes in my extension, which implement the VariantView for TYPO3 8.7.
Classes\View\VariantView.php
<?php
namespace Vendor\Extkey\View;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Fluid\View\TemplateView;
/**
* Extended Fluid Template View that supports different "variants"
*
* #license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
*/
class VariantView extends TemplateView
{
/**
* #param string $layoutVariant
* #return void
*/
public function setLayoutVariant($layoutVariant)
{
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->baseRenderingContext->setTemplatePaths($objectManager->get(TemplatePaths::class));
/** #var TemplatePaths $templatePaths */
$templatePaths = $this->baseRenderingContext->getTemplatePaths();
$templatePaths->setLayoutVariant($layoutVariant);
}
const DEFAULT_LAYOUT_VARIANT = '.default';
}
Classes\View\TemplatePaths.php
<?php
namespace Vendor\Extkey\View;
class TemplatePaths extends \TYPO3\CMS\Fluid\View\TemplatePaths
{
/**
* Layout variant to use for this view.
*
* #var string
*/
protected $layoutVariant = VariantView::DEFAULT_LAYOUT_VARIANT;
/**
* #param string $layoutVariant
* #return void
*/
public function setLayoutVariant($layoutVariant)
{
$this->layoutVariant = $layoutVariant;
}
/**
* Wrapper for parent class method which adds layout variant in action parameter
*
* #param string $controller
* #param string $action
* #param string $format
* #return string|NULL
* #api
*/
public function resolveTemplateFileForControllerAndActionAndFormat($controller, $action, $format = self::DEFAULT_FORMAT)
{
$action = $action . $this->layoutVariant;
return parent::resolveTemplateFileForControllerAndActionAndFormat($controller, $action, $format = self::DEFAULT_FORMAT);
}
}
In your controller add the following lines:
protected function setViewConfiguration(\TYPO3\CMS\Extbase\Mvc\View\ViewInterface $view) {
parent::setViewConfiguration($view);
$view->setLayoutVariant($this->settings['layoutVariant']);
}
As of late I have exploring and expanding my PHP skills into new territory and working on getting a better understanding of various design patterns. From a technical standpoint I understand traits and how they are useful but don't have the practical side down just yet. There is a piece of code that I was working on recently, and I am not sure if this is the best way of accomplishing what I want.
<?php namespace Acme\Traits;
trait TCities{
/**
* #var self
*/
private static $instance;
/**
* #var int
*/
private $cityID;
/**
* #var float
*/
private $latitude;
/**
* #var float
*/
private $longitude;
/**
* #var
*/
private $cityName;
// more fields ----->>>
/**
* #return TCities
*/
public static function getInstance() {
if (!(self::$instance instanceof self)) {
self::$instance = new self;
}
return self::$instance;
}
/**
* #return int
*/
public function getCityID(): int{
return $this->cityID;
}
/**
* #param int $cityID
*/
public function setCityID(int $cityID){
$this->cityID = $cityID;
}
// more methods ....
Since I have city data that can come from 3 different databases and used all over the system, this makes it easy access that data without having to know all of the fields from the various DBs.
Here is an example of how the trait gets used.
<?php namespace Acme\QueryLibs\MySql;
use Acme\Traits\TCities;
class SqlLocationQueries extends SqlQuery{
use TCities;
/**
* SqlLocationQueries constructor.
*
* #param IDatabaseMySql $db
*/
public function __construct(IDatabaseMySql $db){
parent::__construct($db);
}
/**
* #param int $cityID
*
* #return TCities
*/
public function getCityData(int $cityID): TCities{
$query = ' SELECT *
FROM cities
WHERE id=?
LIMIT 1 ';
$params = [$cityID];
self::setQuery($query);
self::setParams($params);
$result = self::readOne();
if(empty($result)){
LocationErrors::unknownCityByID($cityID);
}
$cityInst = TCities::getInstance();
$cityInst->setCityID($result['cityID']);
$cityInst->setCityName($result['name']);
$cityInst->setLatitude($result['lat']);
$cityInst->setLongitude($result['lon']);
return $cityObj;
}
As you can see, this method returns 'TCities'. It's very convenient but not sure if this is the right/good approach?
Then in a higher level method (This is a very simplistic use case but gets the point across)
$locationOrigin = new SqlLocationQueries($this->db);
$cityOriginData = $locationOrigin->getCityData($cityID);
echo 'Welcome to '.$cityOriginData->getCityName().'<br />';
echo 'Where the coordinates are '.$cityOriginData->getLatitude().' '.$cityOriginData->getLatitude().'<br />';
Is this a misuse of traits or a good use case from them? If it is a bad use case, what would be the more efficient and correct way to accomplish this goal?
I've got the following class in a Zend Framework project:
<?php
/**
* User's class
*
* This class should be responsible for all
*
* #author Steve Davies
* #copyright 2012
* #version SVN: $Id$
*/
class Api_Admin_Users extends Api_Core
{
/**
* Class Constructor
*
* #return void
*/
public function __construct() {
parent::__construct();
}
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
$user = self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
echo $user->getFullName();
}
}
However when I try and use code hinting on $user->getFullName();, it doesn't work.
Using the following trick from here, it works:
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
/* #var $user \UserManagement\Users */
$user = self::_instance()->_em->getRepository('UserManagement\Users')->find('1');
echo $user->getFullName();
}
But, I don't want to have to include that comment line everytime I instantiate the object. When I try to move this to the Class definition - or even the method definition, it fails to work.
Can anyone provide an answer for this?
PHP is a dynamic language and as such it is not trivial to infer variable types from static code analysis (like it is in Java for example).
It's especially difficult with factory methods like yours getRepository('UserManagement\Users').
NetBeans currently has no way of knowing how to translate the function argument to the type of returned variable (unless you're satisfied with some parent class from which all subclasses returned by that factory derive). Unfortunatelly vdoc's are the only way to deal with such cases.
Create a method in Api_Admin_Users to access the repository and add the type hint there. This will benefit all methods in the class. As long as the methods in the repository are type-hinted correctly, you're all set.
class Api_Admin_Users extends Api_Core
{
/**
* Class Constructor
*
* #return void
*/
public function __construct() {
parent::__construct();
}
/**
* Get the repository
*
* #return \UserManagement\Users
*/
public static function getRepository() {
return self::_instance()->_em->getRepository('UserManagement\Users');
}
/**
* Get User's name
*
* This returns the user's name
*
* #return void
*/
public function new() {
$user = self::getRepository()->find('1');
echo $user->getFullName();
}
}