I have a set of read-only tests and a couple of ones that modify data (insert/update/delete). I'd like to back up my tables, so each test class would have a list of associated tables that they'll modify. This is just test data.
I thus thought of this:
abstract class DataAlteringTestBase extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
echo "backing up tables: " . $this->GetAlteredTableNames();
}
public abstract function GetAlteredTaleNames();
}
One of the subclasses:
class DataAlteringTest extends DataAlteringTestBase
{
function GetAlteredTaleNames()
{
return array("some_table");
}
public function testDummyStuffChild()
{
$this->assertTrue(true);
}
}
The problem is, I think, that PHPUnit tries to get the method implementation from the abstract class, rather than its children.
Call to undefined method DataAlteringTest::GetAlteredTableNames() -
the implementation ...\tests\DataAlteringTestBase.php:6 - the abstract
class
How to fix it? or is there something wrong with the idea of implementing this in PHP/PHPUnit in the first place?
You have a few typos - you wrote GetAlteredTaleNames() in some places and GetAlteredTableNames() in other places.
Lets say I have this code:
class A {
...
}
class B extends A {
...
}
class C extends B {
...
}
$c = new C();
$c->getMethodOrPropertyFromB()->getMethodOrPropertyFromA();
Other than a bad architecture or bad design will this have any impact on PHP / Webserver (Apache/Nginx) performance when the script executes?
If this is not recommended to have such multi-level in PHP classes, can you explain why?
Note: in addition to the answers I've got I will let this here which is helpful as well
My initial thought was that this may not be good for inheritance but after testing it seems okay. However, there are other means of accomplishing this you could be aware of.
Abstract classes or Interfaces may make sense.
Abstract classes are just like other classes but they cannot be instantiated. There are also abstract methods which must be implemented by concrete classes.
abstract class A {
//You can also have abstract methods
abstract public function doFoo();
abstract public function doBar($when);
//Also implemented method which when
//called unless overridden will use this logic
public function sayHi(){
echo "hi";
}
}
Now this class can choose to implement the abstract methods or not also adding any further logic needed by it.
abstract class B extends A {
public function doFoo(){
//Some code
}
abstract public function doFooBar();
public function sayBye(){
echo "bye";
}
}
This is a concrete class and all abstract methods must be implemented here if not already ones that are implemented can be overridden yet again.
class C extends B {
public function doFoo(){
//Some different code
}
public function doBar($when){
//Some code
}
public function doFooBar(){
//Some code
}
//do not need sayHi() and sayBye() but they will be available.
}
Interface in a simple and crude way is a bag of methods. You are simply telling the developer if you are going to use this implement these. These methods are not declared as abstract but cannot be implemented in the interface.
interface iA {
public function doFoo();
public function doBar();
}
An interface can be extended by other interface which is just adding more methods to the interface
interface iB extends iA {
public function doFooBar();
}
interface iC {
public function doAnything();
}
And implemented by classes
class A implements iA{
public function doFoo(){
//Some Code
}
public function doBar(){
//Some Code
}
}
class B implements iB{
public function doFoo(){
//Some Code
}
public function doBar(){
//Some Code
}
public function doFooBar(){
//Some Code
}
}
The added advantage of interfaces is that a class or abstract can implement more then one
abstract class C implements iA, iC {
public function doFoo(){
//Some Code
}
}
class D extends C {
//get doFoo() from C implementation and must implement the remaining...
public function doBar(){
//Some Code
}
public function doAnything(){
//Some Code
}
}
This seems perfectly fine. PHP only support single inheritance - so you can only inherit from one class.
If you need more functionality in a class but cannot get the functality in a parent class you can also consider using traits. Traits try to solve the single inheritance problem - even if it's not a problem per se.
If you properly build your classes you get a nice chain of inheritance which does not have any bad influences onto Apache/Nginx.
I have one class
Class Mainclass{}
And another class which is
Class Childclass extends Mainclass{}
Now i want to write callback in Mainclass which check if child class found with method, merge value and return?
How can i achieve using reflection?
One easy way would be to create an interface containing that method
interface XYZ
{
public function myMethod();
}
And make your child class implement it
class Childclass extends Mainclass implements XYZ
{
public function myMethod()
{
//actual implementation
}
}
Afterwards, your main class can easily check if it is implementing that interface:
class Mainclass
{
public function whatever()
{
if ($this instanceof XYZ)
{
$this->myMethod();
}
}
}
Now, I'm fairly sure it would work but I really think this is bad design: a parent class should never depend on the implementation of its child classes. However since I don't know the context in which you're working, I'll leave this here and hope it helps you anyway.
I am having some trouble with Symfony2. Namely in how to use the __construct() function. the Official Documentation is shockingly bad!
I want to be able to use the following:
public function __construct()
{
parent::__construct();
$user = $this->get('security.context')->getToken()->getUser();
}
How ever I get the following error:
Fatal error: Cannot call constructor in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 11
Line 11 is "parent::__construct();"
I removed it and got the following, new error
Fatal error: Call to a member function get() on a non-object in /Sites/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 242
I think I might need to set up the ContainerInterface DIC, but I have no idea how to do this (I tried and failed, miserably)
Any ideas folks?
Update - Tried changing to extend ContainerAware and got this error:
Fatal error: Class DEMO\DemoBundle\Controller\Frontend\HomeController cannot extend from interface Symfony\Component\DependencyInjection\ContainerAwareInterface in /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php on line 43
Using the following code in the controller:
<?php
namespace DEMO\DemoBundle\Controller\Frontend;
use Symfony\Component\DependencyInjection\ContainerAware;
class HomeController extends ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
I'm assuming you are extending the default Symfony controller? If so, a look at the code will reveal the answer:
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
class Controller extends ContainerAware
{
Notice that there is no Controller::__construct defined so using parent::__construct will not get you anywhere. If we look at ContainerAware:
namespace Symfony\Component\DependencyInjection;
class ContainerAware implements ContainerAwareInterface
{
protected $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
}
Again, no constructor and the container is not available until setContainer is called. So override setContainer and put your logic there. Or else just make a stand alone controller that does not extend the base controller class and inject your dependencies directly into the constructor.
Update Aug 2017
Still getting a few hits on this. If you really want to execute something before each controller then use a kernel controller listener. If all you need is the user then of course use getUser(). And please don't override setContainer(). In some cases it would work but it would just convolute your code.
I also frequently want an instance of the current User in most of my controllers. I find it is easiest to just do something like this:
class SomeController extends Controller
{
protected $user;
public function getUser()
{
if ($this->user === null) {
$this->user = $this->get('security.context')->getToken()->getUser();
}
return $this->user;
}
}
However, this is an overly simplistic example case. If you want to do more work before a Controller action is started, I suggest you define your Controller as a Service.
Also take a look at this article: Moving Away from the Base Controller
I have to retrieve the 'facade' manager for my rest api's resource. Not using the constructor and using a private function seems the easiest and simplest for me.
/**
* Class ExchangesController
* #RouteResource("Exchange")
*/
class ExchangesController extends Controller
{
/**
* Get exchange manager
* #return ExchangeManager
*/
protected function getExchangeManager()
{
return $this->get('exchange_manager');
}
/**
* #ApiDoc(
* description="Retrieve all exchanges",
* statusCodes={
* 200="Successful"
* }
* )
*/
public function cgetAction()
{
return $this->getExchangeManager()->findAll();
}
PS It's ok for me to use private/protected functions in my controller as long as it contains zero conditionals
You cannot call getUser() or get() for services in controller constructors. If you remember that, you will save lots of debugging time.
I know the question is very old, but I didn't found an answer until now. So I'll share it.
The goal here, is to execute a code everytime a action in our controller is called.
The __construct method doesn't work, because it's called before anything else, so you can't access the service container.
The trick is to overload each method automatically when they are called :
<?php
namespace AppBundle\DefaultController;
class DefaultController extends Controller {
private function method1Action() {
return $this->render('method1.html.twig');
}
private function method2Action() {
return $this->render('method2.html.twig');
}
public function __call($method, $args) {
$user = $this->get('security.tokenStorage')->getToken()->getUser();
// Do what you want with the User object or any service. This will be executed each time before one of those controller's actions are called.
return call_user_func_array(array($this, $method), $args);
}
}
Warning ! You have to define each method as a private method ! Or the __call magic method won't be called.
There are only two solutions to this problem:
Use a private method as pointed out by #Tjorriemorrie here. But this is a dirty method for purists. (I'm using this! :D );
Define the controller as a service, but this way you will lose all the shortcuts provided by Symfony\Bundle\FrameworkBundle\Controller\Controller. Here is the article that shows how to do this.
As told, personally, in my situation, I prefere a solution like this:
class MyController extends Controller
{
/** #var AwesomeDependency */
private $dependency;
public function anAction()
{
$result = $this->getDependency();
}
/**
* Returns your dependency.
*/
private function getDependency()
{
if (null === $this->dependency)
$this->dependency = $this->get('your.awesome.dependency');
return $this->dependency;
}
}
This is typically a class that I call MyManager where I put the code that I use in more than one action in the controller or that unusefully occupies lines (for example the code to create and populate forms, or other code to do heavy tasks or tasks that require a lot of code).
This way I mantain the code in the action clear in its purposes, without adding confusion.
Maybe the use of a property to store the dependency is an overoptimization, but... I like it :)
As i see, Controller extends ContainerAware, and if we take a look of ContainerAware it implements ContainerAwareInterface. So, ContainerAware must have declared the exact methods in it's interface. Add this line
public function __construct();
to the ContainerAwareInterface definition and it will be solved.
consider the following code as PHP-style pseudo code to get my point across.
class C extends PHPUnit_Framework_TestCase
{
public function m1()
{
$v = $this->m2();
if($v == "x")
{
throw new Exception();
}
}
protected function m2()
{
[...];
return $v;
}
}
now I want to add a test that asserts that an Exception is thrown if m2() returns "x".
How can I simulate that?
I thought about using Reflection to redefine the method during runtime, but it seems that Reflection doesn't offer such a functionality and I would have to resort to experimental extensions like classkit or runkit. Would that be the way to go?
In this case I could extend the class and redefine m2() but where would I put that derived class then? In the same file as the test?
The latter solution wouldn't work anymore if I would choose m2 to be private.
I'm quite sure that there is a best practice to deal with this situation.
Ether I'm completely off on what you are trying to do here or you are doing something that confuses me greatly.
To me is seems that you are asking for is that you want to check that your test method throws an exception.
class C extends PHPUnit_Framework_TestCase
Why would you want to test your test method?
I'm going to assume that that is the real class and not your test
In that case I always strongly argue for just testing it as if the protected method would be inline in the public method.
You want to test the external behavior of your class. Not the implementation. The protected method is and implementation detail that your test shouldn't care about. That would mean that you would have to change your test when you change that protected method.
And from there on out:
class CTest extends PHPUnit_Framework_TestCase {
public function testM1NormalBehavior() {
}
/**
* #expectedException YourException
*/
public function testM1ThrowsExceptionWhenM2ConditionsAreMet() {
$c = new C('set_Up_In_A_Way_That_Makes_M2_Return_X');
$c->m1();
}
}
You can use a partial mock of C to force m2() to return "x". I'll assume that the extends PHPUnit_Framework_TestCase was accidental and that C is actually the class under test and not the unit test itself.
class CTest extends PHPUnit_Framework_TestCase {
/**
* #expectedException Exception
*/
function testM1ThrowsExceptionWhenM2ReturnsX() {
$c = $this->getMock('C', array('m2'));
$c->expects($this->once())->method('m2')->will($this->returnValue('x'));
$c->m1();
}
}