Preprocessing like "#if defined" in PHP - php

I have following question:
I am programming a SOAP Server application with PHP. But I have to do that in two different ways, one which is for external usage (for all people) and one that is just for an import. And the import application has just a little bit more possibilities, but else it is the same.
In C I would write something like this (using the preprocessor):
#ifdef INTERNAL
int funktion( int ok, double asdfg, const char *aaa){
#else
int funktion( int ok, double asdfg){
#endif
return 0;
}
I know the function defined() in PHP, but it does not really do what I want to do (I think).
But is there something simolar?
Of course I could write two different applications, but it would be very great if there was something like this ...
Thank you for help!
EDIT:
I know that normally it is possible to write conditional functions like
if(CST){
function asdf($asdf){
}
}
else{
function asdf(){}
}
but I need it in a Class and there it does not work ...
Kind regards!

In PHP there are no such pre-processing constructs as PHP is not compiled. But in PHP classes can be defined conditionally. So you could do this in two steps:
define the class with the full option (3rd argument), but define those sensitive members as protected instead of public
extend the class conditionally, providing access to the protected members via a new name, and with the appropriate signature. Other public members do not have to be mentioned explicitly as they are inherited as usual
Here is an example:
define('INTERNAL', false);
// Define complete class, but with members set to protected
// when they have constraints depending on INT/EXT access
class _myClass {
protected function _funktion ($ok, $str, $id = -1) {
echo "arguments: $ok,$str,$id";
}
public function otherFunc() {
echo "other func";
}
}
// Define myClass conditionally
if (INTERNAL) {
class myClass extends _myClass{
// give public access to protected inherited method
public function funktion ($ok, $str, $id) {
$this->_funktion ($ok, $str, $id);
}
}
} else {
class myClass extends _myClass{
// give public access to protected inherited method, but only
// with 2 parameters
function funktion ($ok, $str) {
$this->_funktion ($ok, $str);
}
}
}
$obj = new myClass();
// if signature has 2 arguments, third is ignored
$obj->funktion(1, 'test', 3);
// other methods are availble
$obj->otherFunc();

I know it's an old question, and a little different, but FWIW I was looking for some more elegant way, than the one I use now, to have a debug/release run, i.e. a kind of conditional compilation.
So far I couldn't find anything better than running some code inside the assert (https://www.php.net/manual/en/function.assert.php). Here's one of possible use cases:
function debugMsg(string $message): bool
{
echo $message . PHP_EOL;
return true;
}
.....
assert(debugMsg("some debug message"));
Then I can conditionally set 'zend.assertions' to '0' for release or to '1' for debug (using ini_set).
As a result, having a very heavy processing (performance test) and running the code in the "debug mode", gives me tons of output and allows me to see lots of details for debugging purpose, but it works up to 10 times slower than in the "release mode" with all that logging skipped.
Note:
that code (the function call) should return true to work correctly
the 'zend.assertions' shouldn't be '-1' in the php.ini, because otherwise the code for assert is not even generated for execution, and thus cannot be controlled inside the code.

Related

Is the newInstance method fast with little footprint to use in PHP 8 ReflectionAttribute class?

In PHP 8, the class ReflectionAttribute is introduced. It is something like annotations in Java, Typescripts and etc. Well every time you wanna use the attribute of a property, for example, you must do as follow:
$attributeReflection = ...;
...
$attribute = $attributeReflection->newInstance();
$message = $attribute->getMessage();
Where the $attributeReflection is an instance of ReflectionAttribute. And the attribute itself is as follow:
#[Attribute(Attribute::ALL)]
class MyAttribute{
public function __construct(
public ?string $message = ''
){}
}
And is used as follow for a property
class Foo{
#[MyAttribute("my message")
public ?string $id = null;
}
As you can see, every time I wanna get the message of the attribute, I have to create a new instance of it. While the message is never changed for this case.
I`m looking for a way to avoid a new instance and use a shared one.
Is it possible?
It looks like nobody has written up the documentation for the ReflectionAttribute class yet, but you can see a summary in the feature proposal for Attributes, which lists its methods:
class ReflectionAttribute
{
public function getName(): string { ... }
public function getArguments(): array { ... }
public function newInstance(): object { ... }
}
The key here is that you can access the arguments without calling the constructor - indeed, the attribute name doesn't even need to be a valid class name, since it will not be autoloaded until newInstance is called.
So in your example, you can simply say $message = $attributeReflection->getArguments()[0], or write a custom factory that merges instances with the same message, etc.
On the other hand, beware of premature optimisation: only spend time making this more complex if profiling tells you that this is actually a significant cost in your application. You may well find that the reflection itself has a much higher cost than this constructor call, and decide to run the whole thing in a build script, saving the information needed at run-time into some kind of cache.

Phpunit does not execute effective parent test case?

I'm currently testing a wrapper to an API with PHPUnit (CLI).
Due to the nature of the tests, I can pretty much use the same code for testing two different use cases. The only difference is in the values I send to the API as parameters.
So, I decided to write a class DefaultTest, where I test the API using default values used by the API and a second CustomTest(Case) where I test my parameter container with differing values. CustomTest inherites from DefaultTest, as all the functions used for validating the returned data are equivalent in both cases.
Here's some code for your understanding:
class DefaultTest extends PHPUnit_Framework_TestCase {
public function testAPIMethod()
{
$this->checkParameterContainer();
$this->validateResults();
}
public function checkParameterContainer()
{
/* Set up default parameter container */
}
public function validateResults()
{
/* Validate the results */
}
}
class CustomTest extends DefaultTest {
public function checkParameterContainer()
{
/* Set up custom parameter container */
}
public function validateResults()
{
parent::validateResult();
}
}
PHPUnit takes the child class, executes the testAPIMethod, leading to CustomTest::checkParameterContainer() and DefaultTest::validateResults() being executed.
But DefaultTest's testAPIMethod is never executed, as DefaultTest::checkParameterContainer() is never called.
Both classes are fully valid TestCases and DefaultTest is executed normally when not specialized.
So, my question for you guys: Why is that? Do I miss something here? Is this by design?
In case, somebody needs it: PHPUnit uses reflection to find test methods on each class, but will not search in parent classes. So the following will be needed in the child test class:
public function testAPIMethod()
{
parent::testAPIMethod();
}

Need advice on doing PHP unit test on complex methods within a class

I am a beginner of unit testing and having difficulty of testing an algorithm (which is executable by cron in actual implementation) that is within a PHP class with functions that don't have arguments as well as depending on other classes for data sources, e.g. this one:
class Mailing_System_Algo {
function __construct()
{
//Run the mailing system method
$this->execute_mailing_system();
}
function execute_mailing_system()
{
$Class_Data_Source = new Data_Source;
$groups = $Class_Data_Source->get_groups();
//Proceed only if groups are defined
if (!(empty($groups))) {
//rest of the algo codes here-very long and lots of loops and if statements
}
}
}
I would like treat the algo function like a blackbox so I won't be altering anything on their codes when I do the test. But how can I start testing them by feeding them inputs if the execute_mailing_system will run right away the moment the class is instantiated?
Supposing I would like to check if the algo will execute with or without groups, how can I provide an input in my unit test codes for $groups?
This is how my test case would look like:
class WP_Test_Mailing_System_Algo extends WP_UnitTestCase {
/**
* Run a simple test to ensure that the tests are running
*/
function test_tests() {
//no problem here
$this->assertTrue( true );
}
function test_if_algo_wont_run_if_no_groups_provided {
//Instantiate, but won't this algo run the construct function rightaway?
$Mailing_System_Algo = new Mailing_System_Algo;
//rest of the test codes here
//how can I access or do detailed testing of execute_mailing_system() function and test if it won't run if groups are null or empty.
//The function does not have any arguments
}
}
Of course there are lots of tests that I would be writing but I'm currently stuck on this one. This is the first test that I would need to execute. But I have a problem on how to get started doing this. I believe that once I get the technique right, the rest of the tests would be straightforward. I would appreciate any of your inputs and help..Thanks.
There is two flaws with the code that will hamper testing:
Constructor does Real Work
Hard-Coded Dependencies
You can improve this by changing the class to
class Mailing_System_Algo
{
public function __construct()
{
// constructors should not do work
}
public function execute_mailing_system(Data_Source $Class_Data_Source)
{
$groups = $Class_Data_Source->get_groups();
//Proceed only if groups are defined
if (!(empty($groups))) {
//rest of the algo codes here-very long and lots of loops and if statements
}
}
}
This is way, you can replace your Data_Source with a Mock or Stub, returning defined test values.
If this is not an option, have a look at the Test Helper extension:
https://github.com/sebastianbergmann/php-test-helpers¹
In particular, have a look at set_new_overload(), which can be used to register a callback that is automatically invoked when the new operator is executed.
¹ the Test-Helper extension is superseded by https://github.com/krakjoe/uopz

unit test a method that creates an object

I'm trying to get my head round Unit Testing and there's one more piece of the jigsaw I need to find.
What I'm trying to do is write tests for the following code. In this case, I've got a really simple Front Controller (written in PHP).
class frontController
{
public function routeRequest($oRequest)
{
$sClassname = $oRequest->getController();
$sMethod = $oRequest->getAction();
$oController = new $sClassname();
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
The problem I have is because the code creates new objects. I can easily mock the request object so that I can tightly control what it will actually do within my test case. I'm not sure the best way to actually replace the controller with a test double.
This article from IBM suggests having a factory method for creating my controller and then overriding this with a specific class used for testing:
class frontController
{
public function routeRequest($oRequest)
{
$sMethod = $oRequest->getAction();
$oController = $this->createController($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
protected function createController($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
and then for testing perhaps something like this:
class testFrontController extends frontController
{
public function setMockController($oMockController)
{
$this->oMc = $oMockController;
}
protected function createController($oRequest)
{
return $this->oMockController;
}
}
(note this isn't quite what the article says, but I'm thinking it would be most useful to me if it did this)
Another solution could be to have another class that creates the controller. This would then be a dependent class of the frontController. This way I can replace the factory/creation class during testing with a test double. Something like this:
class frontController
{
public function routeRequest($oRequest, $oControllerFactory)
{
$sMethod = $oRequest->getAction();
$oController = $oControllerFactory->create($oRequest);
$oResponse = $oController->{$sMethod}($oRequest);
return $oResponse;
}
}
class controllerFactory
{
public function create($oRequest)
{
$sClassname = $oRequest->getController();
return new $sClassname();
}
}
I guess the dependency injection could be taken care of in the front controller constructor or via a setter instead of a parameter to the actual "route" method.
I think I prefer option 2.
Is either of these two methods the right way of going about testing this kind of thing?
(perhaps "good way" would be better word here!)
Any thoughts or suggestions on option 1 vs option 2 appreciated or indeed any alternatives. Remember - the key thing is about how to test an object that itself creates other objects as part of its execution.
Thanks!
You might find this article handy.
It discusses how object creation should be separated from the actual running of the application.
I generally find factories to be a good thing to use for this scenario. In addition to the swappability aspect, it means that additional parameters, data, or dependencies required by the object being created can be stored by the factory, and so the object which actually requests the new object doesn't have to know anything about them...
You do not want to use the real controller but a mock, right ?
It seems to me the simplest way to achieve this would be to subclass the request so that it returns the name of a MockController.
I assume you have thought through your assertions so as to define the goal of what exactly you are testing. Keep in mind that unit tests are going to be testing the returns from your methods, which, in this case, is $oResponse (whatever this may be). As a result, your test assertions will be based on this return value. Since I don't know what that return value is from your code snippets, I can only demonstrate an example that you can complete.
I would recommend PHPUnit for your testing as it seems to be the most complete package for PHP imho (many are fans of SimpleTest, as well ... to each their own).
It would look something like this (Please note that I have left out includes for brevity. Read the PHPUnit documentation for more information):
class AimTest extends PHPUnit_Framework_TestCase{
private $_controller = null;
private $_request = null;
public function setUp(){
$this->_controller = new frontController();
//what does this object's type?
$this->_request = new requestObject();
}
public function testObjectCreation(){
/*
* note, that this is only one of several assertions that could
* be made depending on the return value
*/
$return = $this->_controller->routeRequest($this->_request);
//tailor to what you expect your output to be
$this->assertTrue($return == "my expected output");
}
Hope I didn't miss the mark completely on your stated purpose. Moral of the story is that you can only test what your methods return. If you want to test object instantiation from a method, use the instanceof PHP function against a method that returns that object after instantiation.

PHP: Callback on Entry/Exit of Class Methods?

Is there a way I can set up callbacks on (or automataically log) method parameters, entries, and exits without making explicit calls within each method? I basically want to log this information to my logger class (which is static) without having to do it manually for each method.
Right now I have to call Logger::logEntry() and Logger::logExit() in every method to accomplish this. I would love to not have to do this:
class TestClass {
public function tester($arg) {
Logger::logEntry();
Logger::info('Parameter $arg => ' . $arg);
// Do some stuff...
Logger::logExit();
}
}
use a wrapper class. this method has the following benefits:
no need to change your underlying class structure / method signatures
change logging? just update this class
update object calls vs inserting code into every class you want to log
.
class LogWatch {
function __construct($class) {
$this->obj = $class;
}
function __call($method, $args) {
if (in_array($method, get_class_methods($this->obj) ) ) {
Logger::logEntry();
Logger::info('Parameter '.implode(', ', $args) );
call_user_func_array(array($this->obj, $method), $args);
Logger::logExit();
} else {
throw new BadMethodCallException();
}
}
}
$test = new LogWatch(new TestClass() );
$test->tester();
// you can use instances of `LogWatch()` just like your watched class
// including passing appropriate params:
$test->tester($param1, $param2);
If you want to do function logging for the sake of debugging you may want to look into the Xdebug extension. There's no good way to intercept function calls at at runtime, and any automated interception will add great runtime overhead.
Using XDebug you could instead turn it on as-needed, as well as get lots of other stuff
( XDebug is thus used with PHPUnit to do unit testing and coverage analysis. )
Xdebug
PHPUnit
The Problem with __call
__call may look to be a fun solution to the problem, but there are 3 problems with this, namely
Significant Execution Overhead. your doing __call --> call_user_func_array , which will literally add not one, but two function calls to every execution.
Backtraces become indecipherable: The actual function you were trying to call gets lost in a sea of __call and call_user_func_array making backtracing exceedingly hard, especially if your backtraces come with their arguent lists included.
Stupid Hidden Functions: You're going back to PHP4 style "hiding" of functions by prefixing them with _ to stop the user directly calling it or seeing it, because if the function name happens to be named what they wan't, the __call wont trigger, so you have already got a whole class full of really horrible function names, which developers will be tempted to call directly anyway in various places. ( And if you want to get rid of __call later, you will have to rename all these functions as to not break the code! )
Thus, if you are utilising php code to implement this will result in epically horrible code, that any future user of your codebase will NOT want to work with. You are far better getting something ( like Xdebug ) that can be added transparently when you need it, and save greatly polluting your code.
you could use the magic function __call. It gets called when no functions match that name. Rename your methods to be prefixed with something, (eg: underscore), and optionally set them to private/protected.
class TestClass {
public function __call($function, $args) {
Logger::logEntry();
Logger::info('Parameters: ' . implode(", ", $args);
$localFunc = "_" . $function;
$return = $this->$localFunc($args);
Logger::logExit();
return $return;
}
private function _tester() {
// do stuff...
return "tester called";
}
}
$t = new TestClass();
echo $t->tester();
// "tester called"

Categories