I'm using the Cart66 Wordpress plugin, and I'm trying to include a variable in a shortcode, you can see the code below:
$price = do_shortcode('[add_to_cart item="test-item" showprice="only" text=""]').' test';
echo do_shortcode('[add_to_cart item="test-item" showprice="no" quantity="1" text="'.$price.'" ]');
I've done some googling, and apparently this is the right way to include variables in Wordpress shortcodes, but this doesn't seem to work for me, Cart66 just falls back and uses the default "Add to Cart" text instead of the text defined in the shortcode above.
Can anyone see where I'm going wrong here?
As you have googled to add text in the shortcode is correct but not fully correct.
You have used "do_shortcode()" function which is used to replace the shortcode functionality and display its functionality in frontend. But, if you want to add a parameter in a shortcode and make it working you need to change the shortcode functionality a bit.
You have to find shortcode in your files containing the shortcode's functionality:
Find code something like below:
add_shortcode('add_to_cart','function_name');
function function_name($atts)
{
$atts //-- will be used to add parameters as you needed
}
You can use PHP's Output Buffering control
PS: do_shortcode() does not natively echo the output; whatever is bound on that action may echo by itself as well, which is when you either (A) edit the plugin, or (B) use OB.
I think there were some weird characters in the returend value that were causing issues, I used the Expression code below, and it seemed to solve my issue:
$value = substr(do_shortcode('[add_to_cart item="test-item" showprice="only" text=""]'), 0, 4).' Test';
$patterns = array();
$patterns[0] = '/"/';
$replacements = array();
$replacements[2] = ' ';
$value = preg_replace($patterns, $replacements, html_entity_decode($price, ENT_QUOTES));
echo do_shortcode('[add_to_cart item="test-item" showprice="no" quantity="1" text="'.$price.'" ]');
Needless to say this was a very ... complicated solution. I ended up using some good old SQL by utilising Wordpresses WPDB class. Turning about 7 lines of code into 2:
$priceValue = $wpdb->get_var("SELECT price FROM wp_cart66_products WHERE id = x");
echo do_shortcode('[add_to_cart item="test-item" showprice="no" quantity="1" text="£'.$priceValue.' Membership" ]');
This is a much better solution, I wouldn't recommend trying to use shortcodes for things they weren't intended to be used for.
The ‘add_shortcode’ function does not allow you to use external variables. It operates with a local scope, so any variables declared INSIDE will be recognized, but any variables OUTSIDE will not be recognized. If you want to use an external variable you will need to use global.
Using global on your external variable will pull it within scope and allow you to use it within the add_shortcode function! :)
$greeting = "hello world!"; //external variable
function run_greeting() {
global $greeting //pulls variable within scope
echo $greeting;
}
add_shortcode( 'greeting_shortcode', 'run_greeting' );
Related
I am building a website using php. I would want to separate the php from the html. Smarty engine, I guess does that, but right now its too complicated for me. Looking for a quick fix and easy to learn solution, one which is an accepted standard as well. Anyone helping please.
Consider frameworks or choose a template engine
Use a framework. Depending on your project, either a micro framework like Slim or something more complete like Laravel.
What I sometimes do when writing complex systems with quite much php code is separating it the following way (don't know your exact project, but it might work for you):
You create a php file with all the functions and variables you need. Then, you load every wepgage through the index.php file using .htaccess (so that a user actually always loads the index.php with a query string). Now, you can load the html page using file_get_contents (or similar) into a variable (I call this $body now); this variable can be modified using preg_replace.
An example: In the html file, you write {title} instead of <title>Sometext</title>
The replacement replaces {title} with the code you actually need:
$body = str_replace('{title}', $title, $body);
When all replacements are done, simply echo $body...
Just declare a lot of variables and use them in the template:
In your application:
function renderUserInformation($user)
{
$userName = $user->userName;
$userFullName = $user->fullName;
$userAge = $user->age;
include 'user.tpl.php';
}
In user.tpl.php:
User name: <?=$username?><br>
Full name: <?=userFullName?><br>
Age: <?=$userAge?>
By putting it in a function, you can limit the scope of the variables, so you won't pollute your global scope and/or accidentally overwrite existing variables.
This way, you can just 'prepare' the information needed to display and in a separate php file, all you need to do is output those variables.
Of course, if you must, you can still add more complex PHP code to the template, but try to do it as little as possible.
In the future, you might move this 'render' function to a separate class. In a way, this class is a view (a User View, in this case), and it is one step in creating a MVC structure. (But don't worry about that for now.)
Looking for a quick fix and easy to learn solution
METHOD 1 (the laziest; yet you preserve highlighting on editors like notepad++)
<?php
// my php
echo "foo";
$a = 4;
// now close the php tag -temporary-
// to render some html in the laziest of ways
?>
<!-- my html -->
<div></div>
<?php
// continue my php code
METHOD 2 (more organized; use template files, after you passed some values on it)
<?php
// my php
$var1 = "foo";
$title = "bar";
$v = array("var1"=>"foo","title"=>"bar"); // preferrable
include("template.php");
?>
template.php
<?php
// $var1, $var2 are known, also the array.
?>
<div>
<span> <?php echo $v["title"]; ?> </span>
</div>
Personally, i prefer method 2 and im using it in my own CMS which uses lots and lots of templates and arrays of data.
Another solution is of course advanced template engines like Smarty, PHPTemplate and the likes. You need a lot of time to learn them though and personally i dont like their approach (new language style)
function renderUserInformation($user)
{
$userName = $user->userName;
$userFullName = $user->fullName;
$userAge = $user->age;
include 'user.tpl.php';
}
Ok I have an issue here which I'm finding really hard to fix. Although I'm guessing it's probably not that complicated.
I'm using wordpress and in my functions.php I have the following:
<?php
class EXAMPLE {
$this->url=rawurlencode($url);
}
function DO-SOMETHING() {
DO-SOMETHING . $this->url);
}
?>
Then I call the function in my html:
<div>
<?php $obj=new EXAMPLE("www.example.com"); echo $obj->DO-SOMETHING();?>
</div>
I need to replace ("www.example.com") with (the_permalink()).
but it doesn't work. Not sure why. I have tried a number of different ways using trial and error, but can't find a solution
Thanks
If it's just about encoding an URL, the following would do:
echo rawurlencode( get_the_permalink() );
You could also wrap that in a function:
echo myrawurlencode( get_the_permalink() );
function myrawurlencode($url){
rawurlencode( $url );
}
note: get_the_permalink() returns the URL, while the_permalink() echoes it directly by default.
If you're going to use a class, you might want to take a look at http://php.net/manual/en/language.oop5.decon.php
and http://www.php.net/manual/en/language.oop5.basic.php first.
Well like mentioned the_peramlink() displays the url using the echo statement, but you could use get_permalink($id) which returns the url. WordPress makes sure that the url returned by both functions are escaped and can be used without using the rawurlencode() function from PHP.
Unless you need to append something to the permalink you don't need this function and should be just fine with the get_permalink($id) function. You could always check the get_permalink documentation in the Wordpress codex for more information.
I'm trying to use drupal_set_title in my node.tpl.php but the text I'm setting the title to is only showing up in the $head_title variable and not the $title variable. The $title variable is still set to the node's title.
This is in Drupal 7. I've used drupal_set_title multiple times like this in Drupal 6 and it has worked perfectly.
I think the reason this isn't working is because of where you're calling it from. Drupal's templating system works by building up variables (of which $title is one) and passing them in to the template file.
By the time you get to node.tpl.php the $title variable, which is only available in the scope of that file, is already set in stone. So while calling drupal_set_title will work to change the $head_title for html.tpl.php (which is called later than node.tpl.php, it can't change the variables of the template file you're calling the code from.
Your best bet would be to put a preprocess function in your theme's template.php which sets the title before the template file is processed:
function MYTHEME_preprocess_node(&$vars) {
drupal_set_title('A new title');
}
If that still doesn't work try explicitly setting $vars['title'] = 'A new title';` in the same preprocess function.
The best option would be to write a very small custom module and implement hook_node_view() which is called way before the template file comes into the process and should always work:
function MYMODULE_node_view($node, $view_mode, $lang_code) {
drupal_set_title('A new title');
}
Clive got me pointed in the correct direction, but I couldn't get the preprocess_node to work, so I had to use preprocess_page instead. Here's the code that works:
function mycooltheme_preprocess_page(&$vars){
if (isset($vars['node']) && $vars['node']->type == 'news'){
drupal_set_title('News');
}
}
I'm having trouble with using PHP code on my pages, within my body content area. I've searched tirelessly on this site, Drupal's site, and other sites in general, so I apologize if the answer is on this site somewhere, but I can't find it and I need help.
We have a lot of info we reuse throughout our site that I'd like to store in a PHP file as variables. We do this on our site now, but I'm rewriting our whole site to use Drupal. So, for example, we sell software, and I'd like a variable for each of our product URLs for various 'add to cart' buttons on the site. I don't want to have to hardcode the product URL into each link, but rather to seta PHP variable that I can call on any drupal page.
I cannot get anything to work; I've read about several suggestions but none work. I've tried setting the variables as their own block, then calling them from within a page when I create a new page. I can echo the variables on the pages but only within the block they are inside, I cannot call them and get them to echo from other blocks or content areas. I've tried using the global keyword (as per one suggestion) but that didn't work for me.
I hope this makes sense. Other info? I'm using Drupal 6.x, I do have PHP code enabled when creating pages, I do have the PHP filter module enabled, I can get PHP code to render so I know it's working, it's just not working where I need it to be.
I should say (if it's not obvious just from reading this!) I am a Drupal newbie so if anyone can help and try to explain their suggestion as plainly as possible for me, I'd really appreciate it!
Thanks in advance.
EDIT 3/15/11
To try to explain further, I'll post some sample code. I haven't done this yet because there isn't much to show yet, and I thought it might confuse the issue even more.
So, I've made a Drupal 'page' which is for our software trial downloads. The PHP variables that I want to set are for our download links; I want to set them in one place so that if, in the future, the download link needs to change, I only have to do so in one spot. You see, we have download links on various site pages. The same is true of our 'buy now' links. Here is the page code:
<p>Try [product] free for 30 days.</p>
<!--<p>[token_custom_ewintry]</p>-->
<p><?php global $ewintry; ?>Download for Windows PC</p>
<p><?php global $emactry; ?>Download for Mac OS X</p>
<p><?php global $ebbtry; ?>Download for BlackBerry</p>
<?php
$ebbtryprint = variable_get("ebbtry", "default");
print $ebbtryprint;
?>
<p>Download for Windows Mobile</p>
<p><?php global $ipewlstorelink; ?>iPhone, iPad, iPod touch owners: Download [product] on the iTunes App Store. You'll be able to create 10 cards for free to try [product] before you buy!</p>
For this sample I've left in everything I've tried. You'll see my calls to global variables, which never worked. I have the global variables defined in a custom block that I created and placed in my 'content top' region. I learned that apparently nothing from that region is actually accesible to my page's body content, because the calls never worked.
I have a custom token that I made yesterday with the Tokens module; it never worked, but then I read on a different post that by default, tokens are available in the body content area, and I need a special filter. I've yet to find a filter, and so I am not sure this solution will ever work.
I have my call to variable_get. Now, this did work. I have variable_set defined within my template.php page. My value does print using the print call above in my code sample. However, I looked at this page this morning and I don't think that's the answer I need. Because now I'll have to call variable_get on all my pages before I can print anything, right? And that doesn't solve the problem where I wanted to only have to set everything in one place to call anywhere. I tried putting the variable_get call in my custom block, but again I can't access anything in 'content top' from my body content area. The variable_get call prints the value in 'content top' but then it will not re-print below that in the content area.
So maybe that code will help someone to help me. I am going to look in detail at CCK now, as that's the only other suggestion I haven't tried. Thanks in advance if anyone can help.
If you're trying to set a global variable, and then use it within a function/method block, you need to use the global keyword on import:
<?php
// For some reason, this sometimes gives me problems
$foo = 'test';
// So I do this instead, they are equivalent
$GLOBALS['bar'] = 'test';
echo "<p>Global <br/> foo: $foo <br/> bar: $bar</p>";
function globalTest() {
global $foo;
echo "<p>globalTest() <br/> foo: $foo <br/> bar: $bar</p>";
}
globalTest();
function globalBarTest() {
global $foo, $bar;
echo "<p>globalBarTest() <br/> foo: $foo <br/> bar: $bar</p>";
}
globalBarTest();
?>
In action: http://jfcoder.com/test/globals.php
Prints:
Global
foo: test
bar: test
globalTest()
foo: test
bar:
globalBarTest()
foo: test
bar: test
I have always gotten in the habit of setting a global variable using $GLOBALS, I never have any issues doing it this way.
I would caution, though, that setting globally scoped variables is considered harmful (or at least unnecessary), since they are so easy to accidentally overwrite somewhere else in your code (by you and/or someone else).
Your stated approach in the description sounds quite messy; you should be using a database and let Drupal abstract how you organize, set and get the data from the datastore, instead of editing your files and hardcoding some links and data into a PHP file. This is what I'm thinking reading your description, which may not be fair, but I thought I needed to mention it.
EDIT
In Drupal, you can set global variables in the default/settings.php page using variable_set(), and then use variable_get() to get the variable by name.
http://api.drupal.org/api/drupal/sites--default--default.settings.php/6
variable_set('foo','bar');
http://api.drupal.org/api/drupal/includes--theme.inc/function/template_preprocess/6
function yourtemplate_preprocess (&$variables) {
$vars['foo'] = variable_get('foo');
}
EDIT 2
Note the source for the variable_set() function:
<?php
function variable_set($name, $value) {
global $conf;
$serialized_value = serialize($value);
db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name);
if (!db_affected_rows()) {
#db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value);
}
cache_clear_all('variables', 'cache');
$conf[$name] = $value;
}
?>
EDIT
Ok, here is what you can do:
/drupal-root/htdocs/sites/settings.php
Open the settings.php file and at the bottom, set your PHP variables using the $GLOBALS global variables, as so:
$GLOBALS['test1_variable'] = 'test 1 variable';
And then in your template (with the PHP Input Format selected):
<?php
echo "<p>This is my {$GLOBALS['test1_variable']}.</p>";
?>
Or...
<p>This is my short tag <?=$GLOBALS['test1_variable'];?>.</p>
And you should see your variable printed out on the page from the template code. Note the curly braces surrounding the $GLOBALS variable.
If you want to provide additional info that should go with some nodes, you should use CCK to create a content type, that has all the additional infos. With styling inside a template, you can archive almost anything.
If CCK is not siutable (in most cases, it is exactly what you want), you need to implement a _preprocess_ function. This would look like
function yourtemplate_preprocess_page(&$variables) {
$vars['my_custom_var'] = "hello"; //anything can go here
}
Now you have a $my_custom_var in your page-template file available.
Be sure to make yourself familiar with the template system of Drupal (if you haven't already).
It sounds like you are looking for the token_filter module.
My problem is that it isn't ready (in token module) for D7 yet.
I have the following dilemma. I have a complex CMS, and this CMS is to be themed by a graphic designer. The templates are plain HTML, with several nested inclusions. I'd like to make it easier for the designer to locate the file to be modified, by looking at the HTML of the page.
What I thought in the first place was to build something stupid like this:
function customInclude($what) {
print("<!-- Including $what -->");
include($what);
print("<!-- End of $what -->");
}
but, guess what? Variables obviously come out of scope in the included file :-) I can't declare them as global or as parameters, as I don't know how they are called and how many are there.
Is there any possibility to implement some kind of "macro expansion" in PHP? An alternative way to call it: I'd like to modify each call of the modify function, in an aspect-oriented style.
I have thought about eval(), is it the only way? Will it have a big impact on performance?
I know this is an old question, but I stumbled upon it and it reminds me of something I used to do it too.
how about if you create the function using a very weird variable?
<?php
function customInclude($___what___) {
echo '<!-- Including '.$___what___.' -->';
include($what);
echo '<!-- End of '.$___what___.' -->';
}
?>
I usually suggest to add a possible variable to display those tags only when necessary, you do not want other people to know...
<?php
function __printIncludeInfo($info, $dump = false){
//print only if the URL contains the parameter ?pii
//You can modify it to print only if coming from a certain IP
if(isset($_GET['pii'])){
if($dump){
var_dump($info);
} else {
echo $info;
}
}
}
function customInclude($___what___) {
__printIncludeInfo('<!-- Including '.$___what___.' -->');
include($what);
__printIncludeInfo('<!-- End of '.$___what___.' -->');
}
?>
in this way you can use the function to print any other information that you need
Not sure if I entirely understand the question, but if you're just trying to make life easier for the designer by showing them the underlying filename of the included file, then you can probably just use this within the template files:
echo '<!-- Start of '.__FILE__.' -->';
....content...
echo '<!-- End of '.__FILE__.' -->';
__FILE__ is just one of several Magic Constants.
Also there's the get_included_files() function that returns an array of all the included files, which might be of use (you could output a list of all the included files with 'tpl' in their name for example).
This is my 100% harcoded solution to custom include problem. It's about using a global var to point the next include filename and then include my custom proxy-include-file (wich replace your custom proxy-include-function)
1 - Add this code to a global include (wherever your customInclude function is defined)
$GLOBALS['next_include'] = "";
$GLOBALS['next_include_is_once'] = false;
function next_include($include_file) {
$GLOBALS['next_include_is_once'] = false;
$GLOBALS['next_include'] = $include_file;
}
function next_include_once($include_file) {
$GLOBALS['next_include_is_once'] = true;
$GLOBALS['next_include'] = $include_file;
}
2 - Create some include proxy-include-file, by example "debug_include.php"
<?php
if(empty($GLOBALS['next_include'])) die("Includes Problem");
// Pre-include code
// ....
if($GLOBALS['next_include_is_once']) {
include_once($GLOBALS['next_include']);
} else {
include($GLOBALS['next_include']);
}
// Post-include code
// ....
$GLOBALS['next_include'] = "";
3 - Perform a search and replace in all your files: (except debug_include.php)
search: 'include((.*));' as a reg.exp
replace with: '{next_include($1);include('debug_include.php');}'
and
search: 'include_once((.*)); as a reg.exp
replace with: '{next_include_once($1);include('debug_include.php');}'
Maybe you should need another search-and-replaces if you have some non-standard includes like
include (.... include (.... include (....
I think you can find some better search-and-replace patterns, but I'm not a regular expression user so I did it the hard way.
You should definitely use objects, namespaces and MVC model. Otherwise there is no pure and clean solution to your problem. And please, don't use eval, it's evil.