Jump to content


Photo

Flaw In Php's Namespace, Cannot Import An Entire Namespace,


  • Please log in to reply
37 replies to this topic

#1 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 02 December 2012 - 12:36 AM

Well its been a while since PHP added namespace support, but so far its still crappy. I am not sure if this has been changed in PHP 5.5, but at least in 5.3.18 and 5.4.9 you cannot do this:

namespace A{
class Foo{
	 public function bar(){
		 echo "foo bar";
	 }
}
}

namespace B{
use \A;
$a = new Foo();
$a->bar();
// This results in a fatal error!
}

Instead, you either have to use the whole namespace name or just import classes in a package one by one:

namespace B{
	 $a = new \A\Foo;
	 $a->bar();
	 // outputs foo bar;

	 use \A\Foo;
	 $n = new Foo;
	 $n->bar();
	 // outputs foo bar;
}

This results in a serious problem when you wish to import an entire sub-namespace. In a real application its unlikely you only have one Foo class in the namespace A, so you have to write multiple lines of use statement to import all these classes, which can be quite annoying.

You may argue that Aliasing is here to serve the purpose, but honestly aliasing is only useful in a really complicated system with namespace as long as 'Application\Model\User\Member\Profile\ProfileField\AboutMe'. In most occasions aliasing is just as much typing as using the entire namespace name, and serves no practical purpose.

You know in Java you can import a package of class using something like 'import javax.swing.*', no idea why in PHP its not possible. Or maybe its already available in PHP 5.5? I dunno.

Edited by Hall of Famer, 02 December 2012 - 12:40 AM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#2 Philip

Philip

    Phailip

  • Staff Alumni
  • 4,746 posts

Posted 02 December 2012 - 12:48 AM

You know in Java you can import a package of class using something like 'import javax.swing.*', no idea why in PHP its not possible.

Because this is PHP and not Java :P

#3 parkerj

parkerj

    Advanced Member

  • Members
  • PipPipPip
  • 167 posts
  • LocationBoston, MA

Posted 02 December 2012 - 12:50 AM

I don't think you can do that in PHP.

<?php
namespace name\of\space\Core;
class Foo{
         public function bar(){
                 echo "foo bar";
         }
}

?>

<?php
class Main extends \name\of\space\Core\Foo {

function __construct() {}

}

eduTrac ERP | College Management System


#4 xylex

xylex

    Advanced Member

  • Members
  • PipPipPip
  • 292 posts

Posted 02 December 2012 - 12:57 AM

PHP requires you to be explicit. That's not necessarily a bad thing. For example, if you can import wildcard namespaces:

namespace A{
class Foo{
    public function bar(){
        echo "A";
    }
}
}

namespace B{
class Foo{
    public function bar(){
        echo "B";
    }
}
}

namespace C{
use \A;
use \B;
$a = new Foo();
$a->bar();
}

What's echoed?

Edited by xylex, 02 December 2012 - 12:59 AM.

The greatest inefficiencies come from solving problems you will never have.  -Rasmus

PHP Development Blog

#5 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 02 December 2012 - 01:00 AM

Because this is PHP and not Java :P


But its a really useful feature PHP is missing, not like the syntax which is simply a matter of opinion. Assume you have a UserFactory class to decide which type of user object(Member, Admin, Banned and Guest) to instantiate, all of these user classes are in the subpackage Model\User. You will have to write this many lines in PHP:
use \Model\User\Member as Member;
use \Model\User\Admin as Admin;
use \Model\User\Banned as Banned;
use \Model\User\Guest as Guest;

In java, all you have to do is to write this line:
import Model.User.*

See how life can be made easier? Sure it may not seem to be a problem when you only needs to import one namespace with four classes, but what if in your controller class you have to import like 5 namespaces and 30+ classes? It will be quite a mess I must say.

PHP requires you to be explicit. That's not necessarily a bad thing. For example, if you can import wildcard namespaces:


Yeah at times it may be helpful, but you have to agree that its so inflexible. There are more occasions you need to import multiple classes from a namespace than dealing with conflicting class names, and PHP aint good at handling this since you can only import one class at a time.

Edited by Hall of Famer, 02 December 2012 - 01:06 AM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#6 trq

trq

    Advanced Member

  • Administrators
  • 30,996 posts
  • LocationSydney, Australia.

Posted 02 December 2012 - 02:48 AM

I've not ran into any major issues with php's implementation and I deal with it all day long. Some people need to get over it. PHP is not Java.

http://thorpesystems.com | http://proemframework.org | http://github.com/trq

SmtpCatcher - A very simple mock sendmail useful for testing PHP mail scripts.
OPM - My Linux package manager.


#7 ignace

ignace

    Now mod flavored

  • Moderators
  • 6,249 posts
  • LocationBelgium

Posted 02 December 2012 - 05:08 AM

use \Model\User\Member as Member;
use \Model\User\Admin as Admin;
use \Model\User\Banned as Banned;
use \Model\User\Guest as Guest;

LOL

1) The as Class part is redundant
2) Why would you create a class for each user role?
3) Assuming all of them implement a UserInterface, how would you check if you are dealing with a banned user?

if ($user instanceof Banned) {

Which is:

1) Not flexible and also hard-couples your code to an implementation
2) If at some point you wish to create a PrivilegedMember you will have to hunt down all type checking code
   and add it.
3) It's error prone, for example if PrivilegedMember extends Member type checking like this:

if ($user instanceof Member) {
  // ..
} else if ($user instanceof PrivilegedMember) {

Means a privileged member is no longer so privileged.

4) It's boring. A new type means lots of code changes as does privilege changes.
Instead use roles, resources, and privileges:

if ($this->acl->isAllowed($this->user, 'content', 'edit')) {

Banned is not a role, more a state, since anyone can be banned, afterwards you still have to know what role he has/had, and it can have special behavior like being only temporary. Something that is not easily captured in an ACL

if ($user->isBanned()) {
  $this->redirect()->to('/you-are-banned');
}

Edited by ignace, 02 December 2012 - 05:29 AM.


#8 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 02 December 2012 - 07:07 AM

use \Model\User\Member as Member;
use \Model\User\Admin as Admin;
use \Model\User\Banned as Banned;
use \Model\User\Guest as Guest;

LOL

1) The as Class part is redundant
2) Why would you create a class for each user role?
3) Assuming all of them implement a UserInterface, how would you check if you are dealing with a banned user?

if ($user instanceof Banned) {

Which is:

1) Not flexible and also hard-couples your code to an implementation
2) If at some point you wish to create a PrivilegedMember you will have to hunt down all type checking code
and add it.
3) It's error prone, for example if PrivilegedMember extends Member type checking like this:

if ($user instanceof Member) {
  // ..
} else if ($user instanceof PrivilegedMember) {

Means a privileged member is no longer so privileged.

4) It's boring. A new type means lots of code changes as does privilege changes.
Instead use roles, resources, and privileges:

if ($this->acl->isAllowed($this->user, 'content', 'edit')) {

Banned is not a role, more a state, since anyone can be banned, afterwards you still have to know what role he has/had, and it can have special behavior like being only temporary. Something that is not easily captured in an ACL

if ($user->isBanned()) {
  $this->redirect()->to('/you-are-banned');
}


Well I am just using this as a quick example in which you may have a series of classes from a namespace you wish to import quickly into another namespace. And now you spent an hour writing useless criticism just for explaining how that user system aint working, its completely missing the point I was arguing early on.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#9 KevinM1

KevinM1

    Snarkimus Prime

  • Moderators
  • 5,217 posts
  • LocationNew Hampshire, USA

Posted 02 December 2012 - 02:42 PM

PHP requires you to be explicit. That's not necessarily a bad thing. For example, if you can import wildcard namespaces:

namespace A{
class Foo{
    public function bar(){
        echo "A";
    }
}
}

namespace B{
class Foo{
    public function bar(){
        echo "B";
    }
}
}

namespace C{
use \A;
use \B;
$a = new Foo();
$a->bar();
}

What's echoed?


In other languages with namespaces, the above would, at the very least, result in a runtime error if not a compiler error.

For once, I agree with Hall of Famer. PHPs namespace implementation is half-baked, and not keeping in line with other languages that implement the feature. Merely dismissing it as "PHP is not Java, get over it" misses the point. The point is that namespaces could be better.

In cases like the example above, it's solved either by using an alias or by explicitly refering to the foo in question. But, one of the entire points of using namespaces is to be able to refer to classes only by their class names. Having to still refer to them by their fully qualified names when there's no naming conflict, even if it's just once, is ridiculous. All it does is add unnecessary boilerplate.

#10 RobertP

RobertP

    Advanced Member

  • Members
  • PipPipPip
  • 288 posts

Posted 02 December 2012 - 02:45 PM

One thing to remember, namespaces is a relatively new feature, and will most likely be improved.
u tha king Pikachu2000!!

#11 kicken

kicken

    Wiser? Not exactly.

  • Gurus
  • 2,703 posts
  • LocationBonita, FL

Posted 02 December 2012 - 04:36 PM

You will have to write this many lines in PHP:

 

No, you only have to write one line like this:
use \Model\User;

Then when you use those classes, do:
new User\Member
or 
new User\Admin



In java, all you have to do is to write this line:

import Model.User.*


There are a lot of people who frown upon using an import * statement and suggest you should be explicit just like PHP forces you to be.  By doing so it makes it easier to see where exactly a particular class comes from.   As you said what if you're importing a bunch of namespaces into your controller, eg
import Blah.*;
import Bleh.*;
import Foo.*;
import Bar.*;

then later on you do something like:
meh = new Meh();

What namespace is Meh from?  Dunno, gotta go search the docs to try and fine out.  With PHP, or if you import selectively you'd know right from the code where it comes from.
Recycle your old CD's, don't trash them!
Did I help you out?  Feeling generous? I accept tips via Paypal or Bitcoin @ 14mDxaob8Jgdg52scDbvf3uaeR61tB2yC7

#12 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 02 December 2012 - 05:40 PM

No, you only have to write one line like this:

use \Model\User;

Then when you use those classes, do:
new User\Member
or
new User\Admin


Nope, this is not what a well-designed namespace system should work. The fact that you have to refer to the class as User\Member and User\Admin instead of just Member and Admin simply kills the purpose of importing namespace. In your case, why not just write the full class name in the format of \Model\User\Member and \Model\User\Admin? How much does it simplify by getting rid of the \Model part? Unless you have a real complicated namespace like App\Model\User\Member\Profile\ProfileField\EditableProfileField, I dont see how it helps practically when you still have to write User\ as prefix for your classes.

Edited by Hall of Famer, 02 December 2012 - 05:41 PM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#13 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 26 December 2012 - 12:01 PM

Whats most annoying about PHP's namespace is that you have to use \ in front of PHP's builtin-class names such as Exception, ArrayObject and even stdclass. Not mentioning how ugly it is to write something like \ArrayObject, this sure makes it much easier to run into bugs in which the evil backslash \ is missing. I know PHP did this for a reason since you may end up defining your own classes that share the same name with PHP's built-in classes, but in most circumstances its not the case. If PHP provides a wildcard import mechanism, at least we can import all classes from PHP's global space so that we dont have to remind ourselves to use backslash \ sign in front of these built-in class names.

Edited by Hall of Famer, 26 December 2012 - 12:04 PM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#14 trq

trq

    Advanced Member

  • Administrators
  • 30,996 posts
  • LocationSydney, Australia.

Posted 26 December 2012 - 03:50 PM

How much have you actually used namespaces Hall of Famer? Most of your arguments refer to issues that I myself have not found to be an actual problem. Sure, there may be some annoyances, but no language can avoid those (annoyances).

http://thorpesystems.com | http://proemframework.org | http://github.com/trq

SmtpCatcher - A very simple mock sendmail useful for testing PHP mail scripts.
OPM - My Linux package manager.


#15 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 26 December 2012 - 08:14 PM

How much have you actually used namespaces Hall of Famer? Most of your arguments refer to issues that I myself have not found to be an actual problem. Sure, there may be some annoyances, but no language can avoid those (annoyances).


Well many people found it not a problem for PHP to be a purely procedural language back in the 90s, so its redundant to bring in OOP? The point is that there's not a way a programming language can meet every coder's need, but a real mature programming language offers a great deal of flexibility to various programmers. The fact that you do not see it a problem not not dictates that the others feel the same way as you do. If you still dont understand, mind elaborating why 'goto' is added in PHP 5.3 when its been argued as a misfeature by many experienced coders? You've gotta give people choices, let them make their own decision on how to write their scripts. Yes no language can avoid certain annoyances, but it's not an excuse to sit here and refuse to improve. You cant be perfect, yet you can always get better.

Edited by Hall of Famer, 26 December 2012 - 08:15 PM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#16 Jessica

Jessica

    This is not my name.

  • Gurus
  • 8,982 posts
  • LocationDallas, TX
  • Age:26

Posted 26 December 2012 - 08:38 PM

" mind elaborating why 'goto' is added in PHP 5.3 when its been argued as a misfeature by many experienced coders? You've gotta give people choices, let them make their own decision on how to write their scripts."

Good job answering your own question!
My goal in replying to posts is to help you become a better programmer, including learning how to debug your own code and research problems. For that reason, rather than posting the solution, I reply with tips and hints on how to find the solution yourself. See below for useful links when you get stuck.

How to Get Good Help: How to Ask Questions | Don't be a help vampire
Debugging Your Code: Debugging your SQL | What does a php function do? | What does a term mean? | Don't see any errors?
Things You Should Do: Normalize Your Data | use print_r() or var_dump()
Lulz: "Functions should not have side effects." - trq

Please take a look at my new PHP/Web Dev blog: The Web Mason - Thanks!!

#17 Philip

Philip

    Phailip

  • Staff Alumni
  • 4,746 posts

Posted 26 December 2012 - 09:07 PM

HoF - I think you have a lot of drive and want to see new features related to this. Why not contribute to the core of PHP and add in / propose some of these features yourself?

#18 requinix

requinix

    Transforming Moderator

  • Moderators
  • 6,040 posts
  • LocationWA

Posted 26 December 2012 - 10:06 PM

By the way, here's a question. Given the pseudo-code
use Fruit\*;
use Colors\*;

$o = new Orange();
Where is PHP supposed to find the Orange class?

#19 Hall of Famer

Hall of Famer

    OOP Fanboi

  • Members
  • PipPipPip
  • 315 posts
  • LocationIthaca

Posted 27 December 2012 - 08:02 AM

" mind elaborating why 'goto' is added in PHP 5.3 when its been argued as a misfeature by many experienced coders? You've gotta give people choices, let them make their own decision on how to write their scripts."

Good job answering your own question!


umm whats your point? PHP right now does not give us a choice for wildcard import, thats what I've been arguing about.


By the way, here's a question. Given the pseudo-code

use Fruit\*;
use Colors\*;

$o = new Orange();
Where is PHP supposed to find the Orange class?


Well ask Java's developers how they handle situations like this with their wildcard import.

Sure there are programmers who make mistakes like that, but it cant be helped. You see people getting errors of missing semicolons everyday, so PHP should allow users to conclude a line without semicolon? Oh yeah, all variables should be constants since some amateur programmers end up overwriting them in an unexpected fashion?


At least, PHP needs to provide auto-importing built-in classes such as ArrayObject and Exception.

Edited by Hall of Famer, 27 December 2012 - 08:12 AM.

Welcome to the world of OOPHP! In a perfect script, everything is an object. You cannot be perfect, but you can approach as close as can.

zog841.jpg


#20 Jessica

Jessica

    This is not my name.

  • Gurus
  • 8,982 posts
  • LocationDallas, TX
  • Age:26

Posted 27 December 2012 - 09:41 AM

You didn't answer his question. Are you able to?
My goal in replying to posts is to help you become a better programmer, including learning how to debug your own code and research problems. For that reason, rather than posting the solution, I reply with tips and hints on how to find the solution yourself. See below for useful links when you get stuck.

How to Get Good Help: How to Ask Questions | Don't be a help vampire
Debugging Your Code: Debugging your SQL | What does a php function do? | What does a term mean? | Don't see any errors?
Things You Should Do: Normalize Your Data | use print_r() or var_dump()
Lulz: "Functions should not have side effects." - trq

Please take a look at my new PHP/Web Dev blog: The Web Mason - Thanks!!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Cheap Linux VPS from $5
SSD Storage, 30 day Guarantee
1 TB of BW, 100% Network Uptime

AlphaBit.com