PHP: Echo variable name of an object? - class

I want to echo the name of the variable object i'm calling, in this case controller_01.
I'm using get_class, but it wont print the variable name, only the object type :(
<?php
class remoteControl{
private $chip = "Intel64<br />";
public function openCase(){
echo "The controler has a " .get_class($this);
return $this->chip;
}
}
$control_01 = new remoteControl();
echo $control_01-> openCase();
?>

You can't do that just like that. An object can have multiple references, but the object isn't itself aware of those references.
The only thing you could do, is to enumerate through every variable you can find and check if it points to the object. But those references could exists also in arrays, or in properties of other objects.
And your design is really flawed if you need the object to find its reference variables this way.

Related

How to debug in TYPO3 if <f:debug> returns strings instead of object?

In a custom TYPO3 8.7.12 extbase extension I am unable to f:debug items in templates.
We are in the listAction controller and simply do:
$institutions = $this->institutionRepository->findAll();
$this->view->assignMultiple([
'institutions' => $institutions,
// ... pagination limit ...
]
);
And in the template:
<f:debug>
{institutions}
</f:debug>
This returns
sometimes the string 'Array' in the fluid debugger (can't reproduce now)
When the code is on 3 lines: #1273753083: Cannot cast object of type "TYPO3\CMS\Extbase\Persistence\Generic\QueryResult" to string.
Or also #1273753083: Cannot cast object of type "TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage" to string.
When the code is on 1 line: #1234386924: Cannot create empty instance of the class "TYPO3\CMS\Extbase\Persistence\ObjectStorage" because it does not implement the TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface.
If I loop through {institutions} with f:for and then f:debug:
<f:for each="{institutions}" as="institution" iteration="i">
<f:debug>
{institution}
</f:debug>
</f:for>
I get the first property of the object, e.g. the name.
EDIT: this is due to a __toString() magic method in the model. If I remove it, instead I get the namespace and uid STUBR\Extension\Domain\Model\Institution:55 – this looks again as if the object isn't rendered.
Wait... php.net says The __toString() method allows a class to decide how it will react when it is treated like a string. So could something be treating (typecasting?) the object as a string?
Working with the properties is normal, the issue just occurs when trying to print the whole object.
Where should I look? Lazy loading? There are some lazy loading properties, but not that many. Or maybe something is missing from the class? Or is there a workaround.
PS:
Unable to print_r or var_dump the query result, I get a memory limit error.
I saw https://wiki.typo3.org/Exception/CMS/1234386924 but initStorageObjects() is already called in the constructor
To answer the question;
<f:debug>{institutions}</f:debug>
will be parsed as an object, but any whitespace inside will make it parse as a string so.
The following methods do the same job as <f:debug> and work similarly in my case:
\TYPO3\CMS\Core\Utility\DebugUtility::debug(
$var = $variable,
$header = 'Institutions',
$group = ''
);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
$variable,
$title = 'Institutions',
$maxDepth = 8,
$plainText = FALSE,
$ansiColors = TRUE,
$return = FALSE,
$blacklistedClassNames = NULL,
$blacklistedPropertyNames = NULL
);
execute in list or show action in controller.
It's less convenient than with f:debug (because you have to do the work in two different places, e.g. when you're in a loop in the template, you have to go to the controller and build that loop again), but it's a helpful workaround.
EDIT: I found it's sufficient to do
<f:debug>{var}</f:debug>
on one line

How to find the Perl code referenced by this line?

I have inherited some Perl code which contains a line that is mysterious to me:
my $binary = A->current->config->settings('arg1', 'arg2')
Basically, I am not sure how to find the related code. "A" is NOT a variable in the local code so I thought this was a class hierarchy. However I checked the directory structure to see if the following path existed, but there was none:
A/current/config/settings.pm
Is A->current->config->settings guaranteed to be a nested class hierarchy, or could it be something else? For example could config actually be a property or method of a different object A->current?
Any assistance you could lend tracking this down would be greatly appreciated!
A is a class name, you should find it in A.pm. current should be a method of the class, defined under a sub current in A.pm. It returns an object whose config method is being called which returns an object again whose settings method is being called with arguments 'arg1' and 'arg2' (well, in fact, the object itself is the first argument).
In fact, any of the methods can return a class instead of an object, too.
Step through the code in the perl debugger and see where it takes you.
foo->bar is a method call, meaning that there is likely a subroutine called bar defined in the package referred to by foo (or a superclass), and gives you no information about whether there is a package bar or foo::bar.
Is A->current->config->settings guaranteed to be a nested class hierarchy
You're thinking of A::current::config::settings.
The following are method calls:
INVOCANT->name
INVOCANT->name(LIST)
That means that A->current->config->settings is a chain of method calls.
The only class named in that code is A.
could config actually be a property or method of a different object A->current?
It's the name of a method of the object or class returned by A->current.
How to find the Perl code referenced by this line?
my $binary = A->current->config->settings('arg1', 'arg2');
is short for
my $obj1 = A->current;
my $obj2 = $obj1->config;
my $binary = $obj2->settings('arg1', 'arg2');
Now that you have the objects available, you can find the class of which they are an instance using
say ref($obj) || "Not a reference";
or
use Scalar::Util qw( blessed );
say blessed($obj) // "Not an object";
As explained, you are dealing with a chain of method calls in the class named A, where at least the first one is a class method since it is invoked on the class (A) itself, not on an object.
An easy way to find that class is by using Class::Inspector
use Class::Inspector;
say "Filename: ", Class::Inspector->resolved_filename( 'A' );
which printed the full path to the class I used in my tests. Also see loaded_filename.
Another interesting way to interrogate a class is to add to it at runtime.
Create an object of A and add to it a method of your choice at runtime
my $objA = A->new();
eval q( sub A::get_info { print "$_\n" for (caller(0)) } );
if ($#) { print "Eval: $#" };
eval q( sub A::boom { croak "Stacktrace: " } );
if ($#) { print "Eval: $#" };
$objA->get_info();
$objA->boom();
These are simple examples but you can acquire practically any information from inside a method.
If A happens to not have a method called new (possible) work with methods in the given chain, starting with my $objA = A->current.
Or, you can directly add a subroutine to the package's symbol table
*{A::new_method} = sub { say "A new method" };
$any_obj_of_A->new_method();
which is now also available on all existing instances, as well as on new ones.

Are there "magic functions" for powershell objects?

In PHP, there are "magic methods" that exist if you need them to. An example of this is the __toString() method which is used to echo out a specific string if a piece of code attempts to echo the object. This is an example using PHP:
<?php
// Declare a simple class
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class;
?>
Which would return:
Hello
Is there a "magic function" that will do this in Powershell?
All default PSObjects in PowerShell have a ToString() method, and if you're creating your custom objects in script (and not code), then you are going to have this method already present. All you need to to is override the ToString() method using Add-Member.
Please see this question for an exact description of this.
You can see what members your custom object has by piping an instance of the object to Get-Member.

Zend_Paginator with result of Zend_Db_Table_Abstract

i have many class in model directory that those are extend of Zend_Db_Table_Abstract.
but i need use of zend_paginator and this need to result of Zend_Db_Select !!
so when i use of this code (productCat is a model class)
$productCat = new ProductCat();
$rows = $productCat->FetchOrderByPriority();
// Get a Paginator object using Zend_Paginator's built-in factory.
$paginator = Zend_Paginator::factory($rows);
$this->view->paginator = $paginator;
it don`t work!
it show me this error :
Catchable fatal error: Object of class Zend_Db_Table_Row could not be converted to string in
this is my view code :
<ul><?php foreach ($this->paginator as $item): ?>
<li><?php echo $item; ?></li><?php endforeach; ?></ul>
is there any idea?
Pagination definitely works. The problem is in your view where you're trying to echo $item.
And it obviously doesn't work since Zend_Paginator::factory($rows) has returned a rowset; so when you're iterating over $paginator object, you're getting objects of Zend_Db_Table_Row type, and you simply cannot echo them.
What you're trying to do, I believe, is to echo a particular property of the item object, something like:
echo $item->name;

How to use Zend Framework's Partial Loop with Objects

I am quite confused how to use partialLoop
Currently I use
foreach ($childrenTodos as $childTodo) {
echo $this->partial('todos/_row.phtml', array('todo' => $childTodo));
}
$childrenTodos is a Doctrine\ORM\PersistantCollection, $childTodo is a Application\Models\Todo
I tried doing
echo $this->partialLoop('todos/_row.phtml', $childrenTodos)
->setObjectKey('Application\Models\Todo');
But in the partial when I try to access properties/functions of my Todo class, I cant seem to get them always ending up with either call to undefined method Zend_View::myFunction() when I use $this->myFunction() in the partial or if I try $this->todo->getName() I get "Call to a member function getName() on a non-object". How do I use partialLoops?
Try this
echo $this->partialLoop('todos/_row.phtml', $childrenTodos)
->setObjectKey('object');
Then in your partial you can access the object like this
$this->object
object is the name of the variable that an object will be assigned to
You can also do this once in your Bootstrap or other initialization class if you have access to the view object like so
protected function initPartialLoopObject()
{
$this->_view->partialLoop()->setObjectKey('object');
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->setView($this->_view);
}
I also had "Call to function on non object" error when trying suggested syntax, seems like they've changed something on later versions of Zend Framework. The following works for me on ZF1.12:
echo $this->partialLoop()
->setObjectKey('object')
->partialLoop('todos/_row.phtml', $childrenTodos);