# Annotations
Annotations are the tags declaring metadata for the program source code. They provide additional information about the program to the compiler and add some new traits to the classes, methods and properties.
# History
# Annotations in Java language
Historically, annotations were first introduced in Java language.1
# Example
class Flower {
public void displayInfo() {
System.out.println("I am a flower.");
}
}
class Rose extends Flower {
@Override
public void displayInfo() {
System.out.println("I am a rose.");
}
}
class Main {
public static void main(String[] args) {
Rose r1 = new Rose();
r1.displayInfo();
}
}
//output: I am a rose
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In the above example, both the superclass and subclass include the method displayInfo()
. However the method of the subclass is called during the program execution due to the @Override
annotation.
# Annotations in PHP language
There were no annotations in the PHP language before version 8.0, so the metadata was written into the DocBlock
. A DocBlock is a piece of documentation in the source code that provides information about a specific class, method or other structural elements.2
# Benefits of use
Suppose you write a validation method:
public function sth($request){
$validator = new Validator([
"name" => "required",
"family" => "required|max:20",
"phone_number" => "nullable|numeric|min:max:11"
]);
$validator->validate($request->all());
if($validator->fails()){
return redirect()->back()->withData();
}
// logic-of-program
$user = User::create($request->all());
...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
You must repeat these codes for every validation. Instead, the code becomes as belows using the annotations:
/**
* @rules(name="required", family="required|max:20", phone_number="nullable|numeric|min:max:11")
*/
public function sth($request){
// logic-of-program
$user = User::create($request->all());
...
}
2
3
4
5
6
7
8
So the annotations make the codes more concise and clean.
# Example in PHP language
<?php
/**
* @param string $myArgument
* @return void
*/
function myFunction($myArgument)
{
...
}
2
3
4
5
6
7
8
9
10
@param string $myArgument
declares that the parameter $myArgument
is of type string.
@return void
declares that the return value for this method is void, which means that no value will be returned.
# Annotations in Larammerce platform
In the Larammerce platform, a PHP annotation-parser
package is developed based on the DocBlock.3 This package helps you to write the codes in the DocBlock and then execute them. Therefore the use of DocBlock in the Larammerce platform goes beyond the annotation in the PHP language.
# Example in Larammerce platform
<?php
class ExampleClass
{
/**
* @role(super_user)
* @rules(subject="required|min:10")
*/
public function exampleMethod()
{
...
}
}
2
3
4
5
6
7
8
9
10
11
12
13
@role(super_user)
indicates that only the super_user has access to the example method. Other users will get a 403 error message.
@rules(subject="required|min:10")
indicates that the input field called subject must be a string with at least 10 characters.
# Steps to work with annotation-parser package
First, install the package:
composer require larammerce/annotation-parser
Now you have access to 2 classes in this package: ReflectiveClass
and ReflectiveMethod
.
Construct an instance object from these classes:
$reflective_class = new ReflectiveClass($class_name);
//constructs the reflective class
2
$reflective_method = new ReflectiveMethod($class_name, $function_name);
//constructs the reflective method
2
These classes provide some useful methods to interact with DocBlock:
$reflective_class->getComment();
//returns the phpdoc on top of class
2
$reflective_method->getComment();
//returns the phpdoc on top of method
2
$reflective_class->getAnnotations();
//returns a list of annotations
2
$reflective_class->hasAnnotation("specific_annotation");
//checks if an specific annotation exists
2
$reflective_class->getAnnotation(("specific_annotation"));
//returns the specific annotation with passed title
2
# Examples of the use of annotation-parser package
Assume that we have a class named TestAnnotations
with a method named handle()
into this class:
<?php
use App\Utils\Reflection\ReflectiveClass;
class TestAnnotations
{
public function handle()
{
$testAnnotationsRef = new ReflectiveClass(TestAnnotations::class);
}
}
2
3
4
5
6
7
8
9
10
11
Now put this DocBlock above the TestAnnotations class and use getComment()
to see the result:
/**
* @salam(ali="2")
*/
class TestAnnotations
{
public function handle()
{
$testAnnotationsRef = new ReflectiveClass(TestAnnotations::class);
$testAnnotationsRef->getComment();
//output:
// """
// /**\n
// * @salam(ali="2")\n
// */
// """
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
The output returns a mere comment. In order to get a processed result, use getAnnotations()
:
public function handle()
{
$testAnnotationsRef = new ReflectiveClass(TestAnnotations::class);
$testAnnotationsRef->getAnnotations();
//output:
// array:1 [
// "salam" => App\Utils\Reflection\Annotation^ {#2571
// -title: "salam"
// -properties: array:1 [
// "ali" => "2"
// ]
// }
// ]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
As you see, the comment is processed and represented in detail.
Now change the DocBloc above the class:
/**
* @salam(Ali="2", Test=3)
*/
class TestAnnotations
{
public function handle()
{
$testAnnotationsRef = new ReflectiveClass(TestAnnotations::class);
$testAnnotationsRef->getAnnotations();
//output:
// array:1 [
// "salam" => App\Utils\Reflection\Annotation^ {#2571
// -title: "salam"
// -properties: array:1 [
// "ali" => "2"
// "Test" => 3
// ]
// }
// ]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
As you see, the result is accurate. So you can write some descriptions above a class and then use them in your code.
Now make a new method called testFunction
with its related DocBlock and use hasAnnotation()
:
<?php
use App\Utils\Reflection\ReflectiveClass;
use App\Utils\Reflection\ReflectiveMethod;
class TestAnnotations
{
...
/**
* @rules(username="required", password="required|max:20")
*/
public function testFunction()
{
$testFunctionRef = new ReflectiveMethod(TestAnnotations::class, "testFunction");
$testFunctionRef->hasAnnotation("salam"); //false
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
This means that there is no annotation named salam
above the testFunction
method.
Now change the keyword:
/**
* @rules(username="required", password="required|max:20")
*/
public function testFunction()
{
...
$testFunctionRef->hasAnnotation("rules"); //true
}
2
3
4
5
6
7
8
It declares that an annotation named rules
exists above the method.
To get this annotation, use getAnnotation()
and see the result:
/**
* @rules(username="required", password="required|max:20")
*/
public function testFunction()
{
$testFunctionRef = new ReflectiveMethod(TestAnnotations::class, "testFunction");
if($testFunctionRef->hasAnnotation("rules")){
print_r($testFunctionRef->getAnnotation("rules"));
}
//output:
// App\Utils\Reflection\Annotation^ {#2575
// -title: "rules"
// -properties: array:2 [
// "username" => "required"
// "password" => "required|max:20"
// ]
// }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
The output represents the DocBlock above the testFunction
method.
You can also do mathematical calculations into the DocBlock. For example, change the DocBlock above the method and see the result:
/**
* @rules(username="required", password="required|max:".(10+12))
*/
public function testFunction()
{
$testFunctionRef = new ReflectiveMethod(TestAnnotations::class, "testFunction");
if($testFunctionRef->hasAnnotation("rules")){
print_r($testFunctionRef->getAnnotation("rules"));
}
//output:
// App\Utils\Reflection\Annotation^ {#2575
// -title: "rules"
// -properties: array:2 [
// "username" => "required"
// "password" => "required|max:22"
// ]
// }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
The output indicates that the mathematical calculation 10+12=22 is done into the DocBlock.
# Source code
To understand how the annotation-parser package works, you can refer to the github (opens new window) of this project and review the related source code.
# References
1. Annotations in the Java language. (opens new window)
2. What is a DocBlock in the PHP language? (opens new window)
3. Annotation-parser package in the Larammerce project. (opens new window)
# Video source
← CRUD/s Validation →