Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
base system
Priority:
Normal
Category:
Task
Assigned:
Reporter:
Created:
13 Apr 2009 at 04:54 UTC
Updated:
7 Dec 2009 at 16:54 UTC
Jump to comment: Most recent file
After searching the forums/handbook/google for a best practice on grabbing the current URL, I finally resorted to #drupal IRC and was told that it's $_GET['q'].
There should be either a global variable (in the tradition of $base_url) or a wrapper function to return the current url. I'm voting for a wrapper function, so I'd like to make one.
| Comment | File | Size | Author |
|---|---|---|---|
| #60 | current_path_no_tests_0.patch | 1.19 KB | mcrittenden |
| #59 | current_path_no_tests_0.patch | 1.19 KB | mcrittenden |
| #57 | current_path_no_tests.patch | 1.19 KB | mcrittenden |
| #56 | current_path_no_tests.patch | 1.2 KB | mcrittenden |
| #46 | path-current_path-431976-46.patch | 2.75 KB | cburschka |
Comments
Comment #1
webchickI've seen this come up repeatedly as a DrupalWTF, so I would like to see this fixed, too. The question is, what to call this function so people will actually find it?
We kicked around some about naming conventions in #drupal. Since $base_url refers to something with http://... in it, current_url() would probably be confusing if it only referred to the 'node/12' part. Quicksketch suggested current_path instead, since elsewhere we refer to something like node/12 as a path. I like that better, for sure.
Adding the appropriate tags. ;)
Comment #2
mcrittenden commentedHere's a first attempt.
Comment #3
webchickThe coding standards (know them, love them, memorize them, and buy them a nice Easter dinner to tell them how much you appreciate their awesomeness) dictate indentation should be 2 spaces rather than tabs.
Additionally, I think the PHPDoc is not quite sufficient to explain to someone who was paging through the huge list of functions how they would know that this was the one that did what they want. How about adding an example?
Comment #4
mcrittenden commentedThanks webchick. Try number two:
Comment #5
mcrittenden commentedAlternatively, the function could prefix a forward slash onto the return var so that a complete URL can be built using base_url() + current_url()?
Comment #6
damien tournoud commentedThe corresponding setter is named
menu_set_active_item(). We probably should harmonize the two.Comment #7
mcrittenden commentedFWIW, I'm opposed to renaming the patch's function to something like menu_get_active_item, just because current_path is more self explanatory and continues the tradition of base_path. If they must be harmonized, I'd rename menu_set_active_item before I'd rename the patch's function. Just my 2 cents.
Comment #8
damien tournoud commentedI agree that menu_set_active_item() is an horrible name. I'm just calling for harmonization.
Comment #9
mcrittenden commentedRename menu_set_active_item to set_current_path then?
Comment #10
mcrittenden commentedOn second thought, that's probably not a good solution either as menu_set_active_item relates to menu_set_item and menu_set_active_trail.
Comment #11
moshe weitzman commentedWe don't have to harmonize right now in this issue. Thats just gonna drag down an otherwise useful patch.
Why would be bother with a tag called Bikeshed? Silly tags like this really do add rows to term_data and term_node. And then the parrots keep on re-using the tag everywhere this adding more rows and even generating email notificaitons. The silly tags make tag browsing harder and vocab admin harder. IMO, the benefit does not outweigh the cost.
Comment #12
mcrittenden commentedComment #13
dave reidInteresting idea. Subscribing.
Comment #14
chx commentedYour example 2 is wrong, please note:
base_pathalways ends with a slash.Comment #15
mcrittenden commentedHere's a reroll per chx's comment. Also changed yoursite.com to example.com per coding standards.
Comment #16
mcrittenden commentedAnother reroll to fix indentation on comments. Sorry guys.
Comment #17
mcrittenden commentedForgot the patch. Sorry again :-/
Comment #18
franskuipers commentedreview in patch review sprint.... my first one.
documentation is not ver clear: current_path: Returns the current URL path of the page being viewed.
In a.d.o I found:
base_path(): Returns the base URL path of the Drupal installation. At the very least, this will always default to /.
$basepath: The base path of the drupal installation. At least will default to /.
$base_url: The base URL of the drupal installation.
As a novice, how can I tel the difference?
Should we have a global $current_path too ??
to make the full url i would think (as a novice): $base_url + base_path() + current_path() , but that is not working when drupal is installed in a subdirectory. $base_url + '/' + current_path() is the right way now.
I feel the function name is not clear: How do I know it is the URL path?; in phpinfo() it is REQUEST_URI.
Maybe rename base_path to base_dir; base_url is ok; current_path can be base_drupal_url ?
Comment #19
mcrittenden commentedfranskuipers: Thanks for the first review! I'd vote no for making a global var out of it just because it's unnecessary and would add another variable without any real benefit. Plus I'm not a big fan of global variables in general so I guess I'm biased (actually addressed that briefly in the opening comments to this issue).
Don't think base_drupal_url really fits since current_path is the path of the page CURRENTLY being viewed, and base_drupal_url sounds like something along the lines of base_url (i.e., something that will never change).
I wouldn't be totally opposed to the idea of renaming base_path to base_dir (kind of lukewarm on that issue), but either way I think we should focus on the current_path function in this issue and introduce the prospect of renaming other functions in separate issues.
Comment #20
chx commentedI am sorry that I have not posted this in the first round -- sorry that was a quick attempt to just CNW it and then return if the author still loves her/his patch. Apparently does, thanks!
So, the problem is with path aliases. If you have 'path/alias' as an alias for 'node/123' and you browse to example.com/drupal/path/alias then this function returns node/123 once you are past DRUPAL_BOOTSTRAP_PATH -- but hook_boot fires before that...
Comment #21
mcrittenden commentedchx: pardon my newbishness. I don't understand why calling a function which calls $_GET['q'] is any different than calling $_GET['q'] directly as far as what it returns. In IRC you referenced http://api.drupal.org/api/function/drupal_init_path/7 which calls http://api.drupal.org/api/function/drupal_get_normal_path/7 which then calls http://api.drupal.org/api/function/drupal_lookup_path/7 which finally sets $_GET['q'] to the path alias rather than the node/XXX path, and that all makes sense. I just don't understand why all that won't happen when called inside a wrapper function as well.
Thought I'd post here instead of IRC so that others could benefit/contribute.
Comment #22
chx commentedIt is not different. $_GET['q'] is undocumented. And this function is documented. What I asked for is "simply" updating the documentation.
Comment #23
chx commentedComment #24
chx commentedNote that I have moved the function to path.inc where it belongs and added comments about path aliases and bootstrap phases.
Comment #25
caktux commentedSome typo and syntax fixes :)
Comment #26
caktux commentedSyntax fix from chx, ready for commit I think ;)
Comment #27
mcrittenden commentedPer IRC request of chx and others, here's an updated version which includes tests. Note that this necessarily includes the addition of a new test file (path.test).
Comment #28
franskuipers commentedDocumentation awful good.
Simple 3 lines code, tested it (with devel PHP execute).
Simpletests passes.
I think: ready to commit.
Comment #29
caktux commentedsee also #445152: Add wrapper function for current path alias ;)
Comment #30
cburschkaExcellent patch! Throughout, I could find only code-style and commenting problems.
The first blank line in this chunk contains trailing white-space.
The hypothetical form seems unnecessarily cumbersome here. "When viewing ..., this function returns ..." would be-- sorry, /is/ more straight-forward. I also think "return "node/306", while base_path() would return" sounds better than " and base_path() would return"...
Needs to be fixed so that grammar and redundancy are fixed. :)
Spaces required on either side of the "=>" operator.
1.) Comments need to end in a period and form complete sentences. (It couldn't hurt to do the same for the assertion messages, though I don't know if it's required there.)
2.) Strings are always encapsulated by single quotes, unless they contain variables, \n-escaped line-breaks, or apostrophes.
3.) String concatenations require a space on either side of the dot.
The minus operator also needs spaces on either side.
The first of these blank lines should be removed. I don't know about the second one.
Comment #31
chx commentedwe have
$this->randomnamefor random strings. Probably just one test against a random string is enough?Comment #32
Pedro Lozano commentedShouldn't all references to $_GET['q'] be converted to current_path() ?
If you do that in this or another patch, can sentences like these be converted without problem with the current patch?
common.inc
language.inc:
Comment #33
mcrittenden commentedPedro Lozano: Yep, that shouldn't cause any problems. If and when it's done, though, I'd vote to stick it in another issue so it doesn't weigh this one down.
I'll reroll a patch in response to the reviews above ASAP.
Comment #34
mcrittenden commentedUpdated patch to reflect chx's "randomName()" function and Arancaytar's grammar and coding style problems.
Comment #35
mcrittenden commentedDiscovered a couple more minor commenting problems. Let's try this again:
Comment #36
mcrittenden commentedTagging.
Comment #37
cburschkaJust one more quibble from me:
You can either quote the URLs or not, but it should be consistent. :)
Okay, two quibbles:
Comments should be on a separate line immediately before the code they reference.
That's really all I can see now.
Comment #38
mcrittenden commentedThanks for your reviews Arancaytar. Here's an updated patch per your two comments.
Comment #39
mcrittenden commentedComment #40
cburschkaWhoops, some whitespace left over at the end of these lines. But this is really the last thing!
Comment #41
mcrittenden commentedWhite space fixed. Thanks again.
Comment #42
mcrittenden commentedProbably not really a feature request.
Comment #43
cburschkaThis looks great now!
The new path.test will need some further test cases (for alias resolution and the like), but this part of it is ready, I believe.
Comment #44
webchickA couple very minor things. Once they're fixed, please mark back to RTBC. mcrittenden, you've earned the title of "Trooper Of The Year." ;)
This is missing a PHPDoc declaration on this class.
Because this a) is not a hook, and b) is inherited from DrupalWebTestCase, we actually do not document it. Strange but true. So this chunk can be removed.
The newly added $this->randomString(); is probably more appropriate here, as that's truly a random string, not a random set of garbled characters.
Comment #45
webchickOh, incidentally, if there is still some documentation somewhere telling you to do it like this, please correct it.
Comment #46
cburschkaSince the remainder is really trivial and I have a moment, I've made the changes. Don't bother crediting me. ;)
Comment #47
sunInstead of duplicating content, I'm pointing to the same review remarks in #432864: Improve comments for function base_path(), which identically apply to this patch.
In general though, I'm a bit opposed to this patch. We have a lot of - senseless - function invocations to base_path() in core and contributed modules. Invoking a function just to get the value of a variable that is available directly is nonsense.
base_path() may be "more special" here, because it returns the value of a global variable. However, $_GET['q'] is... well... a standard environment variable. Accessing it via a function makes absolutely no sense to me. That's plain overhead.
So, if we add this function at all, then only as a helper function for n00bs that don't understand PHP. The PHPDoc should make that purpose clear, and that "regular" PHP coders do not need to resp. should not use it.
Comment #48
sunAnd - sorry, mcrittenden, your effort is great and this is not targeted to you...:
RTBC...? The tests are nonsense. These are testing PHP, not Drupal.
If at all, http://api.drupal.org/api/function/drupal_init_path/7 would have to be used for comparison.
Comment #49
moshe weitzman commentedNo, it isn't senseless. This consolidates code so that we can make future changes in one place. Further, this makes code more readable. $_GET['q'] is a DrupalWTF that means nothing. current_path() is much more descriptive. And I don't really know where to begin with the suggestion that we add phpdoc that says that noobs should use this function but others should not.
The committers can decide whether this needs work or not.
Comment #50
sunIssues with PHPDoc and test comparison still remain.
Comment #51
webchickI disagree completely that this is for "PHP n00bs." This is a DX issue. People with clean URLs enabled (which is the default) have absolutely no idea that there is a ?q=xxx in there, and unless they make a regular habit of var_dump($_GET);ing as they're developing (which, who does?) they end up in #drupal asking the question, "How do I get my current path?", which usually occurs about 3-4 times per week.
It's a nice convenience function for developers, with a negligible performance impact.
Comment #52
webchickI do agree, however, that the PHPDoc of this function should be re-worked to match that of the committed base_path() function. That one was off my radar, so thanks for pointing that out.
And yeah, actually. The tests should be higher-level to cover possible future changes in how we determine what the current path is, as Moshe pointed out. So maybe something like drupalGet(''), check to make sure the current_path() returns ''. Create a node with a path alias, ensure that current_path() still returns node/$nid.
Comment #53
mcrittenden commentedsun: don't worry about offending me. I understand that I'm still new at this and the more constructive criticism I can get, the better. :)
I'm of course fine with fixing comments and I'll do that ASAP (probably Monday if not sooner). But I don't agree that tests here need to be more high level in this specific patch. This patch returns q out of the get array, and nothing more. Therefore, the tests just make sure that it is really returning the q value out of the get array.
I agree that tests need to be put in place eventually to make sure that that q value is what it's supposed to be (i.e., webchick's suggestion with creating a node and alias), but that is completely out of the scope of this patch.
I don't think a simple wrapper function even really warrants a test to begin with because as sun said, all it's really doing is testing PHP, but chx and davereid agreed in IRC that it's needed, no matter how trivial (in fact, the idea of comparing the function's return value to a random value of get q was chx's suggestion...might be interesting to hear his thoughts on this).
I'd vote to fix the comments and get this in there, and devote another patch to testing the paths/alias system in general.
That being said, again I know that I'm new at this and might be completely off base or ignorant. So if/when I'm overruled I'll be happy to fix the tests. :-D
P.S. Sorry for typing out get array...I'm on my phone and brackets are a pain. :)
Comment #54
cburschkaThe point here is that the function itself is trivial and needs no exhaustive testing, but the path handling in total is completely lacking a test suite.
There are at this point two ways we can go:
1.) Decide that the function is trivial enough to need no test in itself, and leave the whole path.test for a separate issue.
2.) Decide to put in a trivial test case for this function.
I agree that we desperately need path.inc tests, and eg. check drupalGet('') -> '', or drupalGet('content/title-alias') -> 'node/123'. But if we do that here, this patch would lose focus from a trivial function addition and become a test suite for path.inc instead, and that should be avoided. Think of the kittens. ;)
Edit: Here we have a bit of a refactoring WTF, because obviously there is also path.module, and while alias resolution is actually done in path.inc, it is tested by modules/path/path.test, so the tests for path.inc don't need to duplicate that. But still, there are plenty of other parts of path.inc that do need tests.
Comment #55
damien tournoud commentedI agree on removing the tests here (those serve no purpose).
Comment #56
mcrittenden commentedFixed comments and removed all tests. More opinions on the testing debate are welcome.
Comment #57
mcrittenden commentedFixed typo.
Comment #58
sunWhen referring to function names and hooks, append trailing braces (
hook_boot()).The description is a bit contradictory - first you say it's not possible to invoke it in hook_boot(), then you explain the return value when used in hook_boot().
We should not teach developers to manually invoke drupal_bootstrap() during the bootstrap process. We already have some contrib modules that do this without any good reason.
Comment #59
mcrittenden commentedThat contradiction was because of someone trying to fix chx's grammar above and ending up changing the meaning completely. Fixed that and appended trailing braces. I don't want to remove the mention of drupal_bootstrap() until chx takes a look at it. It was his comment, so he should get to respond.
Comment #60
mcrittenden commentedOops, couple whitespace fixes.
Comment #61
chx commentedEdit: nevermind. The change I wanted is incorporated in #60 already.
Comment #62
mcrittenden commentedWhat? :)
Comment #63
chx commentedI think this is good. Its the role of hook_boot to tell people "this is not the hook you are looking for"...
Comment #64
dries commentedCommitted to CVS HEAD. Thanks. I've decided not to commit the tests, we can revisit that if desired.
Comment #65
mikeytown2 commentedHeads up from doing boost dev; i18n support with $_GET['q'] isn't all there because of http://api.drupal.org/api/function/drupal_init_path. Our solution was to use $_REQUEST['q']. This is an edge case, just thought I would let you guys know.
Comment #66
sun@mikeytown2: That has always been the case and probably won't change anytime soon. The language prefix is a "virtual" path component - prepended by url() when links are generated, removed by drupal_init_path() when $_GET['q'] is rebuilt. Virtual path prefixes only exist for the language system currently, but people (like me) already considered to re-use this approach to build site sections/contexts (think OG/Domain Access) by adding further prefixes to paths. Also note that $_REQUEST['q'] is always the unaltered 'q' query argument value, very potentially containing an URL alias, not an internal Drupal path. These are further reasons why $_GET['q']/$_REQUEST['q'] is almost unusable prior DRUPAL_BOOTSTRAP_PATH.
Comment #68
mcrittenden commentedSorry to bring up an old issue, just wanted to ping everybody on #653510: Replace $_GET['q'] with current_path() throughout core.