I am using log4php and within my objects, I would like to log the object variables upon entry and exit of a method (for debug purposes). I came across log4php's renderer functionality and thought it would be a great idea but I am unable to get it to work.
public function someMethod() {
$this->logger->debug($this); //entry log
... do something ...
$this->logger->debug($this); //exit log
}
The application throws an error stating that log4php cannot convert the object to a string. Should I be doing something else in order for the renderer to work?
A point to note - the object does have several private and protected variable - no public variables. Perhaps this is an issue - but then I didnt note that statement anywhere in the docs.
Thanks in advance
Unless you extending or inheriting from it, private shouldn't be a problem.
And unless you're directly accessing a protected function inside the class it resides, that can't be either.
In any case, I'm guessing that you're trying to print something out. That error happens when you're trying to echo out an object(PDO thought me that one).
not being able to comment kinda of sucks
Related
In my PHP project im using a Class factory that stores the object instances inside an object member of a static class. This member is an array and if for example i gonne instance lib/log.php (class log {....) it will be accessed like
glob::$data["lib/log"]
Since im using this structure all over my project i want doxygen to recognize the calls for the call/caller graphs and for linking the functions. In my code i currently do like
glob::$data["lib/log"]->info("info to log.......");
Wich i realized wont be recognized by doxygen so i tried modify the code to structure like:
$libLog = glob::$data["lib/log"];
$libLog->info("info to log......");
And adding source comments to tell the code wich instances of classes im using here. I tried in both ways like
/* #var $libLog log */
same as
/* #var log $libLog */
since i found examples refering to both of that. None of them worked. The log class itself gets recognized and is inside the Class list so it can't be an recognation error.
If anyone has idea how i can make doxygen recognize those calls or a hint to another stack posting that solves this problem i would be really gratefull!
To make it simple, I have noticed that PHP doesn't seem to offer any magic constant for determining what the name that a trait has been changed to in a class. Since this sounds confusing to me in words, I will give an example, as it is rather easy and would expect it to be somewhere in the new PHP 5.5, I don't see a way to doing it. So here it is:
Say we have some class, that uses some trait that conflicts with some function inside the class, example:
class SomeClass {
use \Name\Space\SomeTrait { SomeFunction as private NewFunctionName; }
function SomeFunction() {
$this->NewFunctionName();
}
}
Since, obviously this class has the "SomeFunction" function, and we are aware that inside of SomeTrait we have included, is a function that is matching by name to a function we have inside this class. Now, since the "SomeFunction" came into this class via a trait inside of a \Name\Space, these 2 functions do 2 different things, but happen to use the same name, and inside of either another function or literally our 'SomeFunction', we then use the "SomeFunction" from our trait, by calling it by the "NewFunctionName".
So hopefully I haven't lost anyone here, as here is what my question comes down to in the above scenario. Within the \Name\Space\SomeTrait\SomeFunction(), how could one get the "NewFunctionName" that this trait function was assigned too? One would think to use a magic method, such as __FUNCTION__, or __METHOD__, or even __TRAIT__, except none of these give the expected result, so does anyone know a way to get this information without passing it to the function as a parameter and resulting in a hacky code? Maybe PHP 5.6 needs to add a new Magic Constant __AS__, or adjust the result of __TRAIT__, I dont understand why __TRAIT__ and __FUNCTION_ need to return the same information (or nearly the same information). Any help would be awesome, if it is an unconventional hacky method, Im interested in seeing my options, until I can open up a bug report with php regarding this. (if it is truly a bug)
edit:
My current, least hacky, method seems to be,
debug_backtrace()[0]['function']
and though it works, I feel it is doing a lot to get a simple string, especially if you use the function a lot. :/
This is the solution I ended up using. It's not very good but probably better than using the debug_backtrace function.
Problem example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->doSomethingRecursive();
}
}
Solution example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->__internal_doSomethingRecursive();
}
private function __internal_doSomethingRecursive() {
// this works because the class would have
// used and renamed the above function
// but this "internal" function *should*
// remain available under it's original name
$this->__internal_doSomethingRecursive();
}
}
Of course it's possible to break this but for most cases it should be fine. You could also include the name of the trait in the internal function name to further prevent conflicts.
Your current solution is going to be the best, with a couple tweaks:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,1)[0]['function']
The DEBUG_BACKTRACE_IGNORE_ARGS and the frame limit of 1 there will make the backtrace shallow, faster, and use less memory.
This is a design question that has irked me because deep down I know I'm doing it wrong. This is not necessarily just a PHP problem, but I'm working on a PHP project now so that's where I'm coming from.
I'll just give you the scenario:
I have a JSON generation class that is used by a data access script. Basically it's the go-to URL for a website that instantiates the JSONGen class, which in turn looks at a static file and pulls the data that was requested, and sends it back as a JSON object. The file that contains the raw data has it all in array format to allow for easier reading and updating (so one doesn't have to sift through raw JSON data and risk syntax error, etc).
My question is in the accessing of that file.
What I did was to place a require([json file]) outside the class definition. Everything in the [json file] is assigned to one $JSON object.
In the class constructor, I do:
global $JSON;
$this->JSON = $JSON;
(Where $this->JSON is a private class variable).
This gives me access to the JSON from anywhere in the class, which is lovely.
It feels hacky, but I can't find anything anywhere that addresses this specific type of approach.
The problem is that once somebody decides to move the class or whatever, the only way they have of understanding the dependency of this file is in that there's a require statement in the header. Is that just how things work? Or is there a better way to do this?
Should I use extend and put the JSON into a class (THAT sounds really stupid to me), or continue forward with my include? Or should I never, ever include a file in a class like this and rather pass it to the constructor or some other access method?
This specific instance is a small project, and it just doesn't make sense to set up a DB for it. We can add to the file, modify the config, and the whole site updates.... so please don't tell me to switch to a DB- I'm looking for strategies for this specific problem in a more general sense.
Thanks!
Probably going to get downvoted for this one but here it goes...
class JSON_Response {
public static $JSON;
// don't let people make one of these it gives the illusion that there can be more then one
protected function __construct(){}
}
then in your file
JSON_Response::$JSON = $json;
and access if from anywhere as JSON_Response::$JSON;
and if there is anything that you commonly do to the json object (check a flag or something) you can just add a static method to the JSON_Response class.
This question already has answers here:
What is the difference between public, private, and protected?
(16 answers)
Closed 9 years ago.
I have been thinking about the usage of private variables and methods in php.
I am not going to talk about a class of car or anything like that. I want to talk about an own script.
What is the difference between using public or private for the programmer and the owner of the script.
if the script is a calculator, and I am the only one who will meinten the code in the future. when do I have to use private variables of methods. How this is going to change anything in the script?
Also, If it's about touching the variable ? if anyone tries to change the value, and he couldn't because of the private thing. He will go directly to change it using the setters ?
I need a good example that I can see private methods or variables have good benefits for programmer or the end user.
I was programming some scripts, and a guy told me to not use var in classes. I asked him why ? he said that you have to use public or private .. and asked why ?
Why to use setter if there is a way to change the variable directly?
Why to use getter if there is a way to change the variable directly?
First of all, when you're developing strong-OO classes, you should be exposing as little of the internal semantics of your class as possible (obviously without affecting functionality).
Some variables are only valuable inside the context of the class itself, and would make no sense to a developer using the class. Making the variable public allows anyone using the class to change such a variable at will, despite the fact that they may not know what it's used for. In PHP this can be a particular problem when you don't even have type safety to at least mitigate the damage that can be done.
Consider this: You have a class which wraps around some I/O operations. Let's call it FileReader
class FileReader {
public $_handle;
public function __construct($filepath) {
$this->_handle = fopen($filepath, 'r');
if ($this->_handle === NULL) {
throw new Exception("Unable to open the file for reading");
}
}
// ... the rest of the class
}
Now you can see that the class opens up a handle to a file. By making the $_handle variable public, you've exposed it to any and all people working on your class. They don't need to know about the raw file handle you have open, they just want to use your nice class to perform some read operation. However, it IS public; not only can they see it, but they can change it. This is bad, especially when your other code assumes that the $_handle variable is valid.
$reader = new FileReader();
$reader->_handle = "I hope this doesn't break anything. /trololol";
$reader->someOperation(); // oh no! Our file handle has just been changed to something completely wrong, this is now going to the break the class.
Such ridiculous scenarios can be avoided entirely by making the variable private in the first place. For more (and better) example of what each access modifier does, and when to apply them see this answer.
Now, onto getters and setters. In your question, you seem to assume that all getters and setters are written the following way:
class Foo {
private $_bar;
public function getBar() {
return $this->_bar;
}
public function setBar($newBar) {
$this->_bar = $newBar
}
}
In which case, you're absolutely right there is no difference between that and changing the $_bar variable to be public in the first place.
However, getter and setter methods give you control over how your variables are being set by an external developer, so you can instantly detect when they're going to make a boo-boo and avoid undefined behaviour later on. For example:
class Foo {
private $_bar;
public function getBar() {
return $this->_bar;
}
public function setBar($newBar) {
// Now we're going to ensure that $newBar is always an integer
if (!is_int($newBar)) {
// not an integer, throw out an exception to let the developer know that somewhere is setting invalid input
throw new Exception("Expected an integer value for 'Bar'");
}
$this->_bar = $newBar;
}
}
This is not only making your class far more robust, but also making the life of the developer using your class a hell of a lot easier. Rather than having to debug an extremely weird issue somewhere later on when the class attempts to use the corrupt value of $_bar, they can easily tell from a stack trace where the corrupt value was set from and fix it at the source.
There is plenty of documentation about variable access and getter/setter methods out there, and it applies to a whole range of languages so don't be afraid to look up articles that were based on C++/C#/VB.NET, they all roughly translate to the same material.
The end user doesn't see the code, so there's no (dis)advantage there.
For the programmer, declaring things that aren't needed outside the object as private is just a good programming practice and a protection mechanism. Technically, if you're a perfect programmer, and you don't care about how your code looks, using private will provide you no benefits. However, private members enforce the black box model -- you only care about what the object does, not about how it works (when looking at it from the outside). In the end, if for any reason you (or somebody else) needs/wants to use your code, they'll know what methods and properties to use/invoke in order to get the functionality the object has, without modifying the internal values the object needs to maintain. It may or may not give you any advantage -- it's just about how the code looks like. That's what good programming practices are for, and they are usually followed because experience says they tend to minimize errors.
As for var, it was deprecated. Meaning it could (and will) be removed in the future.
Public, Private and Protected only matter in PHP if they are part of a function, or part of a class.
If you wanted to set a variable once and "lock it" so the value couldn't be changed later you can define it or set it as a const (constant).
public scope to make that variable/function available from anywhere,
other classes and instances of the object.
private scope when you want your variable/function to be visible in
its own class only.
protected scope when you want to make your variable/function visible
in all classes that extend current class including the parent class.
See here: http://php.net/manual/en/language.oop5.visibility.php
I am writing a SOAP server and have hit a strange problem.
Here's the relevant lines from the server.php
class MyHandler {
public function __construct() { ... }
public function __wakeup() { ... }
public function getPrice() { ... }
}
$server = new SoapServer("my.wsdl", array("soap_version" => SOAP_1_2));
$server->setClass('MyHandler');
$server->addFunction("getPrice");
$server->handle();
Testing this locally (on PHP 5.3) works fine and I'm able to send requests and receive responses.
When I put this onto my development server (PHP 5.2.9), I get this error message:
SoapServer::addFunction(): Tried to add a non existant function 'getPrice'
Apart from the fact that they can't spell, this is very confusing.
I've since managed to work around the issue by changing the addFunction() line to this:
$server->addFunction(SOAP_FUNCTIONS_ALL);
... and it works fine! Of course, examining $server->getFunctions() shows that this adds the __construct() and __wakeup() functions from my class too, which doesn't seem like such a good thing.
What did I do wrong? Is the carpet bomb "add all functions" approach the only way here?
Using addFunction() tells it to look for a function named getPrice() on its own, outside of a class. This doesn't exist, so is causing the error.
Using addClass() will automatically add all the functions from MyHandler, so you shouldn't need to call addFunction(), getPrice() should have already been added.
Additionally, there's an open ticket (for PHP 5.2.9) on bugs.php.net which seems to indicate that there's no way of adding a class method using addFunction(): http://bugs.php.net/bug.php?id=47919
I don't have access to PHP 5.3 though, so not sure how things may have changed I'm afraid...
$server->addFunction(array("SOAPMethods", "getPrice"));
Hmm, not sure why it's working on PHP 5.3, but from what I understand, SoapServer::setClass() exports all the methods in the given class (ie, your getPrice() method will be exported using that).
SoapServer::addFunction() works specifically with, well functions. Any chance you had a stray getPrice() function lying around in your local environment?
You can test this with commenting out the addFunction() call which should still show your exported methods from "MyHandler".
Using SOAP_FUNCTIONS_ALL is probably a bad idea, as if you remove the setClass() call it actually exports all PHP functions for some reason...
I am using PHP version 5.3.10 and I had the same problem. And I solved it by adding array keyword.
Before:
$server->addFunction("functionName");
After:
$server->addFunction(array("functionName"));
Reference: PHP SoapServer::addFunction documentation.