using phpunit with yii - parent classes are not being recognized - php

I wrote a little test case for a model I created in Yii and when I try to run the test, it gives me: Fatal error: Class
'.....\ActiveRecord' not found in Commissions.php'
Now, my class (commissions.php) inherits the ActiveRecord class in Yii but how can I tell PHPunit where to find it? I've tried using an include statement in Commissions.php but then it can't find the class that ActiveRecord inherits and so on.
<?php
include_once('Commissions.php');
class CommissionsTest extends PHPUnit_Framework_TestCase
{
// Here, the idea would be to check one or two employees manually or based on the SQL query
// Or even a previous value using the function so that when any changes are made, the value
// remains the same while using the same arguments.
public function setUp()
{
$this->employee = new Commissions();
$this->employee->employeeId = 'V1S';
$this->employee->year = 2012;
$this->employee->period = 1;
}
public function testAttributes()
{
$this->assertEquals('V1S', $this->employee->employeeId);
$this->assertEquals(2012, $this->employee->year);
$this->assertEquals(1, $this->employee->period);
}
}
?>

What you should have at the beginning of your testcase is:
Yii:import('application.models.Commissions'); //or whatever your model is called
class CommissionsTest extends CDbTestCase { //Not PHPUnit_Framework_TestCase

Related

In PHP, how to pass a class instance to another class's constructor

I am trying to make an implementation of the Bridge Design Pattern, following the steps on Tutorials Point. I am converting the code from Java to PHP and changing some names.
The problem is, when I try to pass the concrete bridge implementer class to the concrete class implementing interface, an error is throw.
My code is as follows:
// LaunchApi.php
interface LaunchApi
{
public function launch();
}
// RedEngine.php
class RedEngine implements LaunchApi
{
public function launch()
{
echo "The red engine is really fast!!!";
}
}
// Rocket.php
abstract class Rocket
{
protected $launchApi;
protected function __construct($launchApiImplementer)
{
$this->launchApi = $launchApiImplementer;
}
public abstract function launch();
}
// FullRocket.php
class FullRocket extends Rocket
{
public function __construct($launchApi)
{
parent::__construct($launchApi);
}
public function launch()
{
$this->launchApi->launch();
}
}
// LaunchingScript.php
$redEngine = new RedEngine();
$redEngine->launch(); // this works
$redRocket = new FullRocket($redEngine);
$redRocket.launch(); // this won't work
The error throw is:
design-patterns\Bridge>php LaunchingBridge.php
The red engine is really fast!!!
Fatal error: Call to undefined function launch() in \design-patterns\Bridge\LaunchingBridge.php on line 24
I tried to pass by reference using the &, but it only changes the error.
yeah should be $redRocket->launch(); instead of $redRocket.launch();
like what nigel ren said

Pass a parent class as a parameter to a function

This is a basic PHP question, and somehow I couldn't find any information about it.
So what I'm trying to do is to pass a parent class to a function so all of its children class can be passed too.
Is there anyway to do it?
function transform(Fruit $fruit){}
transform($orange)
transform($apple)
Update :
Looks like I need to show the situation more.
So what I have is a transformer parent
class ResourceTransformer{
public function transform(ResourceModel $model){}
}
And its child
class ColorTransformer extends ResourceTransformer{}
Now what I want to do is passing ColorModel, a child of ResourceModel to ColorTransformer.
class ColorModel extends ResourceModel{}
when I'm doing that it throws an error like this:
Type error: Argument 1 passed to App\\Modules\\Product\\Transformer\\ResourcesTransformer::transform() must be an instance of App\\Modules\\Product\\Models\\ResourceModel, instance of App\\Modules\\Product\\Models\\ColorModel given.
So basically, ColorTransformer can't accept ColorModel and only accept ResourceModel, yet ColorModel is a child of ResourceModel. Might be some of you can give me more enlightement.
I have tried this code to check your problem
class ResourceModel { }
class ResourceTransformer
{
public function transform(ResourceModel $model)
{
var_dump($model);
}
}
class ColorTransformer extends ResourceTransformer { }
class ColorModel extends ResourceModel { }
$transformer = new ColorTransformer();
$model = new ColorModel();
$transformer->transform($model);
and i've got correct result
object(ColorModel)#2 (0) { }
If this is not working in your case then it's look like the class ResourceModel form this part of your code
class ResourceTransformer{
public function transform(ResourceModel $model){}
}
is not the same that in this part
class ColorModel extends ResourceModel{}
You told in comment that the problem is only with the ColorModel but your information about error tell us that namespaces for ResourceModel and ColorModel are the same so I think the problem is with your ResourceTransformer class definition - do you have this code somewhere in top of your file with this definition?
use App\Modules\Product\Models\ResourceModel;
If you don't then do you have an another declaration of the ResourceModel class somewhere in your file with ResourceTransformer class definition?
The other thing I see in your question is the difference between this part of your code
class ResourceTransformer{
public function transform(ResourceModel $model){}
}
and class name in your error
Type error: Argument 1 passed to App\Modules\Product\Transformer\ResourcesTransformer::transform() must be an instance of App\Modules\Product\Models\ResourceModel, instance of App\Modules\Product\Models\ColorModel given.
Look that in error you have a class ResourcesTransformer and you tell us that this class is named ResourceTransformer. If this difference is ok then your problem should be placed in file with declaration of the ResourcesTransformer class.
You can simply pass name of class as a string and dinamically instantiate it:
function transform($name_of_class){
...
new $name_of_class;
}
Check the example please;
<?php
// function transform(Fruit $fruit){ //or
function transform($fruit){
print_r($fruit);
}
class Fruit{
public $name = null;
function __construct($name){
$this->name = $name;
}
}
transform(new Fruit('Apple')); // result: Fruit Object ( [name] => Apple )
echo '<br />';
$orange = new Fruit('Orange');
transform($orange); // result: Fruit Object ( [name] => Orange )

Proper way to deal with class dependency in a custom class in Laravel 4

I'm adding a custom class to my Laravel library, and seem to be very close to success. Heres what I've done so far, followed by the error I'm getting:
My class is called Connector and is located in Acme/Api/Zurmo/Connector
This class requires another class, so this is the code for that:
use Acme\Api\Rest\ApiRestHelper;
class Connector implements ConnectorInterface {
protected $rest;
public function __construct(ApiRestHelper $rest)
{
$this->rest = $rest;
}
and my ApiRestHelper class starts like this:
namespace Acme\Api\Rest;
class ApiRestHelper {
Then I've just added a quick closure in routes.php to test this works, (which it doesn't):
Route::get('/', function()
{
$connector = new Acme\Api\Zurmo\Connector;
var_dump($connector);
});
This is the error I get:
Argument 1 passed to Acme\Api\Zurmo\Connector::__construct() must be
an instance of Acme\Api\Rest\ApiRestHelper, none given
I first assumed I'd screwed my namespacing, filenaming up, but Laravel can locate the class as I can do the following without error:
$rest = new Acme\Api\Rest\ApiRestHelper;
var_dump($rest);
Any ideas what I'm missing here? Thank you.
The constructor expects you to pass in an instance of resthelper:
//manual dependency injection
Route::get('/', function()
{
$connector = new Acme\Api\Zurmo\Connector(new Acme\Api\Rest\ApiRestHelper);
var_dump($connector);
});
OR change the constructor
//creates a hard dependency
use Acme\Api\Rest\ApiRestHelper;
class Connector implements ConnectorInterface {
protected $rest;
public function __construct()
{
$this->rest = new ApiRestHelper();
}
}
A more advanced option would be to use the IOC container for dependency inject, but thats beyond the scope of this answer
http://laravel.com/docs/ioc

Pondering implementation: Instantiate class based on constant without reflection

Second update
I think I've been approaching this problem from the wrong side of the coin. Would I be correct in assuming that I should be making 'First' an abstract class and just finding a way to reference 'Second' and 'Third' at a later time?
Update
Based on some of the feedback, I have added some content to try and clear up what I would like to do. Something similar to this effect.
I know from just looking at the code below that, it is a waste of performance "if" it did work and because it doesn't, know I am approaching the problem from the wrong angle.The end objective isn't all to uncommon at a guess from some of the frameworks I've used.
I'm more trying to base this particular bit of code on the CodeIgniter approach where you can define (what below) is STR_CLASS_NAME in a config file and then at any point through the operation of the program, use it as i have dictated.
STR_CLASS_NAME = 'Second';
class First {
protected $intTestOne = 100;
public function __construct() {
$strClassName = STR_CLASS_NAME;
return new $strClassName();
}
public function TestOne() {
echo $this->intTestOne;
}
protected function TestThreePart() {
return '*Drum ';
}
}
class Second extends First{
/* Override value to know it's working */
protected $intTestOne = 200;
/* Overriding construct to avoid infinite loop */
public function __construct() {}
public function TestTwo() {
echo 'Using method from extended class';
}
public function TestThree() {
echo $this->TestThreePart().'roll*';
}
}
$Test = new First();
$Test->TestOne(); <-- Should echo 200.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum roll*'
You may be asking, why do this and not just instantiate Second, well, there are cases when it is slightly different:
STR_CLASS_NAME = 'Third';
class Third extends First{
/* Override value to know it's working */
protected $intTestOne = 300;
/* Overriding construct to avoid infinite loop */
public function __construct() {}
public function TestTwo() {
echo 'Using method from extended class';
}
public function TestThree() {
echo $this->TestThreePart().'snare*';
}
}
$Test = new First();
$Test->TestOne(); <-- Should echo 300.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum snare*'
Situation
I have a an abstract class which extends a base class with the actually implementation; in this case a basic DB wrapper.
class DBConnector ()
class DBConnectorMySQLi extends DBConnector()
As you can see, MySQLi is the implementation. Now, dependant upon a value in the configuration process, a constant becomes the class name I wish to use which in this case (as shown below builds DBConnectorMySQLi.
define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);
Objective
To have a base class that can be extended to include the implementation
For the code itself not to need know what the name of the implementation actually is
To (in this case) be able to type or use a project accepted common variable to create DBConnectorMySQLi. I.E. $db or something similar. W
Issue
When it comes to actually calling this class, I would like the code to be shown as below. I was wondering whether this is at all possible without the need to add any extra syntax. On a side note, this constant is 100% guaranteed to be defined.
$DBI = new DB_CLASS();
Solution 1
I know it is possible to use a reflection class ( as discussed in THIS QUESTION) and this works via:
$DBI = new ReflectionClass(DB_CLASS);
However, this creates code that is "dirtier" than intended
Solution 2
Start the specific implementation of DBConnectorMySQLi within the constructor function of DBConnector.
define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);
class DBConnector() { public function __construct() { $this->objInterface = new DBConnectorMySQLi(); }
class DBConnectorMySQLi()
This however would result in the need to keep on "pushing" variables from one to the other
Any advice is much appreciate
You can use variables when you instantiate a class.
$classname = DB_CLASS;
$DBI = new $classname();
Source: instantiate a class from a variable in PHP?

Create a PHP Class -> Create an object of it in another class

I have created a PHP class called formChecker.php. It validates a form. As a Java programmer, I would like to stick with the idea of creating an instance of this class in another class and run it from there. It doesn't seem to be working for me.The following is a demonstration:
class formChecker{
..... validation functions go here
}
class runFormChecker{
.... create instance of formchecker here and use it's methods etc.
}
Can this be done? What I'm thinking of is developing a number of classes that can be run seperately.
GF
I'd rather pass the instance of formChecker (or something that implements a certain interface) to the instance of runFormChecker. see http://en.wikipedia.org/wiki/Dependency_injection
Could be as simple as
interface FormChecker {
public function foo($x);
}
class MyFormChecker implements FormChecker
public function foo($x) {
return true;
}
}
class RunFormChecker {
protected $formChecker=null;
public function __construct(FormChecker $fc) {
$this->formChecker = $fc;
}
// ....
}
$rfc = new RunFormChecker(new MyFormChecker);
Just include the formChecker class file just before the class you want to use it in eg:
include "formChecker.php"
class runFormChecker{
function __construct() {
$obj = new formChecker; // create instance
// more processing............
}
}
If however, you have both classes in one file (which is bad), then no need to include the file, you can create the instance of that straight away eg:
class formChecker{
// ............
}
class runFormChecker{
function __construct() {
$obj = new formChecker; // create instance
// more processing............
}
}
More Information Here....
Thanks :)
Yes, and this is not strange. You would usually create the instance of formChecker within an instance of runFormChecker though, and not at the class level.

Categories