I have this a method that i want to get it's values from another method, but i can't since as a parameter i need to pass a class (FTL_Binding) - with no comma between the parameters.
public static function tag_flat_detail(FTL_Binding $tag)
{
$field = $tag->getAttribute('field');
if ( ! is_null($field))
{
$detail = $tag->get('detail');
if ( ! empty($detail[$field]))
{
return self::output_value($tag, $detail[$field]);
}
return self::show_tag_error(
$tag,
'The attribute <b>"field"</b> is not set'
);
}
}
So I've tried this
public static function tag_foo(FTL_Binding $tag)
{
$foo = new FTL_Binding($tag);
return self::tag_flat_detail(FTL_Binding($tag));
}
I'm getting this error ;
Severity: 4096
Message: Argument 1 passed to TagManager_Data::tag_foo() must be an
instance of FTL_Binding, none given, called in
C:\xampp\htdocs\foo\application\libraries\Tagmanager\Data.php on line 70
and defined
Filename: Tagmanager/Data.php
Line Number: 122
I guess the instance $foo = new FTL_Binding($tag); is not working for some reason...
When a function is declared, the types of its arguments can be declared by putting the type before the parameter name:
public static function tag_foo(FTL_Binding $tag, $id = null)
Method tag_foo() expects two parameters:
$tag must be of type FTL_Binding. If FTL_Binding is a class then $tag can be an object of this class or of a derived class. If FTL_Binding is an interface then $tag must be an object of a class that implements FTL_Binding. On PHP 5 only arrays, classes and interfaces can be used as type hints. Since PHP 7, scalar types can also be used.
$id - no type declaration is provided, it can have any type. The = after the name says $id is optional. When it is not provided, the value after = (which is null here) is used instead.
When the function is called, only the values for its arguments must be placed between the parentheses. Like this:
// This works
$x = new FTL_Binding;
self::tag_foo($x, 123); // $id is 123
// This also works
self::tag_foo($x); // $id is NULL
// This doesn't work
self::tag_foo("abc"); // an object of type FTL_Binding was expected
// This also doesn't work
self::tag_foo(NULL, 123); // NULL is also not an object of type FTL_Binding
Read more about classes and objects and about function parameters type declaration (aka "type hinting").
Related
I want to pass a DateTimeZone object to my method in my class Test. I have the following code:
class Test {
function __construct( $timezone_object = new DateTimeZone() ) {
// Do something with the object passed in my function here
}
}
Unfortunately, the above doesn't work. It gave me an error. I know I can do the following instead:
class Test {
function __construct( $timezone_object = NULL ) {
if ( $timezone_object == NULL)
$to_be_processed = new DateTimeZone(); // Do something with my variable here
else
$to_be_processed = new DateTimeZone( $timezone_object ); // Do something with the variable here if this one is executed, note that $timezone_object has to be the supported timezone format provided in PHP Manual
}
}
However, I think that the second choice seems rather unclean. Is there a way to declare my method like the first choice?
If you're just looking for succinct code, you could do
class Test {
function __construct( \DateTimeZone $timezone_object = null ) {
$this->ts = $timezone_object ?? new DateTimeZone();
}
}
the double ?? is an if null check. So you have the type hinting which will only allow DateTimeZone or Null value in (so that's safe), then you just assign a new DateTimeZone instance if the argument was null, otherwise, use the passed in value.
Edit: Found info on default null for PHP 7.1+
Cannot pass null argument when using type hinting
So the code could be even more esoteric, with slightly less key strokes
class Test {
function __construct( ?\DateTimeZone $timezone_object ) {
$this->ts = $timezone_object ?? new DateTimeZone();
}
}
But in my opinion, this is just horrible.
I found a php class in the internet that uses array $options = [] in method argument:
class TADFactory
{
private $options;
public function __construct(array $options = [])
{
$this->options = $options;
}
//some other methods here
}
and in page.php file
$tad_factory = new TADFactory(['ip'=>'192.168.0.1']);
//some other stuffs here
But after executing the page.php file in the browser, it is showing:
Unexpected `[` in page.php file at line 1, expecting `)`....
But according to the php library documentation, I have to use the multidimensional array in argument by that way.
I could not understand what does it mean by array $options = [] in TADFactory class argument and why the error is throwing?
That is a default argument value. It is how you declare that a parameter is optional, and, if not provided, what value it should have by default.
function add($x, $y = 5) {
return $x + $y;
}
echo add(5, 10); // 15
echo add(7); // 12
As for the array annotation, that is a type hint (also called a type declaration), which means that you must pass the function an array or it will throw an error. Type hinting is fairly complicated and debatably necessary in a dynamic language, but it's probably worth knowing about.
function sum(array $nums) {
return array_sum($nums);
}
echo sum([1, 2, 3]); // 6
echo sum(5); // throws an error
NOTE: You can only combine type hints with default argument values if your default argument value is null.
What im doing wrong..im getting this error..
Argument 1 passed to Illuminate\Database\Query\Builder::update() must
be of the type array, string given, called in
C:\xampp\htdocs\newlaravel\app\customer.php on line 33 and defined
Controller
public function siteadmin_customerupdate(Request $request,$id)
{
$cus_name = $request->input('first_name');
//$facebook_id= $request->input('0');
$cus_lname= $request->input('last_name');
$cus_email= $request->input('email');
$v=validator::make($request->all(),
[
]
);
if($v->fails())
{
return redirect()->back()->withErrors($v->errors());
}
else
{
$data=array(
'cus_name'=>$cus_name,
//'facebook_id'=> $facebook_id,
'cus_lname'=> $cus_lname,
'cus_email'=> $cus_email,
);
}
$return = customer::update_customer($data,$id);
Model
public static function update_customer($id,$data)
{
DB::table('le_customer')->whereIn('cus_id', $id)->update($data);
}
route.php
Route::get('siteadmin_editcustomer/{id}', 'SiteadminController#siteadmin_editcustomer');
Route::post('siteadmin_customerupdate','SiteadminController#siteadmin_customerupdate');
You mixed up order of arguments you pass to update_customer method:
customer::update_customer($data,$id);
public static function update_customer($id,$data)
Your customer id is coming string make it Array using explode.
DB::table('le_customer')->whereIn('cus_id', explode(',', $id))->update($data);
Mismatch argument passed and as per your statement first print variable you are passing to update ...
As per error statement it must be array ..but string is coming
What is the proper way to test if a class/method has a type hinted parameter with the reflection class.
How can I test if it exists, is type hinted or not without throwing errors.
What I have sofar returns a notice if it is not type hinted.
Notice: Trying to get property of non-object in
(if I use) getClass()->getName();
$p = new ReflectionParameter(array(get_called_class(), $method), 0);
if ($p) { // not working
echo "param exists";
This is what are you looking for ?
interface CommandInterface
{
}
class Dummy
{
public function execute(
CommandInterface $command,
$when = 'now',
$delayed = true,
$append = null
) {
//
}
}
$reflector = new \ReflectionClass('Dummy');
foreach($reflector->getMethod('execute')->getParameters() as $param)
{
$type = ($param->getClass()) ?
$param->getClass()->name :
gettype($param->getDefaultValue());
echo sprintf('Parameter "%s" of type "%s"'.PHP_EOL, $param->getName(), $type);
}
Output:
Parameter "command" of type "CommandInterface"
Parameter "when" of type "string"
Parameter "delayed" of type "boolean"
Parameter "append" of type "NULL"
I know that it is possible to call a function with a variable number of parameters with call_user_func_array() found here -> http://php.net/manual/en/function.call-user-func-array.php . What I want to do is nearly identical, but instead of a function, I want to call a PHP class with a variable number of parameters in it's constructor.
It would work something like the below, but I won't know the number of parameters, so I won't know how to instantiate the class.
<?php
//The class name will be pulled dynamically from another source
$myClass = '\Some\Dynamically\Generated\Class';
//The parameters will also be pulled from another source, for simplicity I
//have used two parameters. There could be 0, 1, 2, N, ... parameters
$myParameters = array ('dynamicparam1', 'dynamicparam2');
//The instantiated class needs to be called with 0, 1, 2, N, ... parameters
//not just two parameters.
$myClassInstance = new $myClass($myParameters[0], $myParameters[1]);
You can do the following using ReflectionClass
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = array ('dynamicparam1', 'dynamicparam2');
$reflection = new \ReflectionClass($myClass);
$myClassInstance = $reflection->newInstanceArgs($myParameters);
PHP manual: http://www.php.net/manual/en/reflectionclass.newinstanceargs.php
Edit:
In php 5.6 you can achieve this with Argument unpacking.
$myClass = '\Some\Dynamically\Generated\a';
$myParameters = ['dynamicparam1', 'dynamicparam2'];
$myClassInstance = new $myClass(...$myParameters);
I implement this approach a lot when function args are > 2, rather then end up with an Christmas list of arguments which must be in a specific order, I simply pass in an associative array. By passing in an associative array, I can check for necessary and optional args and handle missing values as needed. Something like:
class MyClass
{
protected $requiredArg1;
protected $optionalArg1;
public function __construct(array $options = array())
{
// Check for a necessary arg
if (!isset($options['requiredArg1'])) {
throw new Exception('Missing requiredArg1');
}
// Now I can just localize
$requiredArg1 = $options['requiredArg1'];
$optionalArg1 = (isset($options['optionalArg1'])) ? $options['optionalArg1'] : null;
// Now that you have localized args, do what you want
$this->requiredArg1 = $requiredArg1;
$this->optionalArg1 = $optionalArg1;
}
}
// Example call
$class = 'MyClass';
$array = array('requiredArg1' => 'Foo!', 'optionalArg1' => 'Bar!');
$instance = new $class($array);
var_dump($instance->getRequiredArg1());
var_dump($instance->getOptionalArg1());
I highly recommend using an associative array, however it is possible to use a 0-index array. You will have to be extremely careful when constructing the array and account for indices that have meaning, otherwise you will pass in an array with offset args and wreck havoc with your function.
You can do that using func_get_args().
class my_class {
function __construct( $first = NULL ) {
$params = func_get_args();
if( is_array( $first ) )
$params = $first;
// the $params array will contain the
// arguments passed to the child function
foreach( $params as $p )
echo "Param: $p\n";
}
}
function my_function() {
$instance = new my_class( func_get_args() );
}
echo "you can still create my_class instances like normal:";
$instance = new my_class( "one", "two", "three" );
echo "\n\n\n";
echo "but also through my_function:";
my_function( "one", "two", "three" );
Basically, you simply pass the result of func_get_args to the constructor of your class, and let it decide whether it is being called with an array of arguments from that function, or whether it is being called normally.
This code outputs
you can still create my_class instances like normal:
Param: one
Param: two
Param: three
but also through my_function:
Param: one
Param: two
Param: three
Hope that helps.
I've found here
Is there a call_user_func() equivalent to create a new class instance?
the example:
function createInstance($className, array $arguments = array())
{
if(class_exists($className)) {
return call_user_func_array(array(
new ReflectionClass($className), 'newInstance'),
$arguments);
}
return false;
}
But can somebody tell me if there is an example for classes with protected constructors?