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.
Related
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
My team members wrote the model function calls in the controller statically such as:
$data = ModelName::functionName($param);
while it should be called dynamically such as:
$model = new Model();
$data = $model->functionName($param);
mostly all the calls are made statically. the code is working on the server and on their local machines except for mine. And the static calls are too many to fix without rewriting huge code base.
I always update my project via composer. My php version is 5.4.
anyone might know what this is about?
You probably have PHP running with E_STRICT error reporting. Try turning it off and see if that fixed the problem - like turn of error reporting for E_STRICT errors. See this post on SO :
<?php
error_reporting(E_ALL ^ E_STRICT);
But I have to say, it's a bad idea to mix object-style and static-style calls. Function calls should explicitly show that a function is called in a static or object context, and act accordingly. Even if it's a little hard (how hard is making a grep on all the files and change wrong calls?), i'd recommend fixing your code first.
And also I recommend reading about static keyword in Object Oriented Programming - there's a reason to distinguish static and object method calls, and it's not a reason of "to make things easier", but more of a "to make things clearer", I'd say.
Sorry but I do not write English very well, but what I understand your question is that:
you need to put your static function:
static public function functionName () {
$data = ModelName :: functionName ($ param);
}
That happens through the different versions of PHP that the servers handle.
I hope that I have understood your question and translate it well, because a similar error appeared to me and I solved it that way.
Introduction
I am getting strange error in zf2. I don't know why, but I am getting some routing error. I don't get any messages, but needed controller is not loaded, but another one do. All looking fine, so it is not good idea to ask here to help me to solve this problem, so I am trying to debug this by myself.
What I have tried?
I tried debug_backtrace() function in /public/index.php file like this:
// Setup autoloading
require 'init_autoloader.php';
// Run the application!
Zend\Mvc\Application::init(require 'config/application.config.php')->run();
var_dump(debug_backtrace());
It shows nothing.
Just to check if function is working I tried:
function bob() {
var_dump(debug_backtrace());
}
bob();
And this showed me what params were passed, what functions called etc. This showed me, that function is executed correctly, but this function is not used in my case.
Question
Is there any ways to get what functions was executed in app?
I think you slightly misunderstand what debug_backtrace() does. It lists the function calls that led to the place in code where the backtrace is. So in your bob() example, it will show that function (as bob() was called). But if you just call debug_backtrace() in public/index.php, that's not executed within any functions, which is why you don't get any output.
I am not sure how reasonable it will be for you to install a different stack, but ZendServer has code tracing/profiling built in and that is exactly what you are looking for.
I have come across this line in the eloquent ORM library:
return with(new static)->newQuery();
I've never seen "with" used before, and cannot find it in the PHP documentation. I'm guessing "with" is a stop-word in most searches, so I am not even getting close.
Never having encountered "with" in many years of programming PHP, I feel like I'm missing out. What does it do? I did come across one passing comment regarding the ORM, that mentioned "with" is no longer needed in PHP-5.4, but that was as much as was said. If that is accurate, it would be good to know what the PHP-5.4 equivalent is.
Update: Details supporting the answer:-
I found this helper function in Laravel's Immuminate/Support/helpers.php helper script:
if ( ! function_exists('with'))
{
/**
* Return the given object. Useful for chaining.
*
* #param mixed $object
* #return mixed
*/
function with($object)
{
return $object;
}
}
as mentioned in a few of the answers. That global-scope function allows an object to be created and methods run in t, in one statement. It is (somehow) registered in the composer autoload_files.php script when Laravel is installed, so it gets loaded on every page, even though it contains no classes.
Thanks all. It pays not to assume that everything must be a namespaced class in modern frameworks.
It's a function that will look something like this:
function with($obj) {
return $obj;
}
It's shorter version and more readable version for new ExampleObj()->newQuery().
with function is not build in PHP. It's workaround for older versions than PHP 5.4. As #Rocket Hazmat pointed in PHP 5.4+ you can do just new ExampleObj()->newQuery() so with function here allow you to keep readable backward compatibility.
The with function is a helper provided by Laravel as documented here. The best documentation is the code and as you can see, it simply returns the object. In 5.4 / 5.4 you are better off just surrounding the expression in parens to avoid the overhead of an unnecessary function call.
I think #Izkata hit the nail on the head in the comments.
[I'm guessing] this is a workaround for something along the lines of new Foo()->newQuery() not working in some version of PHP
In PHP 5.4 the following was added:
Class member access on instantiation has been added, e.g. (new Foo)->bar().
(Source: http://www.php.net/manual/en/migration54.new-features.php)
So, I'd assume with looks something like this:
function with($x){
return $x;
}
In PHP 5.4+, you can do (new static)->newQuery(), but with an older version, you can't. with is probably there so you can do with(new static)->newQuery(), which will work in any PHP version.
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.