I'm trying to embed a personal plugin into my smarty TPL files, but I couldn't make it work...
This is my smarty plugin:
<?php
function smarty_function_alticerik($params, &$smarty) {
if (!function_exists('alticerik')) {
if (!function_exists('get_instance')) return "Can't get CI instance";
$CI= &get_instance();
}
return $CI->IceriklerMod->liste($params['where']);
}
?>
And these are my jabber wocky TPL codes:
{foreach item=alt from=alticerik|#alticerik(where="where ustid=$ustid")}
{$alt.id}
{/foreach}
I have searched and read all of the smarty help pages but I still have no idea that how can I make this codes work correctly...
I believe your issue is that functions don't get called using that Smarty syntax.
What you're doing is sort of a mix between a function and a modifier.
Modifiers change a given input - for example, lower casing a string.
{$upperCaseWord|strtolower}
Functions take named parameters and usually do a bit more work such as creating a dropdown.
{html_options options=$arrayOfOptions selected=$selectedValue}
In your case, I'm guessing that you want to use a modifier since you look to be attempting to modify a value. You can still pass options into those, but they aren't named and it gets fairly confusing quickly. However, the code might be:
{foreach item=alt from=$alticerik|#alticerik:"where ustid=$ustid"}
{$alt.id}
{/foreach}
Meanwhile your actual function looks like:
<?php
function smarty_modifier_alticerik($input, $whereString) {
// Here, $input is the same as your $alticerik variable
// and $whereString is just the string that comes after the colon.
if (!function_exists('alticerik')) {
if (!function_exists('get_instance')) return "Can't get CI instance";
$CI= &get_instance();
}
return $CI->IceriklerMod->liste($whereString);
}
?>
Note, however, that in your code, you don't end up using the value of $alticerik from your template, so it makes me wonder if you need a function instead. I can't really know for sure unless I get what the alticerik plugin is supposed to do.
For more information on functions and modifiers, see the documentation here: Smarty.net Function Documentation and here: Smarty.net Modifier Documentation.
Do you mean $CI =& get_instance(); perhaps?
and what's not working? Any errors?
Related
I'm new to Object-Oriented PHP so I'm not entirely sure what my question really is, but here's the jam:
I created a WordPress plugin that adds a bunch of metaboxes on a certain custom post type created by another plugin. In my theme I need to get all the custom meta, but it's quite a lot that needs to be gotten, and usually with certain conditionals and so forth. So, I created a bunch of helper functions to simplify it. Problem is the names of all these functions are kind of a pain, so I put them inside a class in my plugin to simplify things, and my issue is that I'm having trouble combining them. Whether that's possible or not, hopefully you can help with...
So most of the helper functions (now class methods) look something like this:
public function metabox_wrapper( $code ) {
$info = get_post_meta( ID, 'blah', true);
if ( $info ) {
code( $info );
}
}
Then in my theme file I use:
global $Other_Plugins_Global // Created by the other plugin.
$class = new Class( $Other_Plugins_Global );
$class->metabox_wrapper( function( $info ) {
?>
<div>
<?php echo $info; ?>
</div>
<?php
});
The above is currently working - it displays the blah meta from the current post if the blah metadata exists. The other plugin's global variable contains the custom post type info (and therefore the meta), so I pass that through the class instance, use a method in the class to manage all the conditionals and other complicated stuff, and then use the method in the theme file, so that the conditional stuff is pre-arranged and able to be used in the same way elsewhere in the theme.
However, here's the rub: There are situations where I want something like
if (
Do this
if (
Also do this
)
)
But this (and everything like it that I've tried) does not work:
global $Other_Plugins_Global
$class = new Class( $Other_Plugins_Global );
$class->metabox_wrapper( function( $info ) {
?>
<div>
<?php echo $info; ?>
</div>
<?php
$class->other_metabox_wrapper( function( $stuff ) {
?>
<div>
<?php echo $stuff; ?>
</div>
<?php
});
});
So my question is... is there a way I can use these wrapper functions inside of each other? I've tried setting them as static and using :: in the theme, I've tried some fancy variable gymnastics that didn't work and would've been ugly af if it had, I almost raised a demon trying to call the global variable from inside the method... so at this point I'm not even sure what to Google.
Obviously for this particular example I could just use if(){}, but the conditional logic often has multiple conditions and other semi-complicated stuff, so it'd be helpful to keep that separate and able to be used in multiple places around the theme.
I will say that if this is a dumb question and you know of a completely different and more elegant way to accomplish what I'm describing, then I'm all ears.
Many thanks for the help.
The problem lies not in the realm of OOP, but rather in the realm of functions and function scopes. You see, when you create an anonymous function it has its own scope -- the scope of variables that are accessible. In most languages, anonymous function encloses the scope it was created in, creating a closure -- meaning it can access the copies of all variables from the parent scope. In PHP it is not the case, so in order to access $class variable from within the anonymous function you should use use: $class->metabox_wrapper(function($info) use ($class) {.
Another approach would be to bind the context to anonymous function with Closure::bind():
public function metabox_wrapper($code) {
$info = get_post_meta(ID, 'blah', true);
if ($info) {
$code = Closure::bind($code, $this);
$code($info);
}
}
Then you can use $this inside the anonymous function:
$class->metabox_wrapper(function($info) {
?>
<div>
<?php echo $info; ?>
</div>
<?php
$this->other_metabox_wrapper(function($stuff) {
?>
<div>
<?php echo $stuff; ?>
</div>
<?php
});
});
But to tell you the truth I agree with #CrisanLucian. Mixing the code with HTML in such a manner is not the best way to program.
First of all you have to read some Coding Standards articles
1. https://www.tutorialspoint.com/php/php_coding_standard.htm
Try to make separation between PHP code and HTML; Using Twig instead PHP make life much easy
https://aristath.github.io/blog/using-twig-in-wordpress
When you have a more help (hooks) functions better to group them into a class, or create a Helper dir structure and create a file for each scope. (e.g: Trim strings , Resize Images create different files)
After creating Helpers try to not put HTML inside; A helper suppose to return a value ( boolean ).
e.g showCampaign() => will return True;
HTML page/ TWIG page
{{ if(showCampaign()) }}
//HTML CODE IS HERE
{{ endif }}
When you have too many if/else statements is need refactor check the link above or another example: https://carlalexander.ca/mastering-php-conditionals/
happy codding!
We got a shopsystem working with Smarty. I need to pass some Smarty variables to a PHP function and get the return.
What I know and also did so far is the following:
{$order_id|#get_order_total}
So this passes the Smarty Variable "$order_id" to a included PHP file which contains the function get_order_total($order_id) and shows me the return of this function.
Now I need to pass 3 variables to a PHP function. The function would for example look like this:
handleDebit($order, $payCode, $insertId)
Sadly i have not found the right thing so far in smarty documentation. Anyone has ever done this?
If you really need to call the function from within smarty templates, register a wrapper function as smarty-plugin:
<?php
$smarty->registerPlugin("function","handleDebit", "handleDebitSmarty");
function handleDebitSmarty($params, $smarty)
{
return handleDebit($params['order'], $params['payCode'], $params['insertId']);
}
Now you can use it as smarty tag:
{handleDebit order=$blah payCode=$blub insertId=$yeahh}
But you should consider #JonSterling s advice and try to find a way auch that a controller is doing the handleDebit-call and you only handle results/display-stuff in the template.
Before comment please read carefully... Im working on an framework like wordpress widgets and sidebars. These are predefined functions. In our framework I need to pass arguments which create dynamic function definitions. create_function() does not fulfil my requirement.
I have a situation in which I need to create dynamic functions. So, I have created an array which contain function's names. Please refer below example which describe the situation.
E.g.
$dynArr = array(
'function_one',
'function_another',
'function_another_one',
);
foreach ($dynArr as $key => $val) {
function $key() {
// FUNCTION DESCRIPTION HERE
}
}
Is there any solution to do this with PHP or using wordpress filters etc.
Maybe this will help you:
$function = function()
{
echo 'Im annonymous function';
};
$function();
PHP 5.3 required to work ;-)
The most universal way to do it is using eval():
eval('function abc() { echo "hello"; }');
abc();
Propably this is what you need to do as you mentioned wordpress. But I would suggest to go against it, it's inefficient and dangerous, and instead generate a php file instead, if the body of the functions doesn't change that often.
I'm hoping someone can point me to the right direction in this.
Lets say I store Smarty template in database. It can look like this:
{currentusername UserID="5"}
The currentusername is a custom function to get the username. All displays correctly when used in a template. But what if I wanted to get the resolved currentusername function in my php code?
Basically I would get the template from the database, resolve it through smarty and then used the currentusername further in the code.
Is that possible?
Edit so it can be better understood. I have a this piece of code:
require('smarty/libs/Smarty.class.php');
$smarty = new Smarty;
$macro = '{currentusername UserID="5"}';
$resolvedmacro = ""; // this should contain the "Jerry";
function smarty_function_currentusername($params, &$smarty){
$UserID = $params["UserID"];
if ($UserID == 5){
return "Jerry";
}
else{
return "I dont know this guy";
}
}
Can I somehow resolve the $macro through smarty so the variable $resolvedmacro would contain the correct value?
Smarty can render a string as though it was a template using the string: or eval: "resource types" - see the documentation on String Template Resources for details.
You can then use $smarty->fetch() to get the output of that "template" into a normal PHP variable:
require('smarty/libs/Smarty.class.php');
$smarty = new Smarty;
$macro = '{currentusername UserID="5"}';
$resolvedmacro = $smarty->fetch('string:' . $macro);
There is a wider question of why you want to do this, and whether Smarty is the right tool for the job - for instance, if there are a limited number of callbacks possible, it might be over-complicating things to use Smarty to resolve them rather than just storing the name of the callback and its arguments and running it through a switch statement.
Note: The string: and eval: resource types were added in Smarty 3; if for some reason you need to use Smarty 2, you will need to write or find a resource plugin to do the same job. You could also write a resource plugin for either version which fetched a particular macro from the database and rendered it in one step; the docs for Smarty 3 are here.
Kohana (and probably other frameworks) allow you get a route and echo its URL, creating routes that are easy to maintain.
Contact
Is this OK to have in the view, or should I assign it to a variable, and then pass the view the variable?
Thanks
You aren't performing logic here. This is perfectly acceptable.
Of course your view code would be a bit cleaner if you created a variable in your controller, but this really is fine IMHO.
I find such a concatenation unnecessary. It seems url::base() going to be used in every link on the site. Why not to have a method to add it automatically? Something like Route::url("contact")
And usage of such a construct in the template is OK.
You can create a function or static method for generating urls:
public static function url($routename, array $params = NULL)
{
return url::base().Route::get($routename)->uri($params);
}