--
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
---- En jue, 25 feb 2021 23:12:23 +0100 David Gebler davidgebler@gmail.com escribió ----
You can achieve what you're trying to do already with a combination of
get_class()
on a namespaced class and a simple regex (or other method of
processing a string to your liking):$foo = "My\Namespace\Name\Class";
var_dump(preg_match('/^(.)\([^\])$/m',$foo,$matches),$matches);array(3) {
[0] =>
string(23) "My\Namespace\Name\Class"
1 =>
string(17) "My\Namespace\Name"
[2] =>
string(5) "Class"
}Regards
David Gebler
Hi, David.
::namespace notation would be more semantic and faster.
Other example: In WordPress, classes use class-{{class-name}}.php notation for file of classes1. Example: class-wp-error.php
An autoloader for WordPress could be:
<?php
function autoload($fullClassName)
{
$filePath = str_replace('\\', '//', $fullClassName::namespace );
$className = ltrim(strrchr($fullClassName, '\\'), '\\');
$className = strtolower( str_replace('_', '-', $className ) );
require '{$filePath}/class-{$className}.php";
}
spl_autoload_register('autoload');
--
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
Hello, another example with "factories method"1:
use MyProject\Framework;
abstract class AbstractController {
private const HELPER_PATH = static::namespace.'/Helpers';
private const SERVICE_PATH = static::namespace.'/Services';
public function instanceHelper( string $helperClass ) {
$helperClassName = self::HELPER_PATH."/{$helperClass}";
return new $helperClassName();
}
public function instanceService( string $serviceClass ) {
$serviceClassName = self::SERVICE_PATH."/{$serviceClass}";
return new $serviceClassName();
}
}
use MyProject\MyModule;
class Controller {
public function __invoke() {
//......
$date = $this->instanceHelper('Date');
//...
}
}
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
I'm Sorry, I feel a little nervous by writing here again after long time.
Replace '/' by '' and PATH( HELPER_PATH | SERVICE_PATH ) by NAMESPACE( HELPER_NAMESPACE | SERVICE_NAMESPACE ).
Sorry
---- En vie, 26 feb 2021 09:16:18 +0100 Manuel Canga php@manuelcanga.dev escribió ----
Hello, another example with "factories method"1:
use MyProject\Framework; abstract class AbstractController { private const HELPER_PATH = static::namespace.'/Helpers'; private const SERVICE_PATH = static::namespace.'/Services'; public function instanceHelper( string $helperClass ) { $helperClassName = self::HELPER_PATH."/{$helperClass}"; return new $helperClassName(); } public function instanceService( string $serviceClass ) { $serviceClassName = self::SERVICE_PATH."/{$serviceClass}"; return new $serviceClassName(); } } use MyProject\MyModule; class Controller { public function __invoke() { //...... $date = $this->instanceHelper('Date'); //... } }
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga--
To unsubscribe, visit: https://www.php.net/unsub.php
Hola Manuel,
"Don't you think the same ?"
I was thinking of something more generi, maybe :
namespace Foo\Bar;
class A {
static function getNamespace() {
static $ns = __NAMESPACE__;//
https://wiki.php.net/rfc/static_variable_inheritance
return $ns;
}
}
namespace My\Baz;
class B extends \Foo\Bar\A { }
echo \Foo\Bar\A::getNamespace(), PHP_EOL;// Foo\Bar
echo \My\Baz\B::getNamespace(), PHP_EOL;// Foo\Bar Ho no !
Unfortunately it doesn't work ...
Best regards,
Serge
Le ven. 26 févr. 2021 à 09:26, Manuel Canga php@manuelcanga.dev a écrit :
I'm Sorry, I feel a little nervous by writing here again after long time.
Replace '/' by '' and PATH( HELPER_PATH | SERVICE_PATH ) by NAMESPACE(
HELPER_NAMESPACE | SERVICE_NAMESPACE ).Sorry
---- En vie, 26 feb 2021 09:16:18 +0100 Manuel Canga php@manuelcanga.dev
escribió ----Hello, another example with "factories method"1:
use MyProject\Framework; abstract class AbstractController { private const HELPER_PATH = static::namespace.'/Helpers'; private const SERVICE_PATH = static::namespace.'/Services'; public function instanceHelper( string $helperClass ) { $helperClassName = self::HELPER_PATH."/{$helperClass}"; return new $helperClassName(); } public function instanceService( string $serviceClass ) { $serviceClassName = self::SERVICE_PATH."/{$serviceClass}"; return new $serviceClassName(); } } use MyProject\MyModule; class Controller { public function __invoke() { //...... $date = $this->instanceHelper('Date'); //... } }
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga--
To unsubscribe, visit: https://www.php.net/unsub.php
--
To unsubscribe, visit: https://www.php.net/unsub.php
---- En vie, 26 feb 2021 11:08:33 +0100 Glash Gnome glash.gnome@gmail.com escribió ----
Hola Manuel,
"Don't you think the same ?"
I was thinking of something more generi, maybe :namespace Foo\Bar; class A { static function getNamespace() { static $ns = __NAMESPACE__;// https://wiki.php.net/rfc/static_variable_inheritance return $ns; } } namespace My\Baz; class B extends \Foo\Bar\A { } echo \Foo\Bar\A::getNamespace(), PHP_EOL;// Foo\Bar echo \My\Baz\B::getNamespace(), PHP_EOL;// Foo\Bar Ho no !``` Unfortunately it doesn't work ... Best regards,Serge
Hola, Glash,
I sometimes use:
class Foo {
const NAMESPACE = NAMESPACE;
}
Foo::NAMESPACE;
However, this doesn't work:
class Bar extends Foo {
}
Bar::NAMESPACE; // == Foo::NAMESPACE
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
Le 26 févr. 2021 à 09:16, Manuel Canga php@manuelcanga.dev a écrit :
Hello, another example with "factories method"1:
use MyProject\Framework; abstract class AbstractController { private const HELPER_PATH = static::namespace.'/Helpers'; private const SERVICE_PATH = static::namespace.'/Services'; public function instanceHelper( string $helperClass ) { $helperClassName = self::HELPER_PATH."/{$helperClass}"; return new $helperClassName(); } public function instanceService( string $serviceClass ) { $serviceClassName = self::SERVICE_PATH."/{$serviceClass}"; return new $serviceClassName(); } } use MyProject\MyModule; class Controller { public function __invoke() { //...... $date = $this->instanceHelper('Date'); //... } }
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi,
Note that (typos aside) this example cannot work as-is, because static::namespace
(like static::class
) cannot be resolved at compile-time, and therefore cannot be assigned to a constant.
More generally, in the various examples you provided, the namespace is not resolved at compile-time: it is either static::namespace or $fullClassName::namespace where $fullClassName is provided by the autoloader. As such, instead of a ::namespace magic class constant, it might be more appropriate to have a helper function, say get_namespace()
, which has the additional benefit to work not only on (fully qualified) class names, but also on function, constant and namespace names (in the case of namespace names, it would return the name of the parent namespace).
—Claude
Hi,
Note that (typos aside) this example cannot work as-is, because
static::namespace
(likestatic::class
) cannot be resolved at compile-time, and therefore cannot be assigned to a constant.More generally, in the various examples you provided, the namespace is not resolved at compile-time: it is either static::namespace or $fullClassName::namespace where $fullClassName is provided by the autoloader. As such, instead of a ::namespace magic class constant, it might be more appropriate to have a helper function, say
get_namespace()
, which has the additional benefit to work not only on (fully qualified) class names, but also on function, constant and namespace names (in the case of namespace names, it would return the name of the parent namespace).—Claude
Hi, Claude,
That's sound great. Something like dirname[1] but with namespaces.
But...in that case, I also add a new function like basename but with namespaces. Example autoload for WordPress :
function autoload( $ful_class_name ) {
$class_ path = str_replace('\\', '/', get_namespace( $ful_class_name ) );
$class_name = strtolower( get_base_namespace( $ful_class_name ) );
require "{$class_path}/class-{$class_name}.php";
}```
[1]: https://www.php.net/manual/es/function.dirname.php
[2]: https://www.php.net/manual/es/function.basename.php
Regards
--
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
Hi,
Note that (typos aside) this example cannot work as-is, because
static::namespace
(likestatic::class
) cannot be resolved at
compile-time, and therefore cannot be assigned to a constant.More generally, in the various examples you provided, the namespace is
not resolved at compile-time: it is either static::namespace or
$fullClassName::namespace where $fullClassName is provided by the
autoloader. As such, instead of a ::namespace magic class constant, it
might be more appropriate to have a helper function, sayget_namespace()
,
which has the additional benefit to work not only on (fully qualified)
class names, but also on function, constant and namespace names (in the
case of namespace names, it would return the name of the parent namespace).—Claude
Hi, Claude,
That's sound great. Something like dirname[1] but with namespaces.
But...in that case, I also add a new function like basename but with
namespaces. Example autoload for WordPress :function autoload( $ful_class_name ) { $class_ path = str_replace('\\', '/', get_namespace( $ful_class_name ) ); $class_name = strtolower( get_base_namespace( $ful_class_name ) ); require "{$class_path}/class-{$class_name}.php"; }``` [1]: https://www.php.net/manual/es/function.dirname.php [2]: https://www.php.net/manual/es/function.basename.php
Hi,
For that example (and most others), you're manipulating file paths anyway,
and assume that the FQCN is at least one level deep (i.e. not top-level),
so you may as well start with $p = str_replace('\\', \DIRECTORY_SEPARATOR, $fqcn);
then use dirname($p)
and/or basename($p)
.
Now for the (rarer) cases when you actually want the namespace name and/or
the unqualified class name, I agree that the current state is not ideal.
To my knowledge, you have the choice between "magic" string manipulation
(various ways) and "semantic" reflection (e.g. $r = new \ReflectionClass($fqcn);
-- which may try to autoload the class and throws
if it doesn't actually exist -- then use $r->getNamespaceName()
and/or
$r->getShortName()
).
Like str_contains()
was introduced as a "shorthand" for false !==
strpos()``, something like get_namespace_name()
and/or get_short_name()
(or other namings) might be worth considering.
Regards,
--
Guilliam Xavier
---- En vie, 26 feb 2021 14:40:03 +0100 Guilliam Xavier guilliam.xavier@gmail.com escribió ----
Hi,
For that example (and most others), you're manipulating file paths anyway,
and assume that the FQCN is at least one level deep (i.e. not top-level),
so you may as well start with$p = str_replace('\\', \DIRECTORY_SEPARATOR, $fqcn);
then usedirname($p)
and/orbasename($p)
.Now for the (rarer) cases when you actually want the namespace name and/or
the unqualified class name, I agree that the current state is not ideal.
To my knowledge, you have the choice between "magic" string manipulation
(various ways) and "semantic" reflection (e.g.$r = new \ReflectionClass($fqcn);
-- which may try to autoload the class and throws
if it doesn't actually exist -- then use$r->getNamespaceName()
and/or
$r->getShortName()
).
Likestr_contains()
was introduced as a "shorthand" forfalse !==
strpos()``, something likeget_namespace_name()
and/orget_short_name()
(or other namings) might be worth considering.Regards,
--
Guilliam Xavier
Hi, Guilliam,
I think so.
I don't need dirname
function in order to extract path from a file name. However, dirname
exists in order to simplify a "common" task in a semantic way.
Why don't the same with namespaces ?. There is nothing specific in order to work with namespaces only they can be used.
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga
Hi Manuel,
pt., 26 lut 2021 o 09:17 Manuel Canga php@manuelcanga.dev napisał(a):
Hello, another example with "factories method"1:
use MyProject\Framework; abstract class AbstractController { private const HELPER_PATH = static::namespace.'/Helpers'; private const SERVICE_PATH = static::namespace.'/Services'; public function instanceHelper( string $helperClass ) { $helperClassName = self::HELPER_PATH."/{$helperClass}"; return new $helperClassName(); } public function instanceService( string $serviceClass ) { $serviceClassName = self::SERVICE_PATH."/{$serviceClass}"; return new $serviceClassName(); } } use MyProject\MyModule; class Controller { public function __invoke() { //...... $date = $this->instanceHelper('Date'); //... } }
Personally, none of the above examples is convincing bc I'd implement them
using a fixed class names map to avoid loading untrusted classes.
Any kind of helper class is something I'd personally not use to avoid
static coupling of code and hacks while writing unit tests over
services that could be injected by IoC.
Full class names (whether they're aliased or used in use clause) have more
benefit over class name string operations as they're easy for any renaming
which most of the IDE's these days can handle.
IMO introducing namespace magic constant has relatively narrow use and I'd
probably vote NO on this.
Cheers,
Michał Marcin Brzuchalski
---- En vie, 26 feb 2021 13:25:30 +0100 Michał Marcin Brzuchalski michal.brzuchalski@gmail.com escribió ----
Personally, none of the above examples is convincing bc I'd implement them
using a fixed class names map to avoid loading untrusted classes.
Any kind of helper class is something I'd personally not use to avoid
static coupling of code and hacks while writing unit tests over
services that could be injected by IoC.
Full class names (whether they're aliased or used in use clause) have more
benefit over class name string operations as they're easy for any renaming
which most of the IDE's these days can handle.
IMO introducing namespace magic constant has relatively narrow use and I'd
probably vote NO on this.Cheers,
Michał Marcin Brzuchalski
I see...
I agree with you, however one thing is as we would like PHP will be used and other is as it is used.
- https://stackoverflow.com/questions/24798621/how-can-i-get-the-full-namespace-of-a-class-without-creating-an-instance-of-it
- https://stackoverflow.com/questions/13932289/get-php-class-namespace-dynamically
- https://stackoverflow.com/questions/43630010/php-how-can-get-the-namespace-of-class-method-parameter
- https://stackoverflow.com/questions/28182783/get-namespace-of-an-object-using-an-abstract-class-or-trait/28182941
- ...
It's like eval
, it is dangerous, maybe it never should be used. However, sometimes is useful.
do we avoid "dangerous" features ? or do we think people are professional( I don't know if this is used in English equal Spanish ) and they know using it when is needed ?
I think that if something is common and normally useful, PHP should implement that. For example, ::namespace
or get_namespace()
Regards
Manuel Canga
Zend Certified PHP Engineer
Websites: https://manuelcanga.dev | https://trasweb.net
Linkedin: https://es.linkedin.com/in/manuelcanga