Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

arg() was deprecated in D8 because it did not serve any specific need.
Most places that had request dependent logic were using an already injected request, instead of the global arg() function.
D7

// Retrieve an array which contains the path pieces.
$path_args = arg();

// Check if the current page is admin.
if (arg(0) == 'admin') {
  // This is wrong even in D7. path_is_admin() should be used instead.
}

// Conditionally add css or js in certain page.
function mymodule_page_build(&$page) {
  if (arg(0) == 'sth' && arg(1) == 'else') {
    drupal_add_css(drupal_get_path('module', 'mymodule') . '/css/my.css');
  }
}

// Load the current node.
if (arg(0) == 'node' && is_numeric(arg(1))) {
  // This is wrong even in D7. menu_get_object() should be used instead.
}

D8 (procedural)

// Retrieve an array which contains the path pieces.
$current_path = \Drupal::service('path.current')->getPath();
$path_args = explode('/', $current_path);

// Check if the current page is admin.
if (\Drupal::service('router.admin_context')->isAdminRoute(\Drupal::routeMatch()->getRouteObject())) {
}

// Conditionally add css or js in certain page.
function mymodule_page_attachments(array &$attachments) {
  if (\Drupal::routeMatch()->getRouteName() == 'my.route') {
    $attachments ['#attached']['library'][] = 'my_module/my_library'; // you'll need to define in mymodule.libraries.yml
  }
}

// Load the current node.
$node = \Drupal::routeMatch()->getParameter('node');
if ($node) {
}

D8 (OOP)

use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Routing\AdminContext;
use Drupal\Core\Routing\RouteMatchInterface;
class myClass {
  public function __construct(Request $request, AdminContext $admin_context, RouteMatchInterface $route_match) {
    $this->request = $request;
    $this->adminContext = $admin_context;
    $this->routeMatch = $route_match;
  }

  public function test() {
    // This might change in https://drupal.org/node/2239009
    $current_path = $this->request->attributes->get('_system_path');
    // Retrieve an array which contains the path pieces.
    $path_args = explode('/', $current_path);

    // Check if the current page is admin.
    if ($this->adminContext->isAdminRoute($this->routeMatch->getRouteObject())) {
    }

    // Load the current node.
    $node = $this->routeMatch->getParameter('node');
    if ($node) {
    }
  }
}

In any case if you still have procedural code that is still dependent on URL paths, you should at least refactor it to check routes and route names instead.

Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

Bevan’s picture

Eek. These code examples make me want to stick to Drupal 7

Upchuk’s picture

Once you understand them fully, you can't possible think that anymore :)

You can follow me on Twitter: @drupalexp or on my blog.

jaguar_arx’s picture

I'm afraid that Bevan is right. Developers of D8 doesn't understand why Drupal became popular. Look at the code od D8. More code - more troubles.

hermes_costell’s picture

And once you understand fully how to drive a helicopter you'll never want to go back to driving a car.

Oh, did I mention that it takes years to learn how to drive a helicopter?

Wolf_22’s picture

Why stop there? Let's just make a bunch of websites with 1s and 0s! :.)

I'm definitely with you on this: I can't shake the feeling that this replacement for arg() is a functional regression. I'm sure good reasons exist for the change but good golly, the whole thing that made Drupal what it has been is the ease of using things when doing coding (despite even D7 having issues, too). Even if this alternative / "more efficient way" is the way to go, you'd think that the captains behind the wheel would stop for a second and say to themselves, "Hey, wait a minute... Up to this point, our main audience has been accustomed to using a simple arg() call to determine locations. Now, we're going to make them use not only an approach that has multiple more lines of code to get the equivalent but we're now also going to force them to use granular PHP functions [i.e. - explode()] as well as force them to all to become OOP developers just for determining URL endpoints!? This might not be the best idea..."

...which is probably one of the many reasons Backdrop was started.

In other words, D7 apparently enjoyed the luxury of having users' input in how it's direction was determined, or, at least more so than it has been in D8. It's clearly been architected by developers through and through and while that's okay in many respects, it's clearly capable of shortcomings when it comes to accommodating users. Case in point: arg().

Hopefully this is just growing pains and a better approach evolves. The way it stands, it's just dismal.

dx007’s picture

Totally agree with you Bevan !

This is why other languages take advantage. Write less, do more (jQuery). This approach is difficult to remember and maybe be confusing when going further to a deep robust code.

skein’s picture

So basically we add an explode everywhere now? Isn't that the same as using arg() in the first place in a clean wrapper function.

ParisLiakos’s picture

No, basically you stop working with paths, and use routes:)

SKAUGHT’s picture

i think the best example to focus on is the 'add css to this page' example of routing. In technique, we shouldn't be focusing on the path (being the attributes) anymore but what's on the route.

ParisLiakos’s picture

exactly! that way your code works even if a contrib module changes the path of a route :)

Danny Englander’s picture

So with this code for D8:

if (\Drupal::routeMatch()->getRouteName() == 'my.route')

Does that mean the URL path is example.com/my/route ?

ParisLiakos’s picture

No, my.route is the key from the route definition in your routing.yml. The definition contains the path
see https://www.drupal.org/node/2116767

labboy0276’s picture

Quick note:

current_path() should really be \Drupal::request()->getRequestUri();

John Ouellet
Sales Engineering Manager
https://thinktandem.io/

zmove’s picture

Personnally, if I put that code in my module :

// Check if the current page is admin.
if (service('router.admin_context')->isAdminRoute(\Drupal::routeMatch()->getRouteObject())) {
  dsm('admin page');
}

I het the following error :

Fatal error: Call to undefined function service() in /www/modules/mymodule/mymodule.module on line 79

Wow, so complex to just test an argument in the URL, I'm agree with some comments. I find drupal 8 very cool, but the syntax is too much complicated to use. At the era of jQuery and simple and comprehensive language, for me, it's a rollback and I hope Drupal will be able to keep his community, cause it's a really cool CMS

SKAUGHT’s picture

$admin_route = \Drupal::service('router.admin_context')->isAdminRoute();

returns as true/false.

the uptake time for D8 for sure is a bit longer than previous versions. There are as many ways to do things as ever. Depending who you talk with, alot of ''right' vs 'better' is what i do find with other devs. As always, it comes from knowledge base and point of view.

karthikeyan-manivasagam’s picture

 $path = \Drupal::request()->getpathInfo();
 $arg  = explode('/',$path);

$arg will have numeric array of values;

 Array
(
    [0] => 
    [1] => node
    [2] => add
    [3] => application
)
arunkumark’s picture

current_path() function has been deprecated, we can use \Drupal::service('path.current')->getPath() or \Drupal::service()->getPath() to get current path.

aliaric’s picture

Well I got a case when I need to get path arguments in form.
buildForm method does not support path argument values. So id need to use arg

skein’s picture

If you have a form that requires path arguments you should identify part of the path as an argument in yml routing file by using {} and it will be passed into the buildForm for you to use.