Namespace General Questions

Permalink
Concrete5.7.x has added namespaces. Some of us are not familiar with namespace and need to get up to speed with namespace. The direction that 5.7 is going is great. But some of us independent developers haven't needed to use namespaces before.

Here are some areas that seem confusing. There seems to be variations of the "use" syntax in namespace. There are examples like: (I will enclose the lines just in case they get treated like code)
use Package; 
use Concrete\Core\Package\Package;
use \Concrete\Core\Package\Package;


Question 1. Are the all the same?
Question 2. If they are all the same then is there a "proper" form of the use statement?

bhat
 
Phallanx replied on at Permalink Reply
Phallanx
No. They are not the same.

I'll do the first one last.

Namspaces are [windows style] path name syntax and you will notice that even though namespaces don't necessarily have to be the path to the PHP file; generally they are. This could've been great, only they don't let you use that so not much use after all except to make you type out a long path to make a unique namespace.

So you have relative (qualified name relative to the current namespace) which has no preceding slash (analogous to relative paths in Linux file systems) which is your No.2 line.

Then you have a fully qualified namespace which has the slash. This is the equivalent of starting from the root directory in a Linux file system which is your number 3 line so it is a fully qualified namespace.

Your first line requires that the "Package" class is already loaded into the "global namespace". This is the "get out" clause of namespaces and where all your old classes without namespaces will live when loaded.

It's all detailed over at php.net (https://php.net/manual/en/language.namespaces.basics.php).

You will find that most of the old "helpers" are in the global namespace (and why not, they are used ubiquitously and were proven unique by design in 5.6) which is why you don't need a qualified namespace prefix (you can add one if you'd like the typing practice though). So if the core design is able to load the old helpers into the global namespace, it couldh've loaded the addon classes there too and you then could have used 5.6.x addons. But no. You have to use fully qualified namespaces because that's "neater" and "progressive" in the form over function world.

<rant at PHP>
Namespaces in PHP are a real clusterf@~k. They decided to "assist" some people who were using ridiculously long class names to make their classes globally unique by.....wait for it,,,,,, making class names ridiculously long with a path syntax and forcing everyone to use it! Even better though. You can't use the files path to define the namespace and it must be the first line and must be a string. That level of anality and omission in a dynamically typed and loosely coupled scripting language takes genius levels stupidity because we could have just done namspace dirname(__FILE__). But no. Instead of "my_humongously_long_class_name_myclass{/n}" you now have " namepace \my\humongously\long\class\name/n myclass{}". and when you want to instantiate the classe you [can] have "new \my\humongously\long\class\myclass() instead of "new myclass()"

That's progress eh?
</rant>
mkly replied on at Permalink Reply
mkly
Hi @Bhat,
I'll give you a bit more detail about PHP namespaces and a few quirks in relation to concrete5.

As of PHP 5.3 namepacing was introduced. Most other adult languages have namespacing, but as we all know there is this old guard of PHP developers who only got in it for the money and hate learning new things, so they tend to complain about more advanced functionality in PHP. Google "PHP is not Java" for more complaints like @Phallanx.

Anyhow, the utility of namespacing is that when you are working with libraries created by different organtizations or large codebases, namespacing helps keep everything out of each others way. When creating a class in PHP with namespacing you'll make the first line declare it's namespace. It actually does need to be the first line of code in the file.

For example here is the the Package class file
https://github.com/concrete5/concrete5-5.7.0/blob/develop/web/concre...

Notice how the first line declares the namespace. That means that the full name of the Package class is actually
\Concrete\Core\Package\Package

This is because 'class Package' is in the \Concrete\Core\Package namespace
And you can just use it like
$package = new \Concrete\Core\Package\Package();

without ever even using a 'use' statement at the top. The use statements are mostly there to make the code easier to read below help others who come into the code get up to speed with what is used in that particular class or file. If you do
use \Concrete\Core\Package\Package;

Then you will only need to do
$package = new Package();


With that said, concrete5 also has this concept of class 'Aliases' which have been added to make it easier for developers unfamiliar with PHP 5.3 namespaces. You can see a list of them along with the entry for Package here
https://github.com/concrete5/concrete5-5.7.0/blob/develop/web/concre...

This means you do not have to use the full namespace to use those classes.

Lastly, concrete5 uses a slightly modified PSR-4 autoloader so you can typically find the file for the class in question by using the namespaces as directories. This isn't mandatory or a part of how namespaces work, its simply a convention that concrete5 happens to follow. The '\Concrete\Core' namespace corresponds with the '/concrete/src/' directory and then further namespace declarations will correspond to a directory of the same name.

Hope that helps,
Mike
Phallanx replied on at Permalink Reply
Phallanx
@Mkly
QUOTE>>
but as we all know there is this old guard of PHP developers who only got in it for the money and hate learning new things, so they tend to complain about more advanced functionality in PHP. Google "PHP is not Java" for more complaints like @Phallanx.
<<

Awww. So much bile. So little fact, bless him..
mhawke replied on at Permalink Reply
mhawke
Could you and mkly please PM each other with these little barbs instead of littering the forums with this unhelpful crap.
Phallanx replied on at Permalink Reply
Phallanx
@mhawke
When I can mark his posts as Trolling (that is what it is called when people follow others around forums making disparaging remarks), then I won't need to respond to his snide comments. Until such time, I need to defend public slander in public.

You will also note, I have not been the only target so your frustration maybe better vented at the other party - then maybe you too will join our club :)
mhawke replied on at Permalink Reply
mhawke
Please don't lecture me on what a troll is. I participated in my first discussion forum in the early '80s when I signed into CompuServe on my TI-99/4a to learn how to send messages to my brother's TRS-80 Model 100.

This is aimed at both of you. I have 2 children. When they were little kids around the dinner table, my older son would push his little sister's buttons mercilessly sometimes so my daughter and I devised a plan. Every time I saw it coming, I would tap her foot with my foot under the table and she would say nothing back to him. Instead she would ask me one of several pre-arranged questions to change the subject. Do you know how long it took to stop my son's annoying behaviour? Literally one dinner of being ignored and it was done. Over. Never to return. Exercising your freedom of speech is not always the best strategy. Freedom to ignore can be much more powerful sometimes. When you publicly ignore public criticism and stay on task, you are seen as a professional worthy of respect. If you lash out and respond in kind, your reputation is about the same as my kids around the dinner table.

This is just one man's opinion. Feel free to ignore it.
Phallanx replied on at Permalink Reply
Phallanx
@mahwke
Have you finished now you have got that off your chest? Good. Perhaps now we can talk about how crap PHP namespacing is instead of anecdotes that belong on mumsnet.

Your opinion, as advised, is duly ignored.
bcron replied on at Permalink Reply
bcron
ouhhhh, i actually started coding with early egyptian hieroglyphs ...
bhat replied on at Permalink Reply
bhat
Being an old... old programmer it is clear moving forward is a constant in the universe.

Namespace documentation shows \foo\bar examples and they all make sense. The real world is not quite so simplistic.

I volunteer to dedicate a website to help document but need the help of experts to put something together. It is unfortunate that v5.7+ made so many changes and has so little documentation. Yes that was a mistake.

The question now is whether we move forward gracefully? Lots of us are weak in OOP and namespaces. Documentation specific to Concrete5 will be more helpful than php.net or foo\bar examples. With your help I can learn to move forward and promise to help others. And NO everything isn't consistent for example config.php and class Config is not in the src directory. If the real world was as consistent as the foo bar examples I wouldn't even needed to create this discussion. Let's just help each other move forward gracefully. There is no right or wrong way. That's the problem with collective cooperation. Better that then some new BigCorporation(MS) dictating how things will be done.
MrKDilkington replied on at Permalink Reply
MrKDilkington
There is good news, bhat.

More developer documentation is due this week.
http://www.concrete5.org/community/forums/5-7-discussion/5.7.2-now-...

I am very excited.
bhat replied on at Permalink Reply
bhat
Yes the release of new documentation is exciting.

It still would be nice to have more third party documentation. Sometimes just a little different explanation makes all the difference. Not sure how to close this discussion but it has run its course. Hopefully, the new documentation will also add some light on this topic.
Phallanx replied on at Permalink Reply
Phallanx
@bhat

What is missing is a page like this
http://www.concrete5.org/documentation/developers/system/events...

At some point I expect it and those like it will be updated to reflect 5.7. That would turn the questions about namespacing into cut and paste exercises for most. I think you are just a bit early for concrete specific rather than general questions about namespaces.
bhat replied on at Permalink Reply
bhat
Please, let's keep this discussion at somewhat of an adult level if it must go on.

I'm still not comfortable with namespace. As a procedural programmer inconsistencies are difficult. My question was because of what appeared to be inconsistencies. Throw in OOP with namespaces and things get even more difficult.

Procedural PHP is far different from the new environment that C5 has decided to create for us. I thank C5 for literally forcing me to move forward.

With any major system change it would be nice to include developers before the version release. I think the lack of themes for v5.7+ is a good indication that a mistake has been made by not including developers earlier.

Open Source means that many people work together unlike the big corporations that have a team in a back room making all the decisions.

We all make mistakes. Apparently the release of developer documentation is imminent and that is great. From here and going forward my goal is to help document this new version and hopefully watch a great number of new themes appear. At that point I would feel comfortable suggesting Concrete5 to a client and also feel comfortable that I understand how things work. It seems foolish to me to debate namespace issues when all I want is to produce a functional website and have a happy client!
Phallanx replied on at Permalink Reply
Phallanx
@bhat

Namespacing isn't really complicated. You just define a unique namespace (string) for your file or bit of code. There is a certain format for that string (backslashes) but it can basically be anything you like. You can have multiple classes, variables, functions or lemons in that file/code snippet and you can reference them uniquely even if other classes, functions or oranges have the same names. It may help to begin with to think about the namespace as a directory path and the "Use" as "require_once" then at least it puts it into a known context (this thought process leads to problems, though as we shall see later).

The question is how do you come up with a unique namesapace? It's just very confusing in PHP as it is fairly arbitrary and it looks (and people use it) like a path, even though it isn't - in the file system sense. Except they don't use it like an exact path and sometimes they try to use it as a path and miss-type. This means that on a scale of 1=trivial to use/understand and 10 = Shoot yourself in the foot and bang head against wall, PHP is a 9 after coffee and 10 before.

As one example close to home. The user registration page controller exists in
[ROOT]/concrete/controllers/single_page/register.php

In the register.php the namespace and class are defined thusly:
namespace Concrete\Controller\SinglePage;
use \Concrete\Core\Page\Controller\PageController;
use Config;
use Loader;
use User;
use UserInfo;
use UserAttributeKey;
class Register extends PageController {

That's straight forward, right? The namespace is the directory path (with back slashes instead of forward slashes) and the class name is the file name (minus the ,php). That's pretty neat as it also tells us a lot about the file (name, location). Right?

Except it's not (a path). On closer inspection we notice that case is different (windows users wouldn't care), the underscore is contracted and even if we ignore the lack of a preceding slash to show we start at the root; the file is in "controllers" (note the "s") not controller, as it is in the namespace. That's because a namespace is not a [file] path! It is just a unique string someone typed in (it does have "path-like" properties, but we'll leave that for now).

Those are just a small typos in the path, though. Easy mistakes to to make. The file information is still there if I'm not pedantic so it's not really any problem, right? .

OK. So lets look at
use \Concrete\Core\Page\Controller\PageController;

Lets go and look in [ROOT]/Concrete/Core/Page/Controller/. Hmmmm. There is no "Core" directory! In fact PageController.php is in
[ROOT]/concrete/src/Page/Controller

So if we assume that by convention we use namspaces to convey extra information about file names and locations (a brilliant ancillary use, by the way). That particular one is telling us an out and out lie.
In fact, "Core" is probably an arbitrary construct as an alias for "src" so if we replace all references for "Core" with src in our minds maybe we can find those files but it's getting fuzzy and there are probably exceptions and why alias it at all?.

This kind of stuff just sows confusion and increases documentation by an order of magnitude as the generally accepted scheme of using paths to define namespaces and convey info starts to break down and all the exceptions and caveats have to be documented. In fact it always breaks down unless it is enforced via the language, linker, scripts or a mean lead developer with OCD and a big stick. That is no-ones fault. Programmers have to make concessions, have time constraints and are forced to choose between implementations. It is the languages fault for making those choices possible in the first place and allowing developers to keep shooting, not only their toes, but everyone elses too.
mhawke replied on at Permalink Reply
mhawke
Thanks Phallanx for that detailed explanation. I'm sure it will help others as much as it helped me. I too am concerned with the level of abstraction being used and how that abstraction drives up the 'barriers to entry' for a lot of us. This namespacing thing requires us 'amateur' developers to actually know how concrete5 works at a level that was not required before. Until there is a bunch of code we can copy and paste then we are all just wasting time creating code that doesn't work.
bhat replied on at Permalink Reply
bhat
Thanks Phallanx and mhawke for your help!

One final comment and I give up on this conversation.

BTW, this works:
$bt = Concrete\Core\Block\BlockType\BlockType::getByHandle('autonav');


This should not work but it does (according to php documentation).
$bt = BlockType::getByHandle('autonav');


At minimum, the second example should have a leading backslash if it is a global namespace. However, there is no alias in the file that defines the namespace.
mhawke replied on at Permalink Reply
mhawke
To add more confusion to your world, have a look at the alias array that's built at the top of 'concrete/config/app.php'
JohntheFish replied on at Permalink Reply
JohntheFish
I took a look at that list when @mkly posted the link, so have submitted a pull that at least puts it in alphabetical order.

https://github.com/concrete5/concrete5-5.7.0/pull/1448/files...
mhawke replied on at Permalink Reply
mhawke
I'm really new to namespacing and aliasing so mapping all this crap in my head is damn near impossible. With the expanding APIs available for other platforms, I was under the impression that things were supposed to get simpler as software advances. This feels like eventually we will all be required to know how to code in assembly language.
JohntheFish replied on at Permalink Reply
JohntheFish
I agree, the way the core is now built on a more 'sophisticated' infrastructure has raised the fence of expertise needed before anyone can develop anything more than the most simplistic block. A problem compounded by the pending developer documentation.

For the marketplace, maybe that raising of the expertise fence will turn out to be a good thing. However, for web-shops doing small scale development for specific projects, I am concerned the fence may have been set too high and hence removed one of the basic advantages of concrete5.

Having been developing code for many years in many different languages and infrastructures, I find the changes an annoyance rather than an absolute wall and am sure I will get over it once I find time to read through the core code and work out how to do things.

However, if I was coming from outside and really wanted to develop in Python or Java or node.js, I would be developing in Python or Java or node.js, not in a php based infrastructure with pretenses in that direction. After all, php originated and gained popularity because the alternatives were too complex for many simple web applications.
mhawke replied on at Permalink Reply
mhawke
When Apple recently announced their upcoming Watch product, they also announced that they were giving the developers 6 months to build applications that would actually solve people's problems using the watch. Without add-ons and themes, 5.7 solves no problems. It causes problems.
bhat replied on at Permalink Reply
bhat
Thanks mhawke and JohntheFish!
I looked at that file earlier but was not ready to understand.
If my guess is right you just NAILED why we can reference a class by name.

Look at the path and you see the fully qualified name you have to put in front of the class! So that appears to be an alias to the class and not the namespace! It is easy to test but if my guess is true every one of those aliases means you can reference that in code. That is why
$bt = BlockType::getByHandle('autonav');

works in the header file!
Ah, even without documentation the mystery unfolds. Now if someone can explain why
$site = Config::get('concrete.site');

works. I don't see Config in that list and still can't find the appropriate method let alone an alias. Guess it's time to look at some of those other files a little closer and the answer will pop up.
Shotster replied on at Permalink Reply
Shotster
mhawke replied on at Permalink Reply
mhawke
It's a freakin' hornet's nest. Are we really expected to dig this deep into this stuff just to build add-ons? If so, I'm gone.
Shotster replied on at Permalink Reply
Shotster
> Are we really expected to dig this deep into this stuff just to build add-ons?

Of course not. All you really need to know is that the Config object is globally available, and you need to know how to invoke it to get or set a config value. That much, I presume, is coming in the docs.

@bhat specifically asked how it works, so I pointed him to the relevant portions of the C5 framework.

-Steve
mhawke replied on at Permalink Reply
mhawke
Please understand that I'm not blaming the messenger. Just frustrated like the rest of us. It's one thing to reverse engineer existing code but quite another to create working code from a blank sheet.
Phallanx replied on at Permalink Reply
Phallanx
@bhat

Be careful, now. The aliases aren't really anything to do with PHP namespaces as such. They are for the Symfony autloader. So be aware that when you talk about that file that you are talking about a 3rd party framework (like zend or adodb etc). rather than PHP language.

QUOTE>>
Ah, even without documentation the mystery unfolds. Now if someone can explain why
$site = Config::get('concrete.site'); works.
<<
Ah well. You see it gets icker since classes and functions are resolved slightly differently.

When a class is referenced, the current "working" namespace is checked and, if not found, the autoloader is called (tada !!!!! Symfony). However, if a function is referenced and it is not found in the current namespace, the global namespace is checked. This can lead to unintuitive behaviour where you get an error if you try to instantiate a class but no error if you call one of it's functions. That function you are calling must be in the global namespace.

I think all this required knowledge is just a ploy to make us all core developers instead of CMS users that dabble with addons occasionally...lol

As you are hacking away. You might want to look at
[ROOT]/concrete/src/Foundation/ClassLoader.php and find "setupMapClassAutoloader".

That is the key to loading 5.6 packages in 5.7 ;)
bhat replied on at Permalink Reply
bhat
To all but specially mhawke.
Don't give up. Apparently my previous guess might have been wrong but it seemed good.

I don't plan to give up and I will shortly post my website that will help with documentation. I don't know enough yet. C5 has many good points and that is from a person that has made many client websites in WP. You have helped this old procedural php programmer and with that many thanks.

It's early an if we don't get help from excellent documentation I plan to peal the onion with the help of all of us little people. Yes additional complexity was dumped in our laps! You are helping. My goal is to recommend C5 to a client instead of WP. I would be nuts to do that right now. I have to feel confident I can deliver what the client wants. Until the mystery becomes common knowledge I can't make a client suffer while I learn. With your help we will get there regardless of the big guys and whatever they are thinking. We are already pealing the onion. Keep the faith. We might be closer than you think.
stephendmalloy replied on at Permalink Reply
stephendmalloy
This is a great thread and helped answer some of my questions. I'm not alone. Reminds me of the Michael Jackson song "You are not alone". #deepweb

The docs are coming...