I decided to rewrite an older website that I made years ago and use templating system. I decided to use Latte, as its generating PHP files, which makes it really fast compared to systems that parse tpl every time. But I was not able to figure out, how to call a function with latte and get its result.
I am used to our custom company TPL system which can call any function and even pass parameters to it just by calling {function_name.param} or use function constants with {function::param}.
Is something like this possible purely in Latte (I am not using Nette or any other framework)? I do not want to call every single function in PHP and add it to array of parameters that TPL has to its disposal. That just makes it slower (yep I know I could use ifs in there and then ifs in TPL, but that's also an useless code duplication).
I want it to be able to call a function within class that's rendering the TPL (or its parent classes OFC) and return its output when I need it (if I even do need it), so I can avoid unnecessary calls to functions when initializing parameters for TPL parsing.
I tried to google quite a lot, but I didn't find anything useful.
I should also mention, that I am not going to use any framework at all, except Latte with Tracy and Tester for automatic testing. I do not want to use Nette or Symfony 2 etc. as the site is not that big and using whole framework would just make it even more complicated than it needs to be.
Thanks.
.
Ps.: Could somebody create tag for Latte?
You can simply call any php function this way:
{? echo 'hello'}
or in newer versions of Latte:
{php echo 'hello'}
Also, you can pass instances of Nette\Utils\Html (small lib separated from framework, full of great tools even for small apps) which will be directly rendered.
Or if you want to use own class rendering output directly, simply implement __toString() function using IHtmlString interface:
class MyOwnClassRenderableByLatte implements \Latte\Runtime\IHtmlString
{
function __toString()
{
return 'Hi';
}
}
Template sample including your later questions:
{php
// You can instantiate needed classes in one synoptical block
// in the head of template file or reather instantiate them
// outside of template and pass them as template variables
$a = new ClassA();
$b = new ClassB();
}
<div>{$a->someFunction()}</div>
<div>
{* Or you can instantiate class inplace this way,
but I wouldn't recommend it. BTW: This is Latte comment.
*}
{php (new ClassC())->otherFunction()}
</div>
Try to use something like this, its same as with javascript
{some code} //is for latte expression
{ some other code} //with space after first bracket its no more latte expression
Not sure if your TPL will handle it, but you will see
If it will work, you can use more imagination and use something like
{
some fluffy code
}
Related
I am trying to figure out a big PHP Library and it isn't that well documented. I would like to know if there is a way to print out everything about the class. For example I am using the get_class_methods() function to print out the methods of that class and it prints out an area of just that class. I would like to see all the methods within the objects within that class as well. It would be nice to see the variables and everything else. This way I can print out everything and then use the browser's search to find stuff that I need. Is this possible, or is there a method out there that already does this? I'm not that well versed in PHP so if you can give me a function that would be awesome.
PHP has a built in library called Reflection that allows you to analyze classes and objects in intricate detail.
You can get all the methods in a class like so:
<?php
$class = new ReflectionClass('Apple');
$methods = $class->getMethods();
var_dump($methods);
For class properties (member variables):
<?php
$class = new ReflectionClass('Apple');
$properties = $class->getProperties();
var_dump($properties);
A good IDE will help you navigate through the code, start debugging sessions and inspect properties values in execution time.
I felt in love with PHPStorm some years ago, and still today it's my favourite IDE. It even has a Vim plugin which emulates vim =)
There is a Structure view on that IDE, which shows the, well :), code structure of a file. This means every property and method of the opened class file. There is a Project view which is like a directory browser too.
Second recommendation will be to install ack (http://www.beyondgrep.com). PHPStorm has a really efficient searching mechanism, but sometimes you just want to search the entire subdirectories of a project for a regular expression. It's a neat tool also.
My two cents. :)
I built some the following i18n function which is called several times when rendering view :
function e_($text)
{
$t = Translate::Instance();
vprintf($t->_($text), array_slice(func_get_args(), 1)); // outputs translated text
}
Currently, I get the instance of the Translate singleton Class inside the function.
I've read that dependency injection should be used instead.
But If I do use dependency injection, I will have to pass the Translate object each time into the function, right ?
This would became :
<?php e_('my text', $this->Translate);
and not simply <?php e_('my text'); ?>
Well I'd like to avoid that.
The way you use the e_ function is actually using an alias. That's fine as long as you can live with it. You don't need to use a singleton to implement an alias:
function e_($text)
{
return $GLOBALS['e_alias']->alias(func_get_args());
}
When setting up the view layer, set the dependency:
$GLOBALS['e_alias'] = $translate;
In application context, set the global variable $translate. This will allow you to move away from the singleton (which are liars), and you actually only need a global variable.
Additionally it allows you to test views with the e_ alias against different translation implementations.
The downside is that you need to manage a list of all these special global variables, like you need to maintain for the global functions like e_.
See as well this answer to the Getting $this inside function question.
True. The reason you would use dependency injection instead is so that you could swap out the translation method for any particular use of e_().
In this particular case, I'm not sure it would be worth it unless you wish to test different translation methods during testing.
One thing you could do to help a little with performance is make $t static so that Translate::Instance() is only ever called once no matter how many calls to e_() are made.
A little background: At runtime I would like to be able to inspect the currently called functions javadoc-style documentation, to determine its formal (typed) declaration. This would allow runtime type checking (for simple and complex types) by means of reflection (at a cost) during debugging and testing, something that I would find immensely helpful.
So, in php I would like for a user defined function to get called whenever any other function is about to get called. That is, if a function foo() gets called, I would like to have my callHookHandler() function called immediately before.
One solution would be to implement __call() in all user defined classes, but that is both unwieldy and doesn't include support for functions defined outside classes, so I am looking for a better solution.
This sounds a bit of a fun one so I'm going to give answering it a try.
I hope this helps you. Let me know how it goes.
So, what you are asking can be done, and here's how:
For Functions:
Get all defined functions with $function = get_defined_functions().
Loop through the $functions['user'] key and inspect each one with the ReflectionFunction class. You'll need to get:
The comment using ->getDocComment()
The arguments using ->getParameters()
Do some magic (I'll let you figure out how to parse the comment using some regular extressions and match it up with the parameter list from the reflection. Don't forget optional parameters!)
Rename the function using runkit_function_rename
Generate code in a string that checks the parameters and calls the renamed function
Generate a parameter list as a string
Create a new function with runkit_function_add using the code you generated in step #5 and the parameter list from step #6.
For Classes:
Get a list of classes with $classes = get_declared_classes();
Loop through each one and inspect it with ReflectionObject and ->getMethods() to get the methods. Make sure that the class is not internal with ->isInternal() because we can't do anything about the internal classes.
In an inner loop... go through each method using the ReflectionMethod class. Get the arguments and PHPDoc/JavaDoc comments just like you did with normal functions.
Do the same thing you did with the functions only use runkit_method_add and runkit_method_rename instead.
Downsides:
You won't be able to do the checking on internal class methods and functions (which is fine because they won't have doc comments anyway).
This is a lot of work! I left a lot of parts up to your imagination to avoid this being the length of a short book.
Please send me this or open source it and let me know when you finish, I really want to use this myself. Contact info is on my website which is in my profile ;)
Alternatively:
You can use XDebug's function trace along with reflection then analyze the results after the fact so that you don't have to dynamically edit the code. If you want to write unit-test you could even automate it.
Hope type checking makes it into future versions of PHP and wait: https://wiki.php.net/rfc/typechecking
Notes:
This class reference has a potentially useful example of parsing docComments in the comments section of the page:
http://us.php.net/manual/en/class.reflectionmethod.php
References
get_defined_functions
get_declared_classes
ReflectionFunction
ReflectionObject
ReflectionMethod
runkit
Alternative way to hook into function call is to use a trick with namespaces: Intercepting Execution of System Functions in PHP
You can also use the Go! framework to define an aspect to intercept the execution of system functions automatically.
I just want to tell you that I am newbie to OOP and it is quite hard to me, but here is my code:
class functions
{
function safe_query($string)
{
$string = mysql_escape_string(htmlspecialchars($string));
return $string;
}
}
class info
{
public $text;
function infos($value)
{
echo functions::safe_query($value);
}
}
Is there any way to make this sentence : echo functions::safe_query($value); prettier? I can use extends, than I could write echo $this->safe_query($value);, but is it a best way? Thank you.
edit: and maybe I even can to not use class functions and just make separate file of functions and include that?
Yes, just define your function outside of a class definition.
function safe_query($string){
return mysql_escape_string(htmlspecialchars($string));
}
Then call it like this
safe_query($string);
Using a functional class is perfectly fine, but it may not the best way to design your application.
For instance, you might have a generic 'string' or 'data' class with static methods like this (implementation missing, obviously):
class strfunc{
public static function truncate($string, $chars);
public static function find_prefix($array);
public static function strip_prefix($string);
public static function to_slug($string); #strtolower + preg_replace
etc.
}
The point of a class like this is to provide you with a collection of generic, algorithmic solutions that you will reuse in different parts of your application. Declaring methods like these as static obviates their functional nature, and means they aren't attached to any particular set of data.
On the other hand, some behaviors, like escaping data for a query, are more specific to a particular set of data. It would probably be more appropriate to write something like this, in that case:
class db_wrapper{
public function __construct($params); #connect to db
public function escape($string);
public function query($sql);
public function get_results();
}
In this case, you can see that all of the methods are related to a database object. You might later use this object as part of another object that needs to access the database.
The essence of OOP is to keep both the data and its relevant behavior (methods) in one place, called an object. Having behavior and data in the same place makes it easier to control data by making sure that the behavior attached to the data is the only behavior allowed to change it (this is called encapsulation).
Further, having the data and behavior in one place means that you can easily pass that object (data and behavior) around to different parts of your application, increasing code reuse. This takes the form of composition and inheritance.
If you're interested in a book, The Object-Oriented Thought Process makes for a decent read. Or you can check out the free Building Skills in Object-Oriented Design from SO's S.Lott. (Tip: PHP syntax is more similar to Java than Python.)
Functions outside a class litter the global namespace, and it's an open invitation to slide back to procedural programming. Since you're moving to the OOP mindset, functions::safe_query($value); is definitely prettier (and cleaner) than a function declared outside a class. refrain from using define() too. but having a functions class that's a mix of unrelated methods isn't the best approach either.
Is there any way to make this sentence
: echo functions::safe_query($value);
prettier?
Not really. IMO having a functions class serves no purpose, simply make it a global function (if it's not part of a more logical class, such as Database) so you can do safe_query($value); instead.
and maybe I even can to not use class
functions and just make separate file
of functions and include that?
Create files for logical blocks of code, not for what type of code it is. Don't create a file for "functions", create a file for "database related code".
Starting with OOP can be a real challenge. One of the things I did was looking at how things were done in the Zend Framework. Not only read the manual (http://www.framework.zend.com/manual/en/zend.filter.input.html, but also look at the source code. It will take some effort but it pays of.
Looking at the context of your question and the code example you posted, I would advice you to look at some basic patterns, including a simple form of MVC, and the principles they are based upon.
I'm looking to create an on-site API reference for my framework and application.
Basically, say I have a class file model.class.php:
class Model extends Object {
... code here ...
// Separates results into pages.
// Returns Paginator object.
final public function paginate($perpage = 10) {
... more code here ...
}
}
and I want to be able to generate a reference that my developers can refer to quickly in order to know which functions are available to be called. They only need to see the comments directly above each function and the declaration line. Something like this (similar to a C++ header file):
// Separates results into pages.
// Returns Paginator object.
final public function paginate($perpage = 10);
I've done some research and this answer looked pretty good (using Reflection classes), however, I'm not sure how I can keep the comments in.
Any ideas?
I want to keep the current comment formatting. Myself and the people who are working on the code hate the verbosity associated with PHPDocumentor. Not to mention a comment-rewrite of the entire project would take years, so I want to preserve just the // comments in plaintext.
Why don't you just run PHPDocumenter on the code?
PHPDoc is identical to JavaDoc, and will retain all the parameters and comments in the docblock above the function.
EDIT: Since you don't want PHPDoc, I think it would probably be easiest to write a RegEx parser to do it, since Reflection won't provide you with any surrounding comments.
PHP code to get the comment:
if(preg_match("#//(.+)$#",$line,$match)>0)
{
echo "Comment is: ".$match[1];
}
this is what phpdoc is for. you comment your code a specific way, following certain rules, and when you're done you run your code through a parser. It outputs exactly what you're looking for.