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 )
Related
I am trying to inject one class (a simple PHP class) into another (an ORM\Entity annotated class), and getting an error, but I cannot discover the source. Looking at the code I feel like I am doing everything correctly, yet I cannot solve this error.
Here is the relevant code:
First, the class ORM\Entity where I want to inject the ErrorConstants class:
use Base\Model\Constants\ErrorConstants;
/**
* #ORM\Entity ...
*/
class CwPackagePeriod extends AbstractRestEntity
public $errors;
public function __construct()
{
parent::__construct();
$this->errors = new ErrorConstants();
}
}
The ErrorConstants class is a simple class that contains a list of error constants:
class ErrorConstants
{
public const ERR_MISSING = 'Record could not be found.';
}
The error occurs when I try to throw an exception in the CwPackagePeriod class if an integer value is out of bounds on a setter:
throw new InvalidOrMissingParameterException(
sprintf($this->errors::ERR_MISSING)
);
The error is the following:
Class name must be a valid object or a string
The AbstractRestEntity class does not contain any reference to ErrorConstants, and when I add the reference there, nothing changes with respect to the error. What am I doing wrong?
As u_mulder noted constants refer to class, not to class instance. In order to properly get the constants from your class you could use something like that in your ErrorConstants class:
public function getConstants()
{
$reflectionClass = new \ReflectionClass($this);
return $reflectionClass->getConstants();
}
then in your CwPackagePeriod class:
public function __construct()
{
parent::__construct();
$errorConstants = new ErrorConstants();
$this->errors = $errorConstants->getConstants();
}
...
throw new InvalidOrMissingParameterException(
sprintf($this->errors['ERR_MISSING']);
);
Of course the simplest solution would be to use just:
throw new InvalidOrMissingParameterException(
sprintf(ErrorConstants::ERR_MISSING);
);
Finally I would like to note, although it is not very intuitive, you CAN indeed use $this->errors::ERR_MISSING to get a constant. The reason because you get this error is probably because $this->errors is not defined in that part of code for some reason.
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
i try work with the a class of database, and connect it to wipe it I build using extends, but I get an error. Example:
class Admin extends Sdba{
// Var:
public $login = false;
public $users;
public $users_list;
// Function:
public function UserLogin($char) {
if($this->login) {
print "in";
}else{
$this->users = Sdba::table('users'); // creating table object
$this->users_list = $this->users->get();
print_r($this->user_list);
print "out";
}
}
}
and my DB class is:
http://foska.pp.ua/codecanyon/sdba/
my error is: Fatal error: Call to private Sdba::__construct() from invalid context
Tanks !!
You are inheriting from Sdba class, and when you do that, the actual method: Sdba::table can be referenced as self::table in your child class.
Therefore, the code for creating table object should use:
$this->users = self::table('users'); // creating table object
You can also use parent::table to reference your function. But, the benefit of using self over parent is that you can further modify your table method in this child class, if need arises.
it should use parent::table because you use table method from extended class
$this->users = parent::table('users'); // creating table object
I've run into a problem and I'm not sure if this is just normal behaviour or if I wrote something wrong. I have a method in my base class that applies a global filter to a given class by way of creating a proxy for all new instances of that particular class. The way I planned to go about it is as follows:
Attach static $global_filter (the proxy) to the class I want to be filtered, which extends the base class object
Via my loading mechanism, return the proxy instead of the actual class upon new instantiations (which will mask method calls and apply filters accordingly)
However, I am getting stuck in step 1 and it seems that when I try to assign static $global_filter to the descendent class I want filtered, my base class object also gets the same assignment, which breaks everything else that extends from it.
Please see below for relevant code:
class object {
public static $global_filter;
public function _filterGlobal($class, $method, $callback) {
if ( !is_object($class::$global_filter) ) {
$class::$global_filter = new filterable(null);
# Replace the object being called with the new proxy.
}
var_dump($class);
var_dump($class::$global_filter); // `filterable`
var_dump(\core\blueprint\object::$global_filter); // Returns same as line above
die();
return $class::$global_filter->_add($method, $callback);
}
}
Both $class::$global_filter and \core\blueprint\object::$global_filter (the base class) are returning same instance. Whereas I expected object::$global_filter to be null.
I'm not using late static binding in order to preserve consistency (both single-object filters and global filters are called much in the same way non-statically).
This question seems relevant
Any help will be much appreciated :)
Edit, full example
This would be a concrete class, which extends model which extends object
<?php
use core\blueprint\model;
class modelMock extends model {
protected $schema = array();
public function method($test) {
return $test;
}
}
This would be another object (e.g a controller), which extends object aswell. It applies a filter to all new instances of model
<?php
use core\blueprint\object;
class objectMock extends object {
public function applyFilters() {
$this->_filterGlobal('core\blueprint\model', 'method', function($self, $chain) {
$chain->params[0] = 'new param'; // adjust the paramters
return $chain->next();
});
}
}
when I try to assign static $global_filter to the descendent class I want filtered, my base class object also gets the same assignment
Yes, indeed this happens. A static property in essence is a global variable, constrained within the class's namespace. Running into problems with global variables is often an indication you're not using the best solution.
To solve your problem, you could make the filter a (non-static) property:
$class->$filter = new Whatever();
But as always, there's more roads that lead to Rome, and I would advise you to look for alterative ways to do it.
I don't know if this is a help for you:
class a {
public static $type;
public static function setType($class, $newType) {
$class::$type = $newType;
var_dump($class::$type);
}
}
class b {
public static $type = 'myType';
}
var_dump(b::$type);
a::setType('b', 'yourType');
var_dump(a::$type);
May be you have not defined the static property to the concrete class.
Thanks everyone for you help, I spent some time on it this morning and managed to solve my problem. It's a bit of a workaround but here's how it goes:
public function _filterGlobal($class, $method, $callback) {
if ( !is_object($class::$global_filter[$class]) ) {
$class::$global_filter[$class] = new filterable(null);
# Replace the object being called with the new proxy.
}
return $class::$global_filter[$class]->_add($method, $callback);
}
So basically in order to get unique static variables working in child classes without having to explicitly define them, you can use an array that stores the child's class name as a key and then access these variables via a getter.
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.