Yes I looked at the previous questions in this topic and I still was not able to solve the problem. I tried ini_set('xdebug.max_nesting_level', 5000); in my script and still Im getting the error. So I will show you what I'm doing to hopefully get some and and get to a resolution.
Basically I running a test with data from my database.
include 'testSettings.php';
//get config
$conf = Config::getInstance('sendCsv.php');
$conf->getConfig();
$formatter = new FormatterContext(new CSVFormatter($conf));
$formatter->formatLoads(null);
The complain comes when I call `$formatter->formatLoads(null);
So here is FormatterContext()
class FormatterContext
{
private $strategy;
public function __construct(IFormatter $formater)
{
$this->strategy = $formater;
}
public function formatLoads()
{
return $this->formatLoads();
}
}
The interface:
abstract class IFormatter
{
private $config;
private $formatted;
private $fileMaps;
private $fileRows;
abstract public function formatLoads($loads);
public function __construct(Config $conf)
{
$this->fileMaps = $conf->__get('fileMaps');
$this->fileRows = $conf->__get('fileRows');
}
}
The Strategy:
class CSVFormatter extends IFormatter
{
public function formatLoads($loads)
{
echo "hello world!\n";
}
}
Now I really don't know what am I doing wrong here. This is the first time I have encounter this error. Beyond nesting level = 5000 I have not tried, I think at that point something is really wrong. Thanks
Arg! Silly me... In the context class I'm calling the context formatLoad() instead of the strategy. Ooops!
The context class should be like:
class FormatterContext
{
private $strategy;
public function __construct(IFormatter $formater)
{
$this->strategy = $formater;
}
public function formatLoads()
{
// return $this->formatLoads();
return $this->strategy->formatLoads();
}
}
Related
I'm self-studying the PHP language. And I'm focused on the latest PHP OOP language.
I search for some "ready-to-install" PHP software and as I scan for some references to search and know, I saw lines of code with a structure like this (can't remember so I'll create my own):
$myapp->settings->getValue('openforum');
$myapp->settings->setValue('closeformaintenance', '1');
So my question is, how can I reproduce the code above? I don't know what term to use that line of code (objects, I guess?).
Something like this:
$newLogin->search($uid)->setLogin($dateToday);
Like that. I really need to do that way so I can organize my coding structure. Thanks by the way.
And also for the final question, IS THAT POSSIBLE?
Here's a fairly straight forward way of looking at it, using dependency injection.
Try it out: https://3v4l.org/iSJgL
Note, the below requires PHP 7 due to the string type hint. Remove that and I believe it should work in 5.6 just fine.
<?php
$myapp = new MyApp(new SettingsBag([
'works' => false,
'random' => rand(),
]));
var_dump($myapp->settings()->get('random'));
var_dump($myapp->settings()->get('works'));
// Let's change it up...
$myapp->settings()->set('works', true);
// Now it should be true.
var_dump($myapp->settings()->get('works'));
These would normally have namespaces like \App and/or \App\Configuration, but I ignore that here so it's easier to follow:
class MyApp {
private $settings_bag = null;
function __construct(SettingsBag $settings_bag)
{
$this->settings_bag = $settings_bag;
}
public function settings()
{
return $this->settings_bag;
}
}
class SettingsBag {
private $settings = null;
function __construct(array $settings = [])
{
$this->settings = $settings;
}
public function set(string $key, $value)
{
return $this->settings[$key] = $value;
}
public function get(string $key)
{
return $this->settings[$key];
}
}
What you try to achieve is called method chaining. You can get this by the following:
<?php
class TestClass {
private $val = '';
public function test1($val) {
$this->val = $val;
return $this;
}
public function test2() {
echo 'Hello '.$this->val;
}
}
$test->test1('World')->test2(); // Hello World
You have simply to return the instance of the object on the method to allow the method chaining.
You can read more here.
It's method chaining.
See code below:
class T {
public function test() {
// do something
return $this;
}
}
$x = new T;
$x->test()->test();
I am trying to write a unit test for a function that immediately loads an object from a different class that uses the input to the function as a parameter. I am new to php unit testing and couldn't find anything that address my particular problem. A few leads that I had that led to no avail was using an injector, and trying to us a reflection.
The code I am trying to write a unit test for is:
public static function isUseful($item) {
$objPromo = MyPromoCodes::Load($item->SavedSku);
if (!is_null($objPromo)
&& ($objPromo->PromoType == MyPromoCodes::Interesting_Promo_Type)) {
return true;
}
return false;
}
My attempt at mocking this out:
public function testIsUseful() {
$injector = $this->getMockBuilder('MyPromoCodes')
->setMethods(array('Load'))
->getMock();
$objPromo = $this->getMock('MyPromoCodes');
$objPromo->PromoType = 'very interesting promo type';
$injector->set($objPromo, 'MyPromoCodes');
$lineItem1 = $this->getDBMock('LineItem');
$this->assertTrue(MyClass::isUseful($lineItem1));
}
however this doesn't work because there is no set method for this object....
Not sure what else to try, any help would be appreciated.
I made the library that makes static classes mocking possible:
class MyClass {
public static $myPromoCodes = 'myPromoCodes';
public static function isUseful($item) {
$objPromo = self::$MyPromoCodes::Load($item->SavedSku);
if (!is_null($objPromo)
&& ($objPromo->PromoType == MyPromoCodes::Interesting_Promo_Type)) {
return true;
}
return false;
}
}
class MyClassTest extends \PHPUnit_Framework_TestCase
{
public function testSomething()
{
$myClass = Moka::stubClass('MyClass');
$myClass::$myPromoCodes = Moka::stubClass(null, ['::Load' => (object)[
'PromoType' => MyPromoCodes::Interesting_Promo_Type
]]);
$this->assertTrue($myClass::isUseful((object)['SavedSku' => 'SKU']);
$this->assertEquals([['SKU']], $myClass::$myPromoCodes->moka->report('::Load'));
}
}
To start with you cannot mock static method with PHPUnit. At least not with 4.x and 5.x.
I would suggest a DI approach like this:
class MyClass
{
private $promoCodesRepository;
public function __construct(MyPromoCodesRepository $promoCodesRepository)
{
$this->promoCodesRepository = $promoCodesRepository;
}
public function isUseful(MyItem $item)
{
$objPromo = $this->promoCodesRepository->Load($item->SavedSku);
// ...
}
}
Here you can easily mock the Load method.
Unfortunately the "static" approach creates a lot of issues during tests so it is better to avoid it whenever possible.
I am getting this error and i can't see what i am doing wrong. I have done the same thing with other objects from other classes which are built in the exact same way and i can't see why i am getting this error now.
The code in which i create the object is this one:
$consulta2 = "SELECT * FROM TiposDireccion WHERE Cliente_CIF='$cif' and Direccion_Direccion='$direccion' and Direccion_CP=$cp ";
echo($consulta2."</br>");
if ($resultado2 = $conexion->query($consulta2)){
while($fila2 = $resultado2->fetch_object()){
$tipodireccion78=$fila2->TipoDireccion_Tipo;
//we see here that the select is returning a correct string with a correct value
echo($tipodireccion78);
//we try to instantiate and it fails =(
$unTipoDireccion=TipoDireccion::constructor1($tipodireccion78);
This is the class TipoDireccion:
<?php
class TipoDireccion{
private $tipo;
private $descripcion;
//Construct auxiliar
function __construct() {
}
//Constructor 1 : completo
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
function ponTipo($tipo) {
$this->tipo = $tipo;
}
function devuelveTipo() {
return $this->tipo;
}
function ponDescripcion($descripcion) {
$this->descripcion = $descripcion;
}
function devuelveDescripcion() {
return $this->descripcion;
}
}
?>
Thank you a lot in advance!
Don't know if this is still relevant to you, but in case anyone else comes on here for an answer. The problem is in this function:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
Because in the class definition, you define private $tipo; and then you try and assign $tipoDireccion->tipo to what was passed through the function. However, you aren't trying to access that variable through the scope of the class, you are trying to assign it from the 'public' scope as far as the class is concerned.
The fix for this has two options, the first one would be to change private $tipo; to public $tipo;. But that isn't a good solution as you have an assignment function for it.
Instead, use your functions that you made, which would make the function look like:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->ponTipo($tipo);
return $tipoDireccion;
}
That's how you need to access it from the public scope, which you are doing after you initiate a new one.
function constructor1($tipo) {}
should be
static function constructor1($tipo) {}
I am architecting out a class and so far have something roughly like the following
in main.php
$coolObject = new CoolObject(true);
foreach($array as $key=>$val)
{
$coolObject->doFunction($val);
}
then inside of CoolObject:
class CoolObject
{
private $_useFunction;
public function __construct($useFoo)
{
//THIS IS WHERE I NEED HELP
if($useFoo){
$this->_useFunction = $this->_foo();
}
else{
$this->_useFunction = $this->_bar();
}
}
public function doFunction($values)
{
$this->_useFunction($values);
}
private function foo($values){
//do stuff
}
private function bar($values){
//do other stuff
}
}
I realize I could put an if statement or switch into doFunction that could handle this functionality, but since I'm not hip on closures/lamdas I wasn't sure if this is the right situation for them or if I'm just totally off base
What you're trying to achieve (as far as I know) are function pointers in PHP.
You should really take a look in: Array Pointer to a function in PHP
I still think inheritance will be the easiest/cleaniest way to solve this.
So you would probably end with:
class CoolObject
{
private $_useFunction;
public function __construct($useFoo)
{
//THIS IS WHERE I NEED HELP
if($useFoo){
$this->_useFunction = 'foo';
}
else{
$this->_useFunction = 'bar';
}
}
public function doFunction($values)
{
//Edited as #newacct corrects
$this->$_useFunction($values);
}
private function foo($values){
//do stuff
}
private function bar($values){
//do other stuff
}
}
I am looking to incorporate a testing framework into a project I am building and came across Enhance PHP which I like but I am having some difficulty finding relevant information on-line since "enhance php" is such a commonly used phrase.
Has anyone worked with this framework that might be able to point me toward some helpful guide? Have you worked with a unit test framework that you think is amazingly better?
Thanks in advance.
In response to Gotzofter, this is the class to be tested:
<?php
include_once('EnhanceTestFramework.php');
class ExampleClass
{
private $OtherClass;
function __construct($mock = null)
{
if ($mock == null)
$this->OtherClass = new OtherExampleClass();
else
$this->OtherClass = $mock;
}
public function doSomething()
{
return $this->OtherClass->getSomething(1, 'Arg2');
}
}
class OtherExampleClass
{
public function getSomething()
{
return "Something";
}
}
class ExampleClassTests extends \Enhance\TestFixture
{
public function setUp()
{
}
public function tearDown()
{
}
public function verifyWithAMock()
{
$mock = \Enhance\MockFactory::createMock('OtherExampleClass');
$mock->addExpectation(
\Enhance\Expect::method('getSomething')
->with(1, 'Arg2')
->returns('Something')
->times(1)
);
$target = new ExampleClass($mock);
$result = $target->doSomething();
\Enhance\Assert::areIdentical("Something", $result);
$mock->verifyExpectations();
}
}
\Enhance\Core::runTests();
look at my constructor for ExampleClass.
Because enhance-php's site example injects the $mock object by calling new ExampleClass($mock), I am forced to change my ExampleClass constructor to handle a $mock as an input parameter.
Do I have to handle this for all classes that I want to subject to unit testing with the framework?
Thanks.
This:
function __construct()
{
$this->OtherClass = new OtherExampleClass;
}
Should be:
function __construct($otherClass)
{
$this->OtherClass = $otherClass;
}
Your mock is never injected at this point in your test:
$target = new ExampleClass($mock);
One thing I would recommend no matter what testing framework you are using is type-hinting against the expected class, or interface.
<?php
class ExampleClass
{
private $OtherClass; // OtherClass instance
public function __construct(OtherClass $OtherClass=null)
{
// ...
}
}
I'm no di expert, but I don't see the problem in letting each class call new if an instance isn't provided for a particular dependency. You could also of course take the approach where you use setter methods to configure dependencies.
<?php
class class ExampleClass
{
private $OtherClass; // OtherClass instance
public function setOtherClass(OtherClass $OtherClass)
{
$this->OtherClass = $OtherClass;
}
}
It is lame that the ExampleClass in the sample code doesn't even define the doSomething method from the ExampleDependencyClassTests, but if I understand correctly it looks like Enhance PHP is not forcing you to take a particular style of dependency injection. You can write the test class however you want, so for example if you took the setter method approach I mentioned above, you could change the example mock code to
<?php
class ExampleDependencyClassTests extends \Enhance\TestFixture
{
public function verifyWithAMock()
{
$mock = \Enhance\MockFactory::createMock('ExampleDependencyClass');
$mock->addExpectation(
\Enhance\Expect::method('getSomething')
->with(1, 'Arg2')
->returns('Something')
->times(1)
);
$target = new ExampleClass();
$target->setExampleDependencyClass($mock);
$result = $target->doSomething();
$mock->verifyExpectations();
}
}
Of course it would probly make sense to make the appropriate revisions to the ExampleClass!
<?php
class ExampleClass
{
private $ExampleDependencyClass;
public function addTwoNumbers($a, $b)
{
return $a + $b;
}
public function setExampleDependencyClass(
ExampleDependencyClass $ExampleDependecyClass
) {
$this->ExampleDependecyClass = $ExampleDependecyClass;
}
public function doSomething($someArg)
{
return 'Something';
}
}
I've worked with PHPUnit quite a bit, and honestly you'll have to face the same challenges with Mocks there. My 2 cents, try to model your tests without Mocks if possible ;)
There is a tutorial on NetTuts titled Testing Your PHP Codebase With Enhance PHP, which will definitely help you to get started.
And there is a Quick Start Guide on Enhance PHP.