Php dynamic function names

Php dynamic function names

PHP’s implementation of namespaces is influenced by its dynamic nature as a programming language. Thus, to convert code like the following example into namespaced code:

Example #1 Dynamically accessing elements

class classname
function __construct ()
echo __METHOD__ , «\n» ;
>
>
function funcname ()
echo __FUNCTION__ , «\n» ;
>
const constname = «global» ;

$a = ‘classname’ ;
$obj = new $a ; // prints classname::__construct
$b = ‘funcname’ ;
$b (); // prints funcname
echo constant ( ‘constname’ ), «\n» ; // prints global
?>

One must use the fully qualified name (class name with namespace prefix). Note that because there is no difference between a qualified and a fully qualified Name inside a dynamic class name, function name, or constant name, the leading backslash is not necessary.

Example #2 Dynamically accessing namespaced elements

namespace namespacename ;
class classname
function __construct ()
echo __METHOD__ , «\n» ;
>
>
function funcname ()
echo __FUNCTION__ , «\n» ;
>
const constname = «namespaced» ;

/* note that if using double quotes, «\\namespacename\\classname» must be used */
$a = ‘\namespacename\classname’ ;
$obj = new $a ; // prints namespacename\classname::__construct
$a = ‘namespacename\classname’ ;
$obj = new $a ; // also prints namespacename\classname::__construct
$b = ‘namespacename\funcname’ ;
$b (); // prints namespacename\funcname
$b = ‘\namespacename\funcname’ ;
$b (); // also prints namespacename\funcname
echo constant ( ‘\namespacename\constname’ ), «\n» ; // prints namespaced
echo constant ( ‘namespacename\constname’ ), «\n» ; // also prints namespaced
?>

User Contributed Notes 8 notes

When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.

namespace foo ;
class A public function factory () return new C ;
>
>
class C public function tell () echo «foo» ;
>
>
?>

namespace bar ;
class B extends \ foo \ A <>
class C public function tell () echo «bar» ;
>
>
?>

include «File1.php» ;
include «File2.php» ;
$b = new bar \ B ;
$c = $b -> factory ();
$c -> tell (); // «foo» but you want «bar»
?>

You need to do it like this:

When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.

namespace foo ;
class A protected $namespace = __NAMESPACE__ ;
public function factory () $c = $this -> namespace . ‘\C’ ;
return new $c ;
>
>
class C public function tell () echo «foo» ;
>
>
?>

namespace bar ;
class B extends \ foo \ A protected $namespace = __NAMESPACE__ ;
>
class C public function tell () echo «bar» ;
>
>
?>

include «File1.php» ;
include «File2.php» ;
$b = new bar \ B ;
$c = $b -> factory ();
$c -> tell (); // «bar»
?>

(it seems that the namespace-backslashes are stripped from the source code in the preview, maybe it works in the main view. If not: fooA was written as \foo\A and barB as bar\B)

Important to know is that you need to use the *fully qualified name* in a dynamic class name. Here is an example that emphasizes the difference between a dynamic class name and a normal class name.

namespace namespacename \ foo ;

class classname
<
function __construct ()
<
echo ‘bar’ ;
>
>

$a = ‘\namespacename\foo\classname’ ; // Works, is fully qualified name
$b = ‘namespacename\foo\classname’ ; // Works, is treated as it was with a prefixed «\»
$c = ‘foo\classname’ ; // Will not work, it should be the fully qualified name

// Use dynamic class name
new $a ; // bar
new $b ; // bar
new $c ; // [500]: / — Uncaught Error: Class ‘foo\classname’ not found in

// Use normal class name
new \ namespacename \ foo \ classname ; // bar
new namespacename \ foo \ classname ; // [500]: / — Uncaught Error: Class ‘namespacename\foo\namespacename\foo\classname’ not found
new foo \ classname ; // [500]: / — Uncaught Error: Class ‘namespacename\foo\foo\classname’ not found

Be careful when using dynamic accessing namespaced elements. If you use double-quote backslashes will be parsed as escape character.

$a = «\namespacename\classname» ; //Invalid use and Fatal error.
$a = «\\namespacename\\classname» ; //Valid use.
$a = ‘\namespacename\classname’ ; //Valid use.
?>

Please be aware of FQCN (Full Qualified Class Name) point.
Many people will have troubles with this:

function factory ( $class ) <
return new $class ;
>

// File2.php
$bar = \ foo \ factory ( ‘Bar’ ); // Will try to instantiate \Bar, not \foo\Bar

?>

To fix that, and also incorporate a 2 step namespace resolution, you can check for \ as first char of $class, and if not present, build manually the FQCN:

function factory ( $class ) <
if ( $class [ 0 ] != ‘\\’ ) <
echo ‘->’ ;
$class = ‘\\’ . __NAMESPACE__ . ‘\\’ . $class ;
>

// File2.php
$bar = \ foo \ factory ( ‘Bar’ ); // Will correctly instantiate \foo\Bar

$bar2 = \ foo \ factory ( ‘\anotherfoo\Bar’ ); // Wil correctly instantiate \anotherfoo\Bar

Case you are trying call a static method that’s the way to go:

class myClass
public static function myMethod ()
return «You did it!\n» ;
>
>

$foo = «myClass» ;
$bar = «myMethod» ;

echo $foo :: $bar (); // prints «You did it!»;
?>

It might make it more clear if said this way:

One must note that when using a dynamic class name, function name or constant name, the «current namespace», as in http://www.php.net/manual/en/language.namespaces.basics.php is global namespace.

One situation that dynamic class names are used is in ‘factory’ pattern. Thus, add the desired namespace of your target class before the variable name.

namespaced.php
// namespaced.php
namespace Mypackage ;
class Foo public function factory ( $name , $global = FALSE )
if ( $global )
$class = $name ;
else
$class = ‘Mypackage\\’ . $name ;
return new $class ;
>
>

class A function __construct ()
echo __METHOD__ . «
\n» ;
>
>
class B function __construct ()
echo __METHOD__ . «
\n» ;
>
>
?>

global.php
// global.php
class A function __construct ()
echo __METHOD__ ;
>
>
?>

index.php
// index.php
namespace Mypackage ;
include( ‘namespaced.php’ );
include( ‘global.php’ );

$a = $foo -> factory ( ‘A’ ); // Mypackage\A::__construct
$b = $foo -> factory ( ‘B’ ); // Mypackage\B::__construct

$a2 = $foo -> factory ( ‘A’ , TRUE ); // A::__construct
$b2 = $foo -> factory ( ‘B’ , TRUE ); // Will produce : Fatal error: Class ‘B’ not found in . namespaced.php on line .
?>

as noted by guilhermeblanco at php dot net,

public function create ( $class ) return new $class ();
>
>

$foofact = new fact ();
$bar = $foofact -> create ( ‘bar’ ); // attempts to create \bar
// even though foofact and
// bar reside in \foo

//single or double quotes with single or double backslash in dynamic namespace class.

namespace Country_Name class Mexico function __construct ()echo __METHOD__ , «
» ;
>
>

$a = ‘Country_Name\Mexico’ ; //Country_Name\Mexico::__construct
$a = «Country_Name\Mexico» ;
//Country_Name\Mexico::__construct
$a = ‘\Country_Name\Mexico’ ;
//Country_Name\Mexico::__construct
$a = «\Country_Name\Mexico» ;
//Country_Name\Mexico::__construct
$a = «\\Country_Name\\Mexico» ;
//Country_Name\Mexico::__construct
$o = new $a ;

/* if your namespace name or class name start with lowercase n then you should be alart about the use of single or double quotes with backslash */

namespace name_of_country class Japan function __construct ()
echo __METHOD__ , «
» ;
>

$a = ‘name_of_country\Japan’ ;
//name_of_country\Japan::__construct
$a = «name_of_country\Japan» ;
//name_of_country\Japan::__construct
$a = ‘\name_of_country\Japan’ ;
//name_of_country\Japan::__construct
//$a = «\name_of_country\Japan»;
//Fatal error: Uncaught Error: Class ‘ ame_of_country\Japan’ not found
//In this statement «\name_of_country\Japan» means -first letter n with «\ == new line(«\n). for fix it we can use double back slash or single quotes with single backslash.
$a = «\\name_of_country\\Japan» ;
//name_of_country\Japan::__construct
$o = new $a ;
>

namespace Country_Name class name function __construct ()echo __METHOD__ , «
» ;
>
>

$a = ‘Country_Name\name’ ;
//Country_Name\Norway::__construct
$a = «Country_Name\name» ;
//Country_Name\Norway::__construct
$a = ‘\Country_Name\name’ ;
//Country_Name\Norway::__construct
//$a = «\Country_Name\name»;
//Fatal error: Uncaught Error: Class ‘\Country_Name ame’ not found

//In this statement «\Country_Name\name» at class name’s first letter n with «\ == new line(«\n). for fix it we can use double back slash or single quotes with single backslash
$a = «\\Country_Name\\name» ;
//Country_Name\name::__construct
$o = new $a ;

//»\n == new line are case insensitive so «\N could not affected

  • Namespaces
    • Namespaces overview
    • Defining namespaces
    • Declaring sub-​namespaces
    • Defining multiple namespaces in the same file
    • Using namespaces: Basics
    • Namespaces and dynamic language features
    • namespace keyword and _​_​NAMESPACE_​_​ constant
    • Using namespaces: Aliasing/Importing
    • Global space
    • Using namespaces: fallback to global function/constant
    • Name resolution rules
    • FAQ: things you need to know about namespaces

    Источник

    Create functions dynamically

    Hello. I am curious if it is possible to create functions dynamically in such a way, that (1) the names of the functions to be retrieved from an array and (2) these names could be used also inside the functions. I have a code that is solving the first problem, any ideas how to solve problem 2? Thanks.

    ; > $myvaluetwo(); // The result need to be: The name of the function is myvaluetwo. ?> 
    • 4 Contributors
    • 11 Replies
    • 296 Views
    • 1 Week Discussion Span
    • Latest Post 10 Years Ago Latest Post by eburlea

    I did the following, and that worked. Is that any help or am I still not understanding your problem correctly?

     else < echo \'No\'; >'; $function = create_function('$arg1', $function_content); $function('test'); // Returned "Yes". $function('testt'); // …

    All 11 Replies

    Have you checked out the create_function() function? See here: http://php.net/manual/en/function.create-function.php

    $myarray = ['myvalueone','myvaluetwo','myvaluethree','myvaluefour','myvaluefive']; $func = create_function('$functionname', 'echo "The name of the function is $functionname.";'); for($i=0, $n=count($myarray); $i'; > 

    Actually I need to use these dynamically created functions in a multithreading script which extracts from the database a certain number of categories that need to correspond to the name of a function. I know how to run all functions simultaneously, but I do not know how to get the category name as name of the function and as parameter in the same time. And I am not sure if I can use here ‘$func($myarray[$i])’ as parameter to an object instead of a simple function name as below:

    function first () < for($i=1; $i> function second() < for($i=1; $i> function third() < for($i=1; $i> // create 3 thread objects $t1 = new Application_Plugin_Thread( 'first' ); $t2 = new Application_Plugin_Thread( 'second' ); $t3 = new Application_Plugin_Thread( 'third' ); // start them simultaneously $t1->start( 1, 't1' ); $t2->start( 1, 't2' ); $t3->start( 1, 't3' ); // keep the program running until the threads finish while( $t1->isAlive() && $t2->isAlive() && $t3->isAlive() )

    Источник

    Динамическое имя функции в php

    Я хотел бы упростить создание «пользовательских типов сообщений» в WordPress, так как утомительно проходить один и тот же скрипт и снова и снова изменять все экземпляры имен типа почтового типа вручную. Это довольно просто достичь, создав переменную, содержащую имя CPT, и используйте ее везде, где это необходимо. Таким образом, все, что мне нужно сделать, это объявить переменную в начале скрипта, и это должно заботиться обо всем остальном. Единственная проблема заключается в том, что, чтобы заставить ее работать, мне также нужно префикс имени CPT перед каждой функцией внутри скрипта, и кажется, что использование переменной в имени функции непросто или даже рекомендуется в PHP. Так как я могу это решить? Ниже приведен пример ниже, чтобы было ясно:

    $prefix = 'news'; function news_custom_type_init() < global $prefix; register_post_type($prefix, array( 'labels' =>array( 'name' => $prefix, 'singular_label' => $prefix, 'add_new' => 'Add', . )); register_taxonomy_for_object_type( 'category', $prefix ); > add_action('init', $prefix.'_custom_type_init'); 

    Это почти нормально и может быть стандартизировано, если бы я мог динамически переименовывать функцию, чтобы не писать слово «новости» перед ней, а вместо этого использовать «префикс $». Это может быть приятно, но просто не работает:

    $prefix = 'news'; $functionName= $prefix."_custom_type_init"; function $functionName() < global $prefix; register_post_type($prefix, array( 'labels' =>array( 'name' => $prefix, 'singular_label' => $prefix, 'add_new' => 'Add', . )); register_taxonomy_for_object_type( 'category', $prefix ); > add_action('init', $prefix.'_custom_type_init'); 

    Чтобы вручную назвать функцию, можно проигнорировать первоначальную цель моей попытки (особенно когда скрипт встраивает десятки таких функций, как этот). Какой был бы лучший способ сделать это? PS: Я googled и «stackoverflowed» много об этом, но не нашел никакого рабочего решения, которое соответствует моим потребностям и не генерирует сообщение об ошибке WordPress. Спасибо.

    Источник

    Читайте также:  Background img css cover
Оцените статью