Mohit Tripathi
Mohit Tripathi

Reputation: 127

Defining variables in functions.php and access them inside functions hook in Wordpress

I am trying to understand Wordpress structure in more details. As advised to me, using global keyword is not a good idea.

Here is what I am trying to accomplish:

Inside functions.php

$affID = '12334'; //defining a variable

add_shortcode('affiliate_link', function() {
   $newLink = 'https://example.com?id=' . $affID;
   return $newLink;
}

When I run the shortcode, I only get https://example.com?id= part of it. Of course, I can pass the $affID as an argument, but I would like to set up a big list of variables that I am going to use inside different functions, and I think it's not a good idea to pass such a huge list of arguments.

Upvotes: 4

Views: 1461

Answers (1)

ArtisticPhoenix
ArtisticPhoenix

Reputation: 21671

Here are just a few Ideas. Really this is a problem of "scope" more than anything else.

USE

Simply make use of the use part of the closure:

$affID = '12334'; //defining a variable

add_shortcode('affiliate_link', function() use ($affID){
  $newLink = 'https://example.com?id=' . $affID;
  return $newLink;
});

I was actally happy when I seen the closure, this is probably the easiest way.

CLASS

Another way would be to maintain the state of it using a class instance (you could do it static if you really wanted to). This makes sense if you need a class for this functionality or the general affiliate system any way. Then you can just tack this in, with no big deal:

class foo{
     protected $affID = '12334';

     public function affiliate_link_callback(){
          $newLink = 'https://example.com?id=' . $this->affID;
          return $newLink;
     }
}

//to use a class as a call back it works like call_user_func, [obj, method]
add_shortcode('affiliate_link', [new foo, 'affiliate_link_callback']);

GLOBAL

Least desirable would be to use a global, which I personally detest and never use them (but it is a option, I suppose). Globals are bad because it can be a real challenge to find out (or track) where they were set (or modified) which makes debugging it a real chore.

global $affID;     
$affID = '12334'; //defining a variable

add_shortcode('affiliate_link', function(){
   global $affID;
   $newLink = 'https://example.com?id=' . $affID;
   return $newLink;
});

CONSTANT

You can define it as a constant, this only really makes sense if you use it a lot in other parts of your code as it makes maintaining it easier. It's not impossible you would need this ID in several places, and a constant gives you a global way to handle it. It's also conceivable that you wouldn't be modifying this at run time. It's better then a "global" because it can't be changed at runtime, so that negates the problems with keeping track of where it was changed in your code (because it cant be). Of course it has it's own set of limitations because of that. Anyway it's simple to do:

define('AFF_ID','12334'); //defining a variable

add_shortcode('affiliate_link', function(){
   global $affID;
   $newLink = 'https://example.com?id=' . AFF_ID;
   return $newLink;
});

DATABASE

And last depending on what $affID is you may be able to store it in wordpress DB. I would probably go for the user meta so it's linked to a users account. But, if it's a global value for the site, you could use the the options setting stuff instead (I would have to look that up though, example). Don't quote me on the code for this one as I forget exactly what get_user_meta returns, but I know you should almost always return a single value (the third arg should be true)

add_shortcode('affiliate_link', function(){
   $meta = get_user_meta(get_current_user_id(), 'affiliate_id', true);
   $newLink = 'https://example.com?id=' . $meta['affiliate_id'];
   return $newLink;
});

Of course in this last example you have to save the data at some point, but I am sure you can figure that out.

SHORTCODE ATTR

I think you mentioned this in the question, but you can send it as part of the shortcode too:

add_shortcode('affiliate_link', function($attr){
    extract(shortcode_atts( array(
        'id' => false,
    ), $atts, 'affiliate_link' ));

   if(!$affiliate_id) return '';

   $newLink = 'https://example.com?id='.$id;
   return $newLink;
});

I used extract above, which is a fun little function PHP has. I wouldn't recommend it for everything as it can pollute your variables and there are some security concerns.

http://php.net/manual/en/function.extract.php

Import variables from an array into the current symbol table.

Checks each key to see whether it has a valid variable name. It also checks for collisions with existing variables in the symbol table. Warning

Do not use extract() on untrusted data, like user input (e.g. $_GET, $_FILES).

Basically it takes ['id'=>'12345'] and makes a variable named $id that has 12345 as it's value (in this example). You don't have to use it, and I generally avoid it. But I thought it would be fun to use in this example.

Other Thoughts

One additional thought is that I would return the link in it's entirety instead of just the href. So instead of doing this

 <a href="[affiliate_link]">Link</a>

You would do this:

 [affiliate_link]Link[/affiliate_link]


 //  [affiliate_link id="12345" ]Link[/affiliate_link]

The main reason is in the first case, if your shortcode fails it will leave a useless link on the page. A user won't be able to tell this unless they pay close attention to the actual link destination. However, if you generate teh entire link and it fails, nothing gets put on the page. This also works nice for users that don't have an affiliate id (if you use the user meta example, and it's linked to that). In this case nothing would show for the link if they don't have the affiliate Id, but if they do the link would show. As I mentioned if you put the link in the post and then they didn't have it, you would still get a link, but with an empty destination (hope that makes sense).

If you do that then I would add the content in as well, for the link text. Using the last example (above):

add_shortcode('affiliate_link', function($attr, $content=''){
    extract(shortcode_atts( array(
        'id' => false,
    ), $atts, 'affiliate_link' ));

   if(!$affiliate_id) return '';

   $newLink = '<a href="https://example.com?id='.$id.'">'.$content.'</a>';
   return $newLink;
});

 //this shortcode
//[affiliate_link id="12345" ]Link[/affiliate_link]

 //generates this link
//<a href="https://example.com?id=123345">Link</a>

That said, I have no idea if this can be used only in links, images etc. etc. So I just wanted to add that for the sake of completeness.

Really it depends how you use it, how "static" the ID is. Is it site specific, user specific, can it change dynamically etc... ?

Sorry this was so long, I just recently wrote 4 wordpress plugins that add simple shortcodes ... lol. So I was just recently thinking about them. And I really love shortcodes.

Hope that helps.

Upvotes: 4

Related Questions